diff --git a/Rakefile b/Rakefile index ba78677..c7e5891 100644 --- a/Rakefile +++ b/Rakefile @@ -45,6 +45,8 @@ end File.open t.name, 'w' do |output| compiler_command = compiler + sources + compiler_command << '-o' + compiler_command << Pathname.new(t.name).sub_ext('.def').to_path puts puts(compiler_command * ' ') diff --git a/source/CommandLineInterface.def b/source/CommandLineInterface.def index 85be324..e4688c4 100644 --- a/source/CommandLineInterface.def +++ b/source/CommandLineInterface.def @@ -5,6 +5,7 @@ FROM Common IMPORT ShortString; TYPE CommandLine = RECORD input: ShortString; + output: ShortString; lex: BOOLEAN; parse: BOOLEAN END; diff --git a/source/CommandLineInterface.elna b/source/CommandLineInterface.elna index 193a0d1..22389dc 100644 --- a/source/CommandLineInterface.elna +++ b/source/CommandLineInterface.elna @@ -22,6 +22,7 @@ begin result^.lex := false; result^.parse := false; MemZero(ADR(result^.input), 256); + result^.output[1] := CHAR(0); while (i < Narg()) & (result <> nil) do parsed := GetArg(parameter, i); @@ -35,7 +36,20 @@ begin parsed := true; result^.parse := true end; - if parameter[1] <> '-' then + if CompareStr(parameter, '-o') = 0 then + INC(i); + + if i = Narg() then + WriteString(StdErr, 'Fatal error: expecting a file name following -o.'); + result := nil + end; + if i < Narg() then + parsed := GetArg(parameter, i); + result^.output := parameter + end; + parsed := true + end; + if (parameter[1] <> '-') & (parsed = false) then parsed := true; if Length(result^.input) > 0 then diff --git a/source/Compiler.elna b/source/Compiler.elna index a2a5fe3..f72f091 100644 --- a/source/Compiler.elna +++ b/source/Compiler.elna @@ -1,13 +1,15 @@ program; -from FIO import Close, IsNoError, File, OpenToRead, StdErr, StdOut, WriteLine, WriteString; +from FIO import Close, IsNoError, File, OpenToRead, OpenToWrite, StdErr, StdOut, WriteLine, WriteString; from SYSTEM import ADR; from M2RTS import HALT, ExitOnHalt; from Lexer import Lexer, lexer_destroy, lexer_initialize; +from Parser import Parser; from Transpiler import transpile; from CommandLineInterface import PCommandLine, parse_command_line; -from Parser import PAstModule, parse_module; +from Parser import PAstModule, parse; +from Strings import Length; var command_line: PCommandLine; @@ -16,6 +18,7 @@ proc compile_from_stream(); var lexer: Lexer; source_input: File; + source_output: File; ast_module: PAstModule; begin source_input := OpenToRead(command_line^.input); @@ -28,14 +31,30 @@ begin ExitOnHalt(2) end; + source_output := nil; + + if Length(command_line^.output) > 0 then + source_output := OpenToWrite(command_line^.output); + + if IsNoError(source_output) = false then + WriteString(StdErr, 'Fatal error: failed to create the output file "'); + WriteString(StdErr, command_line^.output); + WriteString(StdErr, '".'); + WriteLine(StdErr); + + ExitOnHalt(2) + end + end; + if IsNoError(source_input) then lexer_initialize(ADR(lexer), source_input); - ast_module := parse_module(ADR(lexer)); - transpile(ast_module, StdOut, command_line^.input); + ast_module := parse(ADR(lexer)); + transpile(ast_module, StdOut, source_output, command_line^.input); lexer_destroy(ADR(lexer)); + Close(source_output); Close(source_input) end end; diff --git a/source/Lexer.def b/source/Lexer.def index b707b50..883c604 100644 --- a/source/Lexer.def +++ b/source/Lexer.def @@ -32,7 +32,7 @@ TYPE lexerKindProc, lexerKindBegin, lexerKindEnd, - lexerKindImplementation, + lexerKindXor, lexerKindConst, lexerKindVar, lexerKindCase, @@ -48,7 +48,7 @@ TYPE lexerKindOr, lexerKindTilde, lexerKindReturn, - lexerKindDefinition, + lexerKindDefer, lexerKindRange, lexerKindLeftParen, lexerKindRightParen, diff --git a/source/Lexer.elna b/source/Lexer.elna index 8408604..8566d4c 100644 --- a/source/Lexer.elna +++ b/source/Lexer.elna @@ -355,68 +355,65 @@ begin DEC(token^.identifierKind[1], lexer^.start.iterator); MemCopy(lexer^.start.iterator, ORD(token^.identifierKind[1]), ADR(token^.identifierKind[2])); - if compare_keyword('PROGRAM', lexer^.start, lexer^.current.iterator) then + if compare_keyword('program', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindProgram end; - if compare_keyword('IMPORT', lexer^.start, lexer^.current.iterator) then + if compare_keyword('import', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindImport end; - if compare_keyword('CONST', lexer^.start, lexer^.current.iterator) then + if compare_keyword('const', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindConst end; - if compare_keyword('VAR', lexer^.start, lexer^.current.iterator) then + if compare_keyword('var', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindVar end; - if compare_keyword('IF', lexer^.start, lexer^.current.iterator) then + if compare_keyword('if', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindIf end; - if compare_keyword('THEN', lexer^.start, lexer^.current.iterator) then + if compare_keyword('then', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindThen end; - if compare_keyword('ELSIF', lexer^.start, lexer^.current.iterator) then + if compare_keyword('elsif', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindElsif end; - if compare_keyword('ELSE', lexer^.start, lexer^.current.iterator) then + if compare_keyword('else', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindElse end; - if compare_keyword('WHILE', lexer^.start, lexer^.current.iterator) then + if compare_keyword('while', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindWhile end; - if compare_keyword('DO', lexer^.start, lexer^.current.iterator) then + if compare_keyword('do', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindDo end; if compare_keyword('proc', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindProc end; - if compare_keyword('BEGIN', lexer^.start, lexer^.current.iterator) then + if compare_keyword('begin', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindBegin end; - if compare_keyword('END', lexer^.start, lexer^.current.iterator) then + if compare_keyword('end', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindEnd end; - if compare_keyword('TYPE', lexer^.start, lexer^.current.iterator) then + if compare_keyword('type', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindType end; - if compare_keyword('RECORD', lexer^.start, lexer^.current.iterator) then + if compare_keyword('record', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindRecord end; - if compare_keyword('UNION', lexer^.start, lexer^.current.iterator) then + if compare_keyword('union', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindUnion end; if compare_keyword('NIL', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindNull end; - if compare_keyword('AND', lexer^.start, lexer^.current.iterator) then - token^.kind := lexerKindAnd - end; - if compare_keyword('OR', lexer^.start, lexer^.current.iterator) then + if compare_keyword('or', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindOr end; - if compare_keyword('RETURN', lexer^.start, lexer^.current.iterator) then + if compare_keyword('return', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindReturn end; - if compare_keyword('DEFINITION', lexer^.start, lexer^.current.iterator) then - token^.kind := lexerKindDefinition + if compare_keyword('defer', lexer^.start, lexer^.current.iterator) then + token^.kind := lexerKindDefer end; if compare_keyword('TO', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindTo @@ -430,11 +427,11 @@ begin if compare_keyword('FROM', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindFrom end; - if compare_keyword('MODULE', lexer^.start, lexer^.current.iterator) then + if compare_keyword('module', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindModule end; - if compare_keyword('IMPLEMENTATION', lexer^.start, lexer^.current.iterator) then - token^.kind := lexerKindImplementation + if compare_keyword('xor', lexer^.start, lexer^.current.iterator) then + token^.kind := lexerKindXor end; if compare_keyword('POINTER', lexer^.start, lexer^.current.iterator) then token^.kind := lexerKindPointer diff --git a/source/Parser.def b/source/Parser.def index 7df325c..a766e8e 100644 --- a/source/Parser.def +++ b/source/Parser.def @@ -195,15 +195,6 @@ TYPE 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; +PROCEDURE parse(lexer: PLexer): PAstModule; END Parser. diff --git a/source/Parser.elna b/source/Parser.elna index 2f48819..d870036 100644 --- a/source/Parser.elna +++ b/source/Parser.elna @@ -1,7 +1,7 @@ module; from FIO import ReadNBytes; -from SYSTEM import TSIZE; +from SYSTEM import TSIZE, ADR; from MemUtils import MemZero; from Storage import ALLOCATE, REALLOCATE; @@ -22,7 +22,7 @@ begin return result end; -proc parse_type_fields(lexer: PLexer) -> PAstFieldDeclaration; +proc parse_type_fields(parser: PParser) -> PAstFieldDeclaration; var token: LexerToken; field_declarations: PAstFieldDeclaration; @@ -30,7 +30,7 @@ var current_field: PAstFieldDeclaration; begin ALLOCATE(field_declarations, TSIZE(AstFieldDeclaration)); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); field_count := 0; while token.kind <> lexerKindEnd do @@ -41,16 +41,16 @@ begin current_field := field_declarations; INC(current_field , TSIZE(AstFieldDeclaration) * (field_count - 1)); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); current_field^.field_name := token.identifierKind; - token := parser_lex(lexer); - current_field^.field_type := parse_type_expression(lexer); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); + current_field^.field_type := parse_type_expression(parser); + token := parser_lex(parser^.lexer); if token.kind = lexerKindSemicolon then - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end end; INC(current_field, TSIZE(AstFieldDeclaration)); @@ -59,18 +59,18 @@ begin return field_declarations end; -proc parse_record_type(lexer: PLexer) -> PAstTypeExpression; +proc parse_record_type(parser: PParser) -> PAstTypeExpression; var result: PAstTypeExpression; begin NEW(result); result^.kind := astTypeExpressionKindRecord; - result^.fields := parse_type_fields(lexer); + result^.fields := parse_type_fields(parser); return result end; -proc parse_pointer_type(lexer: PLexer) -> PAstTypeExpression; +proc parse_pointer_type(parser: PParser) -> PAstTypeExpression; var token: LexerToken; result: PAstTypeExpression; @@ -78,18 +78,18 @@ begin NEW(result); result^.kind := astTypeExpressionKindPointer; - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); if token.kind = lexerKindPointer then - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end; - token := lexer_current(lexer); - result^.target := parse_type_expression(lexer); + token := lexer_current(parser^.lexer); + result^.target := parse_type_expression(parser); return result end; -proc parse_array_type(lexer: PLexer) -> PAstTypeExpression; +proc parse_array_type(parser: PParser) -> PAstTypeExpression; var token: LexerToken; buffer: [20]CHAR; @@ -99,25 +99,25 @@ begin result^.kind := astTypeExpressionKindArray; result^.length := 0; - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); if token.kind = lexerKindArray then - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end; if token.kind <> lexerKindOf then - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); result^.length := token.integerKind; - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end; - token := parser_lex(lexer); - result^.base := parse_type_expression(lexer); + token := parser_lex(parser^.lexer); + result^.base := parse_type_expression(parser); return result end; -proc parse_enumeration_type(lexer: PLexer) -> PAstTypeExpression; +proc parse_enumeration_type(parser: PParser) -> PAstTypeExpression; var token: LexerToken; result: PAstTypeExpression; @@ -129,14 +129,14 @@ begin case_count := 1; ALLOCATE(result^.cases, TSIZE(Identifier) * 2); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); current_case := result^.cases; current_case^ := token.identifierKind; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); while token.kind = lexerKindComma do - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); INC(case_count); INC(case_count); @@ -146,7 +146,7 @@ begin INC(current_case, TSIZE(Identifier) * (case_count - 1)); current_case^ := token.identifierKind; - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end; INC(current_case, TSIZE(Identifier)); MemZero(current_case, TSIZE(Identifier)); @@ -154,12 +154,12 @@ begin return result end; -proc parse_named_type(lexer: PLexer) -> PAstTypeExpression; +proc parse_named_type(parser: PParser) -> PAstTypeExpression; var token: LexerToken; result: PAstTypeExpression; begin - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); NEW(result); result^.kind := astTypeExpressionKindNamed; @@ -168,7 +168,7 @@ begin return result end; -proc parse_procedure_type(lexer: PLexer) -> PAstTypeExpression; +proc parse_procedure_type(parser: PParser) -> PAstTypeExpression; var token: LexerToken; result: PAstTypeExpression; @@ -181,8 +181,8 @@ begin ALLOCATE(result^.parameters, 1); - token := parser_lex(lexer); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); + token := parser_lex(parser^.lexer); while token.kind <> lexerKindRightParen do INC(parameter_count); @@ -192,11 +192,11 @@ begin current_parameter := result^.parameters; INC(current_parameter, TSIZE(PAstTypeExpression) * (parameter_count - 1)); - current_parameter^ := parse_type_expression(lexer); + current_parameter^ := parse_type_expression(parser); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); if token.kind = lexerKindComma then - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end end; current_parameter := result^.parameters; @@ -206,69 +206,69 @@ begin return result end; -proc parse_type_expression(lexer: PLexer) -> PAstTypeExpression; +proc parse_type_expression(parser: PParser) -> PAstTypeExpression; var token: LexerToken; result: PAstTypeExpression; begin result := nil; - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); if token.kind = lexerKindRecord then - result := parse_record_type(lexer) + result := parse_record_type(parser) end; if token.kind = lexerKindLeftParen then - result := parse_enumeration_type(lexer) + result := parse_enumeration_type(parser) end; if (token.kind = lexerKindArray) or (token.kind = lexerKindLeftSquare) then - result := parse_array_type(lexer) + result := parse_array_type(parser) end; if token.kind = lexerKindHat then - result := parse_pointer_type(lexer) + result := parse_pointer_type(parser) end; if token.kind = lexerKindProc then - result := parse_procedure_type(lexer) + result := parse_procedure_type(parser) end; if token.kind = lexerKindIdentifier then - result := parse_named_type(lexer) + result := parse_named_type(parser) end; return result end; -proc parse_type_declaration(lexer: PLexer) -> PAstTypedDeclaration; +proc parse_type_declaration(parser: PParser) -> PAstTypedDeclaration; var token: LexerToken; result: PAstTypedDeclaration; begin - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); NEW(result); result^.identifier := token.identifierKind; - token := parser_lex(lexer); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); + token := parser_lex(parser^.lexer); - result^.type_expression := parse_type_expression(lexer); - token := parser_lex(lexer); + result^.type_expression := parse_type_expression(parser); + token := parser_lex(parser^.lexer); return result end; -proc parse_type_part(lexer: PLexer) -> PPAstTypedDeclaration; +proc parse_type_part(parser: PParser) -> PPAstTypedDeclaration; var token: LexerToken; result: PPAstTypedDeclaration; current_declaration: PPAstTypedDeclaration; declaration_count: CARDINAL; begin - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); ALLOCATE(result, TSIZE(PAstTypedDeclaration)); current_declaration := result; declaration_count := 0; if token.kind = lexerKindType then - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); while token.kind = lexerKindIdentifier do INC(declaration_count); @@ -277,8 +277,8 @@ begin current_declaration := result; INC(current_declaration, TSIZE(PAstTypedDeclaration) * (declaration_count - 1)); - current_declaration^ := parse_type_declaration(lexer); - token := parser_lex(lexer) + current_declaration^ := parse_type_declaration(parser); + token := parser_lex(parser^.lexer) end end; if declaration_count <> 0 then @@ -289,40 +289,40 @@ begin return result end; -proc parse_variable_declaration(lexer: PLexer) -> PAstVariableDeclaration; +proc parse_variable_declaration(parser: PParser) -> PAstVariableDeclaration; var token: LexerToken; result: PAstVariableDeclaration; begin NEW(result); - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); result^.variable_name := token.identifierKind; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); - token := parser_lex(lexer); - result^.variable_type := parse_type_expression(lexer); + token := parser_lex(parser^.lexer); + result^.variable_type := parse_type_expression(parser); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); return result end; -proc parse_variable_part(lexer: PLexer) -> PPAstVariableDeclaration; +proc parse_variable_part(parser: PParser) -> PPAstVariableDeclaration; var token: LexerToken; result: PPAstVariableDeclaration; current_declaration: PPAstVariableDeclaration; declaration_count: CARDINAL; begin - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); ALLOCATE(result, TSIZE(PAstVariableDeclaration)); current_declaration := result; declaration_count := 0; if token.kind = lexerKindVar then - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); while token.kind = lexerKindIdentifier do INC(declaration_count); @@ -331,8 +331,8 @@ begin current_declaration := result; INC(current_declaration, TSIZE(PAstVariableDeclaration) * (declaration_count - 1)); - current_declaration^ := parse_variable_declaration(lexer); - token := parser_lex(lexer) + current_declaration^ := parse_variable_declaration(parser); + token := parser_lex(parser^.lexer) end end; if declaration_count <> 0 then @@ -343,41 +343,41 @@ begin return result end; -proc parse_constant_declaration(lexer: PLexer) -> PAstConstantDeclaration; +proc parse_constant_declaration(parser: PParser) -> PAstConstantDeclaration; var token: LexerToken; result: PAstConstantDeclaration; begin NEW(result); - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); result^.constant_name := token.identifierKind; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); result^.constant_value := token.integerKind; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); return result end; -proc parse_constant_part(lexer: PLexer) -> PPAstConstantDeclaration; +proc parse_constant_part(parser: PParser) -> PPAstConstantDeclaration; var token: LexerToken; result: PPAstConstantDeclaration; current_declaration: PPAstConstantDeclaration; declaration_count: CARDINAL; begin - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); ALLOCATE(result, TSIZE(PAstConstantDeclaration)); current_declaration := result; declaration_count := 0; if token.kind = lexerKindConst then - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); while token.kind = lexerKindIdentifier do INC(declaration_count); @@ -386,8 +386,8 @@ begin current_declaration := result; INC(current_declaration, TSIZE(PAstConstantDeclaration) * (declaration_count - 1)); - current_declaration^ := parse_constant_declaration(lexer); - token := parser_lex(lexer) + current_declaration^ := parse_constant_declaration(parser); + token := parser_lex(parser^.lexer) end end; if declaration_count <> 0 then @@ -398,7 +398,7 @@ begin return result end; -proc parse_import_statement(lexer: PLexer) -> PAstImportStatement; +proc parse_import_statement(parser: PParser) -> PAstImportStatement; var result: PAstImportStatement; token: LexerToken; @@ -408,20 +408,20 @@ begin NEW(result); symbol_count := 1; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); result^.package := token.identifierKind; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); ALLOCATE(result^.symbols, TSIZE(Identifier) * 2); current_symbol := result^.symbols; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); current_symbol^ := token.identifierKind; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); while token.kind <> lexerKindSemicolon do - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); INC(symbol_count); REALLOCATE(result^.symbols, TSIZE(Identifier) * (symbol_count + 1)); @@ -429,24 +429,24 @@ begin INC(current_symbol, TSIZE(Identifier) * (symbol_count - 1)); current_symbol^ := token.identifierKind; - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end; INC(current_symbol, TSIZE(Identifier)); MemZero(current_symbol, TSIZE(Identifier)); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); return result end; -proc parse_import_part(lexer: PLexer) -> PPAstImportStatement; +proc parse_import_part(parser: PParser) -> PPAstImportStatement; var token: LexerToken; import_statement: PPAstImportStatement; result: PPAstImportStatement; import_count: CARDINAL; begin - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); ALLOCATE(result, TSIZE(PAstImportStatement)); import_statement := result; import_count := 0; @@ -458,8 +458,8 @@ begin import_statement := result; INC(import_statement, TSIZE(PAstImportStatement) * (import_count - 1)); - import_statement^ := parse_import_statement(lexer); - token := lexer_current(lexer) + import_statement^ := parse_import_statement(parser); + token := lexer_current(parser^.lexer) end; if import_count > 0 then INC(import_statement, TSIZE(PAstImportStatement)) @@ -469,13 +469,13 @@ begin return result end; -proc parse_literal(lexer: PLexer) -> PAstLiteral; +proc parse_literal(parser: PParser) -> PAstLiteral; var literal: PAstLiteral; token: LexerToken; begin literal := nil; - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); if token.kind = lexerKindInteger then NEW(literal); @@ -501,22 +501,22 @@ begin literal^.boolean := token.booleanKind end; if literal <> nil then - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end; return literal end; -proc parse_factor(lexer: PLexer) -> PAstExpression; +proc parse_factor(parser: PParser) -> PAstExpression; var next_token: LexerToken; result: PAstExpression; literal: PAstLiteral; begin result := nil; - next_token := lexer_current(lexer); + next_token := lexer_current(parser^.lexer); - literal := parse_literal(lexer); + literal := parse_literal(parser); if (result = nil) & (literal <> nil) then NEW(result); @@ -526,25 +526,25 @@ begin end; if (result = nil) & (next_token.kind = lexerKindMinus) then NEW(result); - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); result^.kind := astExpressionKindUnary; result^.unary_operator := astUnaryOperatorMinus; - result^.unary_operand := parse_factor(lexer) + result^.unary_operand := parse_factor(parser) end; if (result = nil) & (next_token.kind = lexerKindTilde) then NEW(result); - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); result^.kind := astExpressionKindUnary; result^.unary_operator := astUnaryOperatorNot; - result^.unary_operand := parse_factor(lexer) + result^.unary_operand := parse_factor(parser) end; if (result = nil) & (next_token.kind = lexerKindLeftParen) then - next_token := parser_lex(lexer); - result := parse_expression(lexer); + next_token := parser_lex(parser^.lexer); + result := parse_expression(parser); if result <> nil then - next_token := parser_lex(lexer) + next_token := parser_lex(parser^.lexer) end end; if (result = nil) & (next_token.kind = lexerKindIdentifier) then @@ -553,13 +553,13 @@ begin result^.kind := astExpressionKindIdentifier; result^.identifier := next_token.identifierKind; - next_token := parser_lex(lexer) + next_token := parser_lex(parser^.lexer) end; return result end; -proc parse_designator(lexer: PLexer) -> PAstExpression; +proc parse_designator(parser: PParser) -> PAstExpression; var next_token: LexerToken; inner_expression: PAstExpression; @@ -567,9 +567,9 @@ var arguments: PPAstExpression; handled: BOOLEAN; begin - designator := parse_factor(lexer); + designator := parse_factor(parser); handled := designator <> nil; - next_token := lexer_current(lexer); + next_token := lexer_current(parser^.lexer); while handled do inner_expression := designator; @@ -581,34 +581,34 @@ begin designator^.kind := astExpressionKindDereference; designator^.reference := inner_expression; - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); handled := true end; if ~handled & (next_token.kind = lexerKindLeftSquare) then NEW(designator); - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); designator^.kind := astExpressionKindArrayAccess; designator^.array := inner_expression; - designator^.index := parse_expression(lexer); + designator^.index := parse_expression(parser); - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); handled := true end; if ~handled & (next_token.kind = lexerKindDot) then NEW(designator); - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); designator^.kind := astExpressionKindFieldAccess; designator^.aggregate := inner_expression; designator^.field := next_token.identifierKind; - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); handled := true end; if ~handled & (next_token.kind = lexerKindLeftParen) then NEW(designator); - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); designator^.kind := astExpressionKindCall; designator^.callable := inner_expression; @@ -618,24 +618,24 @@ begin if next_token.kind <> lexerKindRightParen then ALLOCATE(designator^.arguments, TSIZE(PAstExpression)); designator^.argument_count := 1; - designator^.arguments^ := parse_expression(lexer); + designator^.arguments^ := parse_expression(parser); - next_token := lexer_current(lexer); + next_token := lexer_current(parser^.lexer); while next_token.kind = lexerKindComma do - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); designator^.argument_count := designator^.argument_count + 1; REALLOCATE(designator^.arguments, TSIZE(PAstExpression) * designator^.argument_count); arguments := designator^.arguments; INC(arguments, TSIZE(PAstExpression) * (designator^.argument_count - 1)); - arguments^ := parse_expression(lexer); + arguments^ := parse_expression(parser); - next_token := lexer_current(lexer) + next_token := lexer_current(parser^.lexer) end end; - next_token := parser_lex(lexer); + next_token := parser_lex(parser^.lexer); handled := true end end; @@ -643,14 +643,14 @@ begin return designator end; -proc parse_binary_expression(lexer: PLexer, left: PAstExpression, operator: AstBinaryOperator) -> PAstExpression; +proc parse_binary_expression(parser: PParser, left: PAstExpression, operator: AstBinaryOperator) -> PAstExpression; var next_token: LexerToken; result: PAstExpression; right: PAstExpression; begin - next_token := parser_lex(lexer); - right := parse_designator(lexer); + next_token := parser_lex(parser^.lexer); + right := parse_designator(parser); result := nil; if right <> nil then @@ -664,50 +664,50 @@ begin return result end; -proc parse_expression(lexer: PLexer) -> PAstExpression; +proc parse_expression(parser: PParser) -> PAstExpression; var next_token: LexerToken; left: PAstExpression; result: PAstExpression; written_bytes: CARDINAL; begin - left := parse_designator(lexer); + left := parse_designator(parser); result := nil; - next_token := lexer_current(lexer); + next_token := lexer_current(parser^.lexer); if left <> nil then if (result = nil) & (next_token.kind = lexerKindNotEqual) then - result := parse_binary_expression(lexer, left, astBinaryOperatorNotEquals) + result := parse_binary_expression(parser, left, astBinaryOperatorNotEquals) end; if (result = nil) & (next_token.kind = lexerKindEqual) then - result := parse_binary_expression(lexer, left, astBinaryOperatorEquals) + result := parse_binary_expression(parser, left, astBinaryOperatorEquals) end; if (result = nil) & (next_token.kind = lexerKindGreaterThan) then - result := parse_binary_expression(lexer, left, astBinaryOperatorGreater) + result := parse_binary_expression(parser, left, astBinaryOperatorGreater) end; if (result = nil) & (next_token.kind = lexerKindLessThan) then - result := parse_binary_expression(lexer, left, astBinaryOperatorLess) + result := parse_binary_expression(parser, left, astBinaryOperatorLess) end; if (result = nil) & (next_token.kind = lexerKindGreaterEqual) then - result := parse_binary_expression(lexer, left, astBinaryOperatorGreaterEqual) + result := parse_binary_expression(parser, left, astBinaryOperatorGreaterEqual) end; if (result = nil) & (next_token.kind = lexerKindLessEqual) then - result := parse_binary_expression(lexer, left, astBinaryOperatorLessEqual) + result := parse_binary_expression(parser, left, astBinaryOperatorLessEqual) end; if (result = nil) & (next_token.kind = lexerKindAnd) then - result := parse_binary_expression(lexer, left, astBinaryOperatorConjunction) + result := parse_binary_expression(parser, left, astBinaryOperatorConjunction) end; if (result = nil) & (next_token.kind = lexerKindOr) then - result := parse_binary_expression(lexer, left, astBinaryOperatorDisjunction) + result := parse_binary_expression(parser, left, astBinaryOperatorDisjunction) end; if (result = nil) & (next_token.kind = lexerKindMinus) then - result := parse_binary_expression(lexer, left, astBinaryOperatorSubtraction) + result := parse_binary_expression(parser, left, astBinaryOperatorSubtraction) end; if (result = nil) & (next_token.kind = lexerKindPlus) then - result := parse_binary_expression(lexer, left, astBinaryOperatorSum) + result := parse_binary_expression(parser, left, astBinaryOperatorSum) end; if (result = nil) & (next_token.kind = lexerKindAsterisk) then - result := parse_binary_expression(lexer, left, astBinaryOperatorMultiplication) + result := parse_binary_expression(parser, left, astBinaryOperatorMultiplication) end end; if (result = nil) & (left <> nil) then @@ -717,7 +717,7 @@ begin return result end; -proc parse_return_statement(lexer: PLexer) -> PAstStatement; +proc parse_return_statement(parser: PParser) -> PAstStatement; var token: LexerToken; result: PAstStatement; @@ -725,13 +725,13 @@ begin NEW(result); result^.kind := astStatementKindReturn; - token := parser_lex(lexer); - result^.returned := parse_expression(lexer); + token := parser_lex(parser^.lexer); + result^.returned := parse_expression(parser); return result end; -proc parse_assignment_statement(lexer: PLexer, assignee: PAstExpression) -> PAstStatement; +proc parse_assignment_statement(parser: PParser, assignee: PAstExpression) -> PAstStatement; var token: LexerToken; result: PAstStatement; @@ -740,13 +740,13 @@ begin result^.kind := astStatementKindAssignment; result^.assignee := assignee; - token := parser_lex(lexer); - result^.assignment := parse_expression(lexer); + token := parser_lex(parser^.lexer); + result^.assignment := parse_expression(parser); return result end; -proc parse_call_statement(lexer: PLexer, call: PAstExpression) -> PAstStatement; +proc parse_call_statement(parser: PParser, call: PAstExpression) -> PAstStatement; var result: PAstStatement; begin @@ -757,7 +757,7 @@ begin return result end; -proc parse_compound_statement(lexer: PLexer) -> AstCompoundStatement; +proc parse_compound_statement(parser: PParser) -> AstCompoundStatement; var result: AstCompoundStatement; token: LexerToken; @@ -767,7 +767,7 @@ begin result.count := 0; result.statements := nil; - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); while token.kind <> lexerKindEnd do old_count := result.count; @@ -777,47 +777,47 @@ begin current_statement := result.statements; INC(current_statement, TSIZE(PAstStatement) * old_count); - current_statement^ := parse_statement(lexer); + current_statement^ := parse_statement(parser); - token := lexer_current(lexer) + token := lexer_current(parser^.lexer) end; return result end; -proc parse_statement(lexer: PLexer) -> PAstStatement; +proc parse_statement(parser: PParser) -> PAstStatement; var token: LexerToken; statement: PAstStatement; designator: PAstExpression; begin statement := nil; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); if token.kind = lexerKindIf then - statement := parse_if_statement(lexer) + statement := parse_if_statement(parser) end; if token.kind = lexerKindWhile then - statement := parse_while_statement(lexer) + statement := parse_while_statement(parser) end; if token.kind = lexerKindReturn then - statement := parse_return_statement(lexer) + statement := parse_return_statement(parser) end; if token.kind = lexerKindIdentifier then - designator := parse_designator(lexer); - token := lexer_current(lexer); + designator := parse_designator(parser); + token := lexer_current(parser^.lexer); if token.kind = lexerKindAssignment then - statement := parse_assignment_statement(lexer, designator) + statement := parse_assignment_statement(parser, designator) end; if token.kind <> lexerKindAssignment then - statement := parse_call_statement(lexer, designator) + statement := parse_call_statement(parser, designator) end end; return statement end; -proc parse_if_statement(lexer: PLexer) -> PAstStatement; +proc parse_if_statement(parser: PParser) -> PAstStatement; var token: LexerToken; result: PAstStatement; @@ -825,15 +825,15 @@ begin NEW(result); result^.kind := astStatementKindIf; - token := parser_lex(lexer); - result^.if_condition := parse_expression(lexer); - result^.if_branch := parse_compound_statement(lexer); + token := parser_lex(parser^.lexer); + result^.if_condition := parse_expression(parser); + result^.if_branch := parse_compound_statement(parser); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); return result end; -proc parse_while_statement(lexer: PLexer) -> PAstStatement; +proc parse_while_statement(parser: PParser) -> PAstStatement; var token: LexerToken; result: PAstStatement; @@ -841,31 +841,31 @@ begin NEW(result); result^.kind := astStatementKindWhile; - token := parser_lex(lexer); - result^.while_condition := parse_expression(lexer); - result^.while_body := parse_compound_statement(lexer); + token := parser_lex(parser^.lexer); + result^.while_condition := parse_expression(parser); + result^.while_body := parse_compound_statement(parser); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); return result end; -proc parse_statement_part(lexer: PLexer) -> AstCompoundStatement; +proc parse_statement_part(parser: PParser) -> AstCompoundStatement; var token: LexerToken; compound: AstCompoundStatement; begin compound.count := 0; compound.statements := nil; - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); if token.kind = lexerKindBegin then - compound := parse_compound_statement(lexer) + compound := parse_compound_statement(parser) end; return compound end; -proc parse_procedure_heading(lexer: PLexer) -> PAstProcedureDeclaration; +proc parse_procedure_heading(parser: PParser) -> PAstProcedureDeclaration; var token: LexerToken; declaration: PAstProcedureDeclaration; @@ -874,15 +874,15 @@ var begin NEW(declaration); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); declaration^.name := token.identifierKind; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); declaration^.parameters := nil; declaration^.parameter_count := 0; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); while token.kind <> lexerKindRightParen do parameter_index := declaration^.parameter_count; INC(declaration^.parameter_count); @@ -893,48 +893,48 @@ begin current_parameter^.identifier := token.identifierKind; - token := parser_lex(lexer); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); + token := parser_lex(parser^.lexer); - current_parameter^.type_expression := parse_type_expression(lexer); + current_parameter^.type_expression := parse_type_expression(parser); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); if token.kind = lexerKindComma then - token := parser_lex(lexer) + token := parser_lex(parser^.lexer) end end; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); declaration^.return_type := nil; (* Check for the return type and write it. *) if token.kind = lexerKindArrow then - token := parser_lex(lexer); - declaration^.return_type := parse_type_expression(lexer); - token := parser_lex(lexer) + token := parser_lex(parser^.lexer); + declaration^.return_type := parse_type_expression(parser); + token := parser_lex(parser^.lexer) end; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); return declaration end; -proc parse_procedure_declaration(lexer: PLexer) -> PAstProcedureDeclaration; +proc parse_procedure_declaration(parser: PParser) -> PAstProcedureDeclaration; var token: LexerToken; declaration: PAstProcedureDeclaration; begin - declaration := parse_procedure_heading(lexer); + declaration := parse_procedure_heading(parser); - declaration^.constants := parse_constant_part(lexer); - declaration^.variables := parse_variable_part(lexer); - declaration^.statements := parse_statement_part(lexer); + declaration^.constants := parse_constant_part(parser); + declaration^.variables := parse_variable_part(parser); + declaration^.statements := parse_statement_part(parser); - token := parser_lex(lexer); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); + token := parser_lex(parser^.lexer); return declaration end; -proc parse_procedure_part(lexer: PLexer) -> PPAstProcedureDeclaration; +proc parse_procedure_part(parser: PParser) -> PPAstProcedureDeclaration; var token: LexerToken; current_declaration: PPAstProcedureDeclaration; @@ -942,7 +942,7 @@ var declaration_count: CARDINAL; declaration_index: CARDINAL; begin - token := lexer_current(lexer); + token := lexer_current(parser^.lexer); declaration_count := 0; declaration_index := 0; @@ -954,8 +954,8 @@ begin current_declaration := result; INC(current_declaration, TSIZE(PAstProcedureDeclaration) * declaration_index); - current_declaration^ := parse_procedure_declaration(lexer); - token := lexer_current(lexer); + current_declaration^ := parse_procedure_declaration(parser); + token := lexer_current(parser^.lexer); declaration_index := declaration_count end; current_declaration := result; @@ -965,35 +965,44 @@ begin return result end; -proc parse_module(lexer: PLexer) -> PAstModule; +proc parse_module(parser: PParser) -> PAstModule; var token: LexerToken; result: PAstModule; begin NEW(result); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); result^.main := true; if token.kind = lexerKindModule then result^.main := false end; - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); (* Write the module body. *) - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); - result^.imports := parse_import_part(lexer); - result^.constants := parse_constant_part(lexer); - result^.types := parse_type_part(lexer); + result^.imports := parse_import_part(parser); + result^.constants := parse_constant_part(parser); + result^.types := parse_type_part(parser); - result^.variables := parse_variable_part(lexer); - result^.procedures := parse_procedure_part(lexer); - result^.statements := parse_statement_part(lexer); + result^.variables := parse_variable_part(parser); + result^.procedures := parse_procedure_part(parser); + result^.statements := parse_statement_part(parser); - token := parser_lex(lexer); - token := parser_lex(lexer); + token := parser_lex(parser^.lexer); + token := parser_lex(parser^.lexer); return result end; +proc parse(lexer: PLexer) -> PAstModule; +var + parser: Parser; +begin + parser.lexer := lexer; + + return parse_module(ADR(parser)) +end; + end. diff --git a/source/Transpiler.def b/source/Transpiler.def index 98956fc..5f8c219 100644 --- a/source/Transpiler.def +++ b/source/Transpiler.def @@ -10,10 +10,11 @@ TYPE TranspilerContext = RECORD input_name: ShortString; output: File; + definition: File; indentation: CARDINAL END; PTranspilerContext = POINTER TO TranspilerContext; -PROCEDURE transpile(ast_module: PAstModule; output: File; input_name: ShortString); +PROCEDURE transpile(ast_module: PAstModule; output: File; definition: File; input_name: ShortString); END Transpiler. diff --git a/source/Transpiler.elna b/source/Transpiler.elna index 3b3d2d7..44b3e10 100644 --- a/source/Transpiler.elna +++ b/source/Transpiler.elna @@ -643,12 +643,13 @@ begin end end; -proc transpile(ast_module: PAstModule, output: File, input_name: ShortString); +proc transpile(ast_module: PAstModule, output: File, definition: File, input_name: ShortString); var context: TranspilerContext; begin context.input_name := input_name; context.output := output; + context.definition := definition; context.indentation := 0; transpile_module(ADR(context), ast_module)