diff --git a/source/Parser.def b/source/Parser.def index 3fcec3f..7cc47ce 100644 --- a/source/Parser.def +++ b/source/Parser.def @@ -46,6 +46,8 @@ TYPE PPAstTypeDeclaration = POINTER TO PAstTypeDeclaration; AstVariableDeclaration = RECORD + variable_name: Identifier; + variable_type: PAstTypeExpression END; PAstVariableDeclaration = POINTER TO AstVariableDeclaration; PPAstVariableDeclaration = POINTER TO PAstVariableDeclaration; @@ -58,7 +60,7 @@ TYPE PAstModule = POINTER TO AstModule; PROCEDURE parse_type_expression(lexer: PLexer): PAstTypeExpression; -PROCEDURE parse_type_declaration(lexer: PLexer): PAstTypeDeclaration; PROCEDURE parse_type_part(lexer: PLexer): PPAstTypeDeclaration; +PROCEDURE parse_variable_part(lexer: PLexer): PPAstVariableDeclaration; END Parser. diff --git a/source/Parser.mod b/source/Parser.mod index 333085f..ab96df2 100644 --- a/source/Parser.mod +++ b/source/Parser.mod @@ -272,4 +272,56 @@ BEGIN RETURN result END parse_type_part; +PROCEDURE parse_variable_declaration(lexer: PLexer): PAstVariableDeclaration; +VAR + token: LexerToken; + result: PAstVariableDeclaration; +BEGIN + ALLOCATE(result, TSIZE(AstVariableDeclaration)); + + token := lexer_current(lexer); + result^.variable_name := token.identifierKind; + + token := transpiler_lex(lexer); + + token := transpiler_lex(lexer); + result^.variable_type := parse_type_expression(lexer); + + token := transpiler_lex(lexer); + RETURN result +END parse_variable_declaration; +PROCEDURE parse_variable_part(lexer: PLexer): PPAstVariableDeclaration; +VAR + token: LexerToken; + result: PPAstVariableDeclaration; + current_declaration: PPAstVariableDeclaration; + declaration_count: CARDINAL; +BEGIN + token := lexer_current(lexer); + + ALLOCATE(result, TSIZE(PAstVariableDeclaration)); + current_declaration := result; + declaration_count := 0; + + IF token.kind = lexerKindVar THEN + token := transpiler_lex(lexer); + + WHILE token.kind = lexerKindIdentifier DO + INC(declaration_count); + + REALLOCATE(result, TSIZE(PAstVariableDeclaration) * (declaration_count + 1)); + current_declaration := result; + INC(current_declaration, TSIZE(PAstVariableDeclaration) * (declaration_count - 1)); + + current_declaration^ := parse_variable_declaration(lexer); + token := transpiler_lex(lexer) + END + END; + IF declaration_count <> 0 THEN + INC(current_declaration, TSIZE(PAstVariableDeclaration)) + END; + current_declaration^ := NIL; + + RETURN result +END parse_variable_part; END Parser. diff --git a/source/Transpiler.mod b/source/Transpiler.mod index 9817250..dd29e0d 100644 --- a/source/Transpiler.mod +++ b/source/Transpiler.mod @@ -12,9 +12,9 @@ FROM Lexer IMPORT Lexer, LexerToken, lexer_current, lexer_lex, LexerKind; FROM Parser IMPORT AstModule, PAstModule, AstTypeExpressionKind, AstConstantDeclaration, PPAstConstantDeclaration, AstTypeDeclaration, PAstTypeDeclaration, PPAstTypeDeclaration, - AstVariableDeclaration, PPAstVariableDeclaration, - PAstTypeExpression, AstTypeExpression, PPAstTypeExpression, AstFieldDeclaration, PAstFieldDeclaration, - parse_type_expression, parse_type_declaration, parse_type_part; + PAstVariableDeclaration, PPAstVariableDeclaration, + PAstTypeExpression, PPAstTypeExpression, AstFieldDeclaration, PAstFieldDeclaration, + parse_type_expression, parse_variable_part, parse_type_part; (* Calls lexer_lex() but skips the comments. *) PROCEDURE transpiler_lex(lexer: PLexer): LexerToken; @@ -131,7 +131,9 @@ BEGIN WriteString(context^.output, 'MODULE '); (* Write the module name and end the line with a semicolon and newline. *) - token := transpiler_lex(context^.lexer); + IF token.kind <> lexerKindProgram THEN + token := transpiler_lex(context^.lexer); + END; transpile_module_name(context); token := transpiler_lex(context^.lexer); @@ -145,7 +147,9 @@ BEGIN result^.constants := transpile_constant_part(context); result^.types := parse_type_part(context^.lexer); transpile_type_part(context, result^.types); - result^.variables := transpile_variable_part(context); + + result^.variables := parse_variable_part(context^.lexer); + transpile_variable_part(context, result^.variables); transpile_procedure_part(context); transpile_statement_part(context); @@ -316,40 +320,34 @@ BEGIN WriteLine(context^.output) END END transpile_type_part; -PROCEDURE transpile_variable_declaration(context: PTranspilerContext); +PROCEDURE transpile_variable_declaration(context: PTranspilerContext; declaration: PAstVariableDeclaration); VAR - token: LexerToken; - type_expression: PAstTypeExpression; + written_bytes: CARDINAL; BEGIN WriteString(context^.output, ' '); - token := lexer_current(context^.lexer); - write_current(context^.lexer, context^.output); + written_bytes := WriteNBytes(context^.output, ORD(declaration^.variable_name[1]), ADR(declaration^.variable_name[2])); - token := transpiler_lex(context^.lexer); WriteString(context^.output, ': '); - token := transpiler_lex(context^.lexer); - type_expression := parse_type_expression(context^.lexer); - transpile_type_expression(context, type_expression); - token := transpiler_lex(context^.lexer); + + transpile_type_expression(context, declaration^.variable_type); write_semicolon(context^.output) END transpile_variable_declaration; -PROCEDURE transpile_variable_part(context: PTranspilerContext): PPAstVariableDeclaration; +PROCEDURE transpile_variable_part(context: PTranspilerContext; declarations: PPAstVariableDeclaration); VAR - token: LexerToken; + current_declaration: PPAstVariableDeclaration; BEGIN - token := lexer_current(context^.lexer); - - IF token.kind = lexerKindVar THEN + IF declarations^ <> NIL THEN WriteString(context^.output, 'VAR'); WriteLine(context^.output); - token := transpiler_lex(context^.lexer); - WHILE token.kind = lexerKindIdentifier DO - transpile_variable_declaration(context); - token := transpiler_lex(context^.lexer) - END - END; - RETURN NIL + current_declaration := declarations; + WHILE current_declaration^ <> NIL DO + transpile_variable_declaration(context, current_declaration^); + + INC(current_declaration, TSIZE(PAstVariableDeclaration)) + END; + WriteLine(context^.output) + END END transpile_variable_part; PROCEDURE transpile_procedure_heading(context: PTranspilerContext): LexerToken; VAR @@ -593,7 +591,9 @@ VAR BEGIN token := transpile_procedure_heading(context); seen_constants := transpile_constant_part(context); - seen_variables := transpile_variable_part(context); + + seen_variables := parse_variable_part(context^.lexer); + transpile_variable_part(context, seen_variables); transpile_statement_part(context); WriteString(context^.output, 'END ');