DEFINITION MODULE Parser; FROM Common IMPORT Identifier, PIdentifier, ShortString; FROM Lexer IMPORT PLexer; TYPE Parser = RECORD lexer: PLexer END; PParser = POINTER TO Parser; AstLiteralKind = ( astLiteralKindInteger, astLiteralKindString, astLiteralKindNull, astLiteralKindBoolean ); AstLiteral = RECORD CASE kind: AstLiteralKind OF astLiteralKindInteger: integer: INTEGER | astLiteralKindString: string: ShortString | astLiteralKindNull: | astLiteralKindBoolean: boolean: BOOLEAN END END; PAstLiteral = POINTER TO AstLiteral; AstUnaryOperator = ( astUnaryOperatorReference, astUnaryOperatorNot, astUnaryOperatorMinus ); AstBinaryOperator = ( astBinaryOperatorSum, astBinaryOperatorSubtraction, astBinaryOperatorMultiplication, astBinaryOperatorDivision, astBinaryOperatorRemainder, astBinaryOperatorEquals, astBinaryOperatorNotEquals, astBinaryOperatorLess, astBinaryOperatorGreater, astBinaryOperatorLessEqual, astBinaryOperatorGreaterEqual, astBinaryOperatorDisjunction, astBinaryOperatorConjunction, astBinaryOperatorExclusiveDisjunction, astBinaryOperatorShiftLeft, astBinaryOperatorShiftRight ); AstExpressionKind = ( astExpressionKindLiteral, astExpressionKindIdentifier, astExpressionKindArrayAccess, astExpressionKindDereference, astExpressionKindFieldAccess, astExpressionKindUnary, astExpressionKindBinary, astExpressionKindCall ); AstExpression = RECORD CASE kind: AstExpressionKind OF astExpressionKindLiteral: literal: PAstLiteral | astExpressionKindIdentifier: identifier: Identifier | astExpressionKindDereference: reference: PAstExpression | astExpressionKindArrayAccess: array: PAstExpression; index: PAstExpression | astExpressionKindFieldAccess: aggregate: PAstExpression; field: Identifier | astExpressionKindUnary: unary_operator: AstUnaryOperator; unary_operand: PAstExpression | astExpressionKindBinary: binary_operator: AstBinaryOperator; lhs: PAstExpression; rhs: PAstExpression | astExpressionKindCall: callable: PAstExpression; argument_count: CARDINAL; arguments: PPAstExpression END END; PAstExpression = POINTER TO AstExpression; PPAstExpression = POINTER TO PAstExpression; AstStatementKind = ( astStatementKindIf, astStatementKindWhile, astStatementKindAssignment, astStatementKindReturn, astStatementKindCall ); AstStatement = RECORD CASE kind: AstStatementKind OF astStatementKindIf: if_condition: PAstExpression; if_branch: AstCompoundStatement | astStatementKindWhile: while_condition: PAstExpression; while_body: AstCompoundStatement | astStatementKindAssignment: assignee: PAstExpression; assignment: PAstExpression | astStatementKindReturn: returned: PAstExpression | astStatementKindCall: call: PAstExpression END END; PAstStatement = POINTER TO AstStatement; PPAstStatement = POINTER TO PAstStatement; AstCompoundStatement = RECORD count: CARDINAL; statements: PPAstStatement END; AstImportStatement = RECORD package: Identifier; symbols: PIdentifier END; PAstImportStatement = POINTER TO AstImportStatement; PPAstImportStatement = POINTER TO PAstImportStatement; AstConstantDeclaration = RECORD constant_name: Identifier; constant_value: INTEGER END; PAstConstantDeclaration = POINTER TO AstConstantDeclaration; PPAstConstantDeclaration = POINTER TO PAstConstantDeclaration; AstFieldDeclaration = RECORD field_name: Identifier; field_type: PAstTypeExpression END; PAstFieldDeclaration = POINTER TO AstFieldDeclaration; AstTypeExpressionKind = ( astTypeExpressionKindNamed, astTypeExpressionKindRecord, astTypeExpressionKindEnumeration, astTypeExpressionKindArray, astTypeExpressionKindPointer, astTypeExpressionKindProcedure ); AstTypeExpression = RECORD CASE kind: AstTypeExpressionKind OF astTypeExpressionKindNamed: name: Identifier | astTypeExpressionKindEnumeration: cases: PIdentifier | astTypeExpressionKindPointer: target: PAstTypeExpression | astTypeExpressionKindRecord: fields: PAstFieldDeclaration | astTypeExpressionKindArray: base: PAstTypeExpression; length: CARDINAL | astTypeExpressionKindProcedure: parameters: PPAstTypeExpression END END; PAstTypeExpression = POINTER TO AstTypeExpression; PPAstTypeExpression = POINTER TO PAstTypeExpression; AstTypedDeclaration = RECORD identifier: Identifier; type_expression: PAstTypeExpression END; PAstTypedDeclaration = POINTER TO AstTypedDeclaration; PPAstTypedDeclaration = POINTER TO PAstTypedDeclaration; AstVariableDeclaration = RECORD variable_name: Identifier; variable_type: PAstTypeExpression END; PAstVariableDeclaration = POINTER TO AstVariableDeclaration; PPAstVariableDeclaration = POINTER TO PAstVariableDeclaration; AstProcedureDeclaration = RECORD name: Identifier; parameter_count: CARDINAL; parameters: PAstTypedDeclaration; return_type: PAstTypeExpression; constants: PPAstConstantDeclaration; variables: PPAstVariableDeclaration; statements: AstCompoundStatement END; PAstProcedureDeclaration = POINTER TO AstProcedureDeclaration; PPAstProcedureDeclaration = POINTER TO PAstProcedureDeclaration; AstModule = RECORD main: BOOLEAN; imports: PPAstImportStatement; constants: PPAstConstantDeclaration; types: PPAstTypedDeclaration; variables: PPAstVariableDeclaration; procedures: PPAstProcedureDeclaration; statements: AstCompoundStatement END; PAstModule = POINTER TO AstModule; PROCEDURE parse_type_expression(lexer: PLexer): PAstTypeExpression; PROCEDURE parse_type_part(lexer: PLexer): PPAstTypedDeclaration; PROCEDURE parse_variable_part(lexer: PLexer): PPAstVariableDeclaration; PROCEDURE parse_constant_part(lexer: PLexer): PPAstConstantDeclaration; PROCEDURE parse_import_part(lexer: PLexer): PPAstImportStatement; PROCEDURE parse_designator(lexer: PLexer): PAstExpression; PROCEDURE parse_expression(lexer: PLexer): PAstExpression; PROCEDURE parse_statement_part(lexer: PLexer): AstCompoundStatement; PROCEDURE parse_procedure_part(lexer: PLexer): PPAstProcedureDeclaration; PROCEDURE parse_module(lexer: PLexer): PAstModule; END Parser.