diff --git a/Rakefile b/Rakefile index df61126..07d73a4 100644 --- a/Rakefile +++ b/Rakefile @@ -101,6 +101,7 @@ task :backport do source = File.read source_path current_procedure = nil target = '' + module_name = source_path.basename.sub_ext('') source .gsub(/^(var|type|const|begin)/) { |match| match.upcase } @@ -109,7 +110,8 @@ task :backport do .gsub(/proc\(/, 'PROCEDURE(') .gsub(/ & /, ' AND ') .gsub(/ -> /, ': ') - .gsub(/end\./, "END #{source_path.basename.sub_ext('')}.") + .gsub(/program;/, "MODULE #{module_name};") + .gsub(/end\./, "END #{module_name}.") .gsub(/([[:space:]]*)end(;?)$/, '\1END\2') .gsub(/^([[:space:]]*)(while|return|if)\b/) { |match| match.upcase } .gsub(/^from ([[:alnum:]]+) import/, 'FROM \1 IMPORT') diff --git a/source/Compiler.elna b/source/Compiler.elna index 494e4b4..61aff50 100644 --- a/source/Compiler.elna +++ b/source/Compiler.elna @@ -1,4 +1,4 @@ -module Compiler; +program; from FIO import Close, IsNoError, File, OpenToRead, StdErr, StdOut, WriteLine, WriteString; from SYSTEM import ADR; 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.elna b/source/Parser.elna index 9e56180..53a31e4 100644 --- a/source/Parser.elna +++ b/source/Parser.elna @@ -283,4 +283,58 @@ begin return result end; +proc 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; + +proc 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; + end. diff --git a/source/Transpiler.elna b/source/Transpiler.elna index fb8e340..e4a2795 100644 --- a/source/Transpiler.elna +++ b/source/Transpiler.elna @@ -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. *) proc transpiler_lex(lexer: PLexer) -> LexerToken; @@ -138,7 +138,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); @@ -152,7 +154,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); @@ -334,41 +338,35 @@ begin end end; -proc transpile_variable_declaration(context: PTranspilerContext); +proc 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; -proc transpile_variable_part(context: PTranspilerContext) -> PPAstVariableDeclaration; +proc 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; proc transpile_procedure_heading(context: PTranspilerContext) -> LexerToken; @@ -624,7 +622,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 ');