DEFINITION MODULE Parser;

FROM Common IMPORT Identifier, PIdentifier;
FROM Lexer IMPORT PLexer;

TYPE
  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;

  AstTypeDeclaration = RECORD
    identifier: Identifier;
    type_expression: PAstTypeExpression
  END;
  PAstTypeDeclaration = POINTER TO AstTypeDeclaration;
  PPAstTypeDeclaration = POINTER TO PAstTypeDeclaration;

  AstVariableDeclaration = RECORD
    variable_name: Identifier;
    variable_type: PAstTypeExpression
  END;
  PAstVariableDeclaration = POINTER TO AstVariableDeclaration;
  PPAstVariableDeclaration = POINTER TO PAstVariableDeclaration;

  AstModule = RECORD
    imports: PPAstImportStatement;
    constants: PPAstConstantDeclaration;
    types: PPAstTypeDeclaration;
    variables: PPAstVariableDeclaration
  END;
  PAstModule = POINTER TO AstModule;

PROCEDURE parse_type_expression(lexer: PLexer): PAstTypeExpression;
PROCEDURE parse_type_part(lexer: PLexer): PPAstTypeDeclaration;
PROCEDURE parse_variable_part(lexer: PLexer): PPAstVariableDeclaration;
PROCEDURE parse_constant_part(lexer: PLexer): PPAstConstantDeclaration;
PROCEDURE parse_import_part(lexer: PLexer): PPAstImportStatement;

END Parser.
