From dd663f51bf8680f87d24569d01e2d86ed308304d Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 24 Jun 2026 00:03:14 +0200 Subject: Add source code position to AST nodes --- boot/stage24/cl.elna | 318 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 214 insertions(+), 104 deletions(-) (limited to 'boot/stage24') diff --git a/boot/stage24/cl.elna b/boot/stage24/cl.elna index 8b64551..da99621 100644 --- a/boot/stage24/cl.elna +++ b/boot/stage24/cl.elna @@ -115,57 +115,69 @@ type _cast ) ElnaTreeNode = record - kind: ElnaTreeKind + kind: ElnaTreeKind; + position: ElnaPosition end ElnaTreeTypeExpression = record - kind: ElnaTreeKind + kind: ElnaTreeKind; + position: ElnaPosition end ElnaTreeExpression = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType end ElnaTreeIntegerLiteral = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; value: Word end ElnaTreeCharacterLiteral = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; value: Char end ElnaTreeNilLiteral = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType end ElnaTreeBooleanLiteral = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; value: Bool end ElnaTreeStringLiteral = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; value: String end ElnaTreeVariableExpression = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; name: String end ElnaTreeCastExpression = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; expression: ^ElnaTreeExpression; type_expression: ^ElnaTreeTypeExpression end ElnaTreeDereferenceExpression = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; pointer: Word end ElnaTreeBinaryExpression = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; lhs: ^ElnaTreeExpression; rhs: ^ElnaTreeExpression; @@ -173,6 +185,7 @@ type end ElnaTreeUnaryExpression = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; operand: ^ElnaTreeExpression; operator: Word @@ -184,6 +197,7 @@ type *) ElnaTreeStatement = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeStatement end (** @@ -197,39 +211,46 @@ type end ElnaTreeIfStatement = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeStatement; conditionals: ^ElnaTreeConditionalStatements; _else: ^ElnaTreeStatement end ElnaTreeGotoStatement = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeStatement; label: String end ElnaTreeAssignStatement = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeStatement; assignee: Word; assignment: ^ElnaTreeExpression end ElnaTreeReturnStatement = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeStatement; returned: ^ElnaTreeExpression end ElnaTreeLabelDeclaration = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeStatement; label: String end ElnaTreeFieldAccessExpression = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; aggregate: Word; field: String end ElnaTreeArrayAccessExpression = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; array: Word; index: ^ElnaTreeExpression @@ -240,6 +261,7 @@ type end ElnaTreeEnumerationTypeExpression = record kind: ElnaTreeKind; + position: ElnaPosition; members: ^ElnaTreeEnumeration; length: Word end @@ -250,40 +272,48 @@ type end ElnaTreeRecordTypeExpression = record kind: ElnaTreeKind; + position: ElnaPosition; members: ^ElnaTreeField; length: Word end ElnaTreeNamedTypeExpression = record kind: ElnaTreeKind; + position: ElnaPosition; name: String end ElnaTreePointerTypeExpression = record kind: ElnaTreeKind; + position: ElnaPosition; base: ^ElnaTreeTypeExpression end ElnaTreeArrayTypeExpression = record kind: ElnaTreeKind; + position: ElnaPosition; base: ^ElnaTreeTypeExpression; length: ^ElnaTreeExpression end ElnaTreeTraitExpression = record kind: ElnaTreeKind; + position: ElnaPosition; name: String; argument: ^ElnaTreeTypeExpression end ElnaTreeDeclaration = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeDeclaration; name: String end ElnaTreeVariableDeclaration = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeDeclaration; name: String; type_expression: ^ElnaTreeTypeExpression end ElnaTreeProcedureDeclaration = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeDeclaration; name: String; body: ^ElnaTreeStatement; @@ -294,6 +324,7 @@ type end ElnaTreeModuleDeclaration = record kind: ElnaTreeKind; + position: ElnaPosition; types: ^ElnaTreeDeclaration; globals: ^ElnaTreeVariableDeclaration; procedures: ^ElnaTreeProcedureDeclaration; @@ -301,6 +332,7 @@ type end ElnaTreeTypeDeclaration = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeDeclaration; name: String; type_expression: ^ElnaTreeTypeExpression @@ -311,6 +343,7 @@ type end ElnaTreeCall = record kind: ElnaTreeKind; + position: ElnaPosition; type_decoration: ^ElnaType; callee: ^ElnaTreeVariableExpression; arguments: ^ElnaTreeExpressionList; @@ -318,6 +351,7 @@ type end ElnaTreeCallStatement = record kind: ElnaTreeKind; + position: ElnaPosition; next: ^ElnaTreeStatement; call: ^ElnaTreeCall end @@ -507,7 +541,7 @@ type add_ptr, nop ) - ElnaTacKind = (list, label, constant, variable) + ElnaTacKind = (list, label, constant, variable, ignore) (* - If value is a variable or label, length is its name length. @@ -658,7 +692,7 @@ type allocated: Bool end - ElnaErrorKind = (unexpected_token) + ElnaErrorKind = (unexpected_token, undefined_symbol) ElnaError = record next: ^ElnaListNode; kind: ElnaErrorKind; @@ -672,6 +706,12 @@ type possibilities: Word; got: ElnaLexerKind end + ElnaErrorUndefinedSymbol = record + next: ^ElnaListNode; + kind: ElnaErrorKind; + position: ElnaPosition; + symbol_name: String + end var symbol_table_global: ^ElnaSymbolTable @@ -711,13 +751,13 @@ extern proc free(ptr: Pointer) extern -proc memcpy(dst: Pointer, src: Pointer, n: Word) +proc memcpy(dst: Pointer, src: Pointer, n: Word) -> Pointer extern -proc memcmp(s1: Pointer, s2: Pointer, n: Word) +proc memcmp(s1: Pointer, s2: Pointer, n: Word) -> Int extern -proc memset(b: Pointer, c: Int, len: Word) +proc memset(b: Pointer, c: Int, len: Word) -> Pointer extern proc strlen(s: ^Char) -> Word @@ -735,6 +775,9 @@ extern proc atoi(str: ^Char) -> Int extern +proc exit(status: Int) +extern + proc free_and_nil(pointer: Pointer) -> Pointer begin free(pointer); @@ -956,7 +999,7 @@ begin return result end -proc elna_rtl_instruction_set_operand(this: ^ElnaRtlInstruction, n: Word, operand_type: Word, +proc elna_rtl_instruction_set_operand(this: ^ElnaRtlInstruction, n: Word, operand_type: ElnaRtlKind, operand_value: Word, operand_length: Word, operand_offset: Word) begin this^.operands[n].kind := operand_type; @@ -1276,37 +1319,39 @@ begin tac_instruction^.operands[1].value, tac_instruction^.operands[1].length, 0); elna_list_append(instructions, instruction); - pseudo_symbol := elna_symbol_table_lookup(variable_map, tac_instruction^.operands[3].value, tac_instruction^.operands[3].length); + if tac_instruction^.operands[3].kind = ElnaTacKind.variable then + pseudo_symbol := elna_symbol_table_lookup(variable_map, tac_instruction^.operands[3].value, tac_instruction^.operands[3].length); - if pseudo_symbol^.rtl_type^.kind = ElnaRtlTypeKind.byte_array then - target_operand.kind := ElnaRtlKind.register; - target_operand.value := ElnaRtlRegister.t0; - target_operand.length := 0; - target_operand.offset := 0; - long_word_type := elna_rtl_constant_type(4); + if pseudo_symbol^.rtl_type^.kind = ElnaRtlTypeKind.byte_array then + target_operand.kind := ElnaRtlKind.register; + target_operand.value := ElnaRtlRegister.t0; + target_operand.length := 0; + target_operand.offset := 0; + long_word_type := elna_rtl_constant_type(4); - instruction := elna_rtl_variable_address(variable_map, pseudo_symbol, @tac_instruction^.operands[3], @target_operand); - elna_list_append(instructions, instruction); + instruction := elna_rtl_variable_address(variable_map, pseudo_symbol, @tac_instruction^.operands[3], @target_operand); + elna_list_append(instructions, instruction); - instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a0, 0, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, - target_operand.value, target_operand.length, 0); - instruction^.types[1] := long_word_type; - elna_list_append(instructions, instruction); + instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a0, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + target_operand.value, target_operand.length, 0); + instruction^.types[1] := long_word_type; + elna_list_append(instructions, instruction); - instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); - elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a1, 0, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, - target_operand.value, target_operand.length, 4); - instruction^.types[1] := long_word_type; - elna_list_append(instructions, instruction) - else - instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv); - elna_rtl_instruction_set_operand(instruction, 1, tac_instruction^.operands[3].kind, - tac_instruction^.operands[3].value, tac_instruction^.operands[3].length, 0); - elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.a0, 0, 0); - elna_list_append(instructions, instruction) + instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.a1, 0, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.memory, + target_operand.value, target_operand.length, 4); + instruction^.types[1] := long_word_type; + elna_list_append(instructions, instruction) + else + instruction := elna_rtl_instruction_create(ElnaRtlOperator.mv); + elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.pseudo, + tac_instruction^.operands[3].value, tac_instruction^.operands[3].length, 0); + elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.register, ElnaRtlRegister.a0, 0, 0); + elna_list_append(instructions, instruction) + end end end @@ -2403,6 +2448,7 @@ begin result^.kind := ElnaTreeKind.integer_literal; result^.value := atoi(buffer); result^.type_decoration := nil; + result^.position := token^.position; free(buffer); @@ -2411,28 +2457,31 @@ end proc elna_parser_boolean_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeBooleanLiteral var + token: ^ElnaLexerToken result: ^ElnaTreeBooleanLiteral begin + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeBooleanLiteral)); result^.kind := ElnaTreeKind.boolean_literal; - result^.value := string_compare(cursor^.start, 4, "true"); + result^.value := string_compare(token^.start.ptr, 4, "true"); result^.type_decoration := nil; - - elna_lexer_read(cursor); + result^.position := token^.position; return result end proc elna_parser_nil_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNilLiteral var + token: ^ElnaLexerToken result: ^ElnaTreeNilLiteral begin - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeNilLiteral)); result^.kind := ElnaTreeKind.null; result^.type_decoration := nil; + result^.position := token^.position; return result end @@ -2441,14 +2490,17 @@ proc elna_tac_integer_literal(integer_literal_node: ^ElnaTreeIntegerLiteral, ope begin operand^.kind := ElnaTacKind.constant; operand^.value := integer_literal_node^.value; - operand^.length := 4 + operand^.length := word_type^.size end proc elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral, operand: ^ElnaTacOperand) +var + current_position: Word begin operand^.kind := ElnaTacKind.constant; - operand^.value := boolean_literal_node^.value; - operand^.length := 1 + current_position := boolean_literal_node^.value; + operand^.value := current_position; + operand^.length := bool_type^.size end proc elna_tac_nil_literal(nil_node: Word, operand: ^ElnaTacOperand) @@ -2517,7 +2569,7 @@ begin result^.kind := ElnaTreeKind.character_literal; elna_parser_escape(token^.start.ptr + 1, @result^.value); - + result^.position := token^.position; result^.type_decoration := nil; return result @@ -2530,7 +2582,7 @@ begin operand^.kind := ElnaTacKind.constant; current_position := character_literal_node^.value; operand^.value := current_position; - operand^.length := 1 + operand^.length := char_type^.size end proc elna_parser_variable_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeVariableExpression @@ -2543,6 +2595,7 @@ begin result^.kind := ElnaTreeKind.variable_expression; result^.name := token^.start; + result^.position := token^.position; result^.type_decoration := nil; return result @@ -2583,6 +2636,7 @@ begin goto elna_parser_escape_loop end; result^.value.length := target_position - result^.value.ptr; + result^.position := token^.position; result^.type_decoration := nil; return result @@ -2623,7 +2677,6 @@ begin elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, 4, 4); elna_list_append(instructions, instruction) - end proc elna_parser_trait_expression(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeTraitExpression @@ -2636,6 +2689,7 @@ begin token := elna_lexer_read(cursor); result^.name := token^.start; + result^.position := token^.position; if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) <> nil then result^.argument := elna_parser_type_expression(cursor, error_list); @@ -2660,12 +2714,13 @@ begin result := nil; (* Skip the cast keyword and opening paren. *) - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) = nil then goto elna_parser_cast_expression_end end; result := malloc(#size(ElnaTreeCastExpression)); result^.kind := ElnaTreeKind._cast; + result^.position.start_location := token^.position.start_location; result^.type_decoration := nil; result^.expression := elna_parser_binary_expression(cursor, error_list); @@ -2682,9 +2737,13 @@ begin result := free_and_nil(result); goto elna_parser_cast_expression_end end; - if elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list) = nil then - result := free_and_nil(result) + token := elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list); + if token = nil then + result := free_and_nil(result); + goto elna_parser_cast_expression_end end; + result^.position.end_location := token^.position.end_location; + .elna_parser_cast_expression_end; return result end @@ -2722,13 +2781,15 @@ proc elna_parser_dereference_expression(cursor: ^ElnaLexerCursor, simple_expression: ^ElnaTreeExpression) -> ^ElnaTreeDereferenceExpression var result: ^ElnaTreeDereferenceExpression + token: ^ElnaLexerToken begin + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeDereferenceExpression)); result^.kind := ElnaTreeKind.dereference_expression; result^.pointer := simple_expression; result^.type_decoration := nil; - elna_lexer_read(cursor); + result^.position := token^.position; return result end @@ -2840,6 +2901,7 @@ begin result^.kind := ElnaTreeKind.unary_expression; result^.operand := operand; result^.operator := operator; + result^.position := token^.position; result^.type_decoration := nil end end; @@ -2993,6 +3055,7 @@ begin result^.lhs := lhs_node; result^.rhs := rhs_node; result^.operator := token^.kind; + result^.position := token^.position; result^.type_decoration := nil elsif elna_list_empty(error_list) then result := lhs_node @@ -3131,12 +3194,13 @@ begin result^.count := 0; result^.callee := callee; - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); + result^.position.start_location := token^.position.start_location; token := elna_lexer_peek(cursor); if token^.kind = ElnaLexerKind.right_paren then - elna_lexer_read(cursor); - goto elna_parser_call_end + token := elna_lexer_read(cursor); + goto elna_parser_call_close end; .elna_parser_call_loop; @@ -3159,16 +3223,20 @@ begin elna_lexer_read(cursor); goto elna_parser_call_loop elsif token^.kind = ElnaLexerKind.right_paren then - elna_lexer_read(cursor) + token := elna_lexer_read(cursor) else parser_error := elna_error_unexpected_token_create(cursor, 2); parser_error^.expected[1] := ElnaLexerKind.comma; parser_error^.expected[2] := ElnaLexerKind.right_paren; elna_list_append(error_list, parser_error); - result := free_and_nil(result) + result := free_and_nil(result); + goto elna_parser_call_end end end; + .elna_parser_call_close; + result^.position.end_location := token^.position.end_location; + .elna_parser_call_end; return result end @@ -3186,20 +3254,17 @@ begin arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand)); procedure_info := elna_symbol_table_lookup(symbol_table, parsed_expression^.name.ptr, parsed_expression^.name.length); - (* TODO: procedure_info should never be nil. *) - if procedure_info = nil then - elna_tac_make_variable(operand, symbol_table, word_type) - elsif procedure_info^.procedure_type^.return_type = nil then - elna_tac_make_variable(operand, symbol_table, word_type) - else - elna_tac_make_variable(operand, symbol_table, procedure_info^.procedure_type^.return_type) - end; - call_instruction := elna_tac_instruction_create(ElnaTacOperator.proc_call); elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.label, parsed_expression^.name.ptr, parsed_expression^.name.length); elna_tac_instruction_set_operand(call_instruction, 2, ElnaTacKind.list, arguments_operand, parsed_call^.count); - elna_tac_instruction_set_operand(call_instruction, 3, operand^.kind, operand^.value, operand^.length); + + if procedure_info^.procedure_type^.return_type = nil then + elna_tac_instruction_set_operand(call_instruction, 3, ElnaTacKind.ignore, 0, 0) + else + elna_tac_make_variable(operand, symbol_table, procedure_info^.procedure_type^.return_type); + elna_tac_instruction_set_operand(call_instruction, 3, operand^.kind, operand^.value, operand^.length) + end; argument_entry := parsed_call^.arguments; .elna_tac_call_loop; @@ -3220,15 +3285,20 @@ var token: ^ElnaLexerToken begin (* Skip the goto. *) - elna_lexer_read(cursor); - token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); + token := elna_lexer_read(cursor); + result := malloc(#size(ElnaTreeGotoStatement)); + result^.kind := ElnaTreeKind.goto_statement; + result^.next := nil; + result^.position.start_location := token^.position.start_location; + token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); if token <> nil then - result := malloc(#size(ElnaTreeGotoStatement)); - result^.kind := ElnaTreeKind.goto_statement; - result^.next := nil; - result^.label := token^.start + result^.label := token^.start; + result^.position.end_location := token^.position.end_location + else + result := free_and_nil(result) end; + return result end @@ -3254,14 +3324,18 @@ var result: ^ElnaTreeLabelDeclaration token: ^ElnaLexerToken begin - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); + result := malloc(#size(ElnaTreeLabelDeclaration)); + result^.kind := ElnaTreeKind.label_declaration; + result^.next := nil; + result^.position.start_location := token^.position.start_location; + token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); if token <> nil then - result := malloc(#size(ElnaTreeLabelDeclaration)); - - result^.kind := ElnaTreeKind.label_declaration; - result^.next := nil; - result^.label := token^.start + result^.label := token^.start; + result^.position.end_location := token^.position.end_location + else + result := free_and_nil(result) end; return result end @@ -3328,15 +3402,18 @@ var token: ^ElnaLexerToken begin (* Skip dot. Read the enumeration value. *) - elna_lexer_read(cursor); token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeFieldAccessExpression)); - result^.kind := ElnaTreeKind.field_access_expression; result^.type_decoration := nil; result^.aggregate := aggregate; + result^.position.start_location := token^.position.start_location; + + token := elna_lexer_read(cursor); + result^.field := token^.start; + result^.position.end_location := token^.position.end_location; return result end @@ -3345,21 +3422,27 @@ proc elna_parser_array_access_expression(cursor: ^ElnaLexerCursor, array: ^ElnaTreeExpression, error_list: ^ElnaList) -> ^ElnaTreeArrayAccessExpression var result: ^ElnaTreeArrayAccessExpression + token: ^ElnaLexerToken begin - elna_lexer_read(cursor); - + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeArrayAccessExpression)); result^.kind := ElnaTreeKind.array_access_expression; result^.type_decoration := nil; result^.array := array; + result^.position.start_location := token^.position.start_location; + result^.index := elna_parser_binary_expression(cursor, error_list); if result^.index = nil then result := free_and_nil(result) - elsif elna_parser_expect(cursor, ElnaLexerKind.right_square, error_list) = nil then - result := free_and_nil(result) + else + token := elna_parser_expect(cursor, ElnaLexerKind.right_square, error_list); + if token = nil then + result := free_and_nil(result) + else + result^.position.end_location := token^.position.end_location + end end; - return result end @@ -3513,6 +3596,7 @@ end proc elna_parser_assign_statement(cursor: ^ElnaLexerCursor, assignee: ^ElnaTreeNode, error_list: ^ElnaList) -> ^ElnaTreeAssignStatement var + token: ^ElnaLexerToken result: ^ElnaTreeAssignStatement begin result := malloc(#size(ElnaTreeAssignStatement)); @@ -3523,8 +3607,10 @@ begin result^.assignment := nil; (* Skip the assignment sign (:=) with surrounding whitespaces. *) - if elna_parser_expect(cursor, ElnaLexerKind.assignment, error_list) <> nil then - result^.assignment := elna_parser_binary_expression(cursor, error_list); + token := elna_parser_expect(cursor, ElnaLexerKind.assignment, error_list); + if token <> nil then + result^.position := token^.position; + result^.assignment := elna_parser_binary_expression(cursor, error_list) end; if result^.assignment = nil then result := free_and_nil(result) @@ -3567,14 +3653,16 @@ end proc elna_parser_return_statement(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeReturnStatement var + token: ^ElnaLexerToken result: ^ElnaTreeReturnStatement begin (* Skip "return" keyword. *) - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeReturnStatement)); result^.kind := ElnaTreeKind.return_statement; result^.next := nil; + result^.position := token^.position; result^.returned := elna_parser_binary_expression(cursor, error_list); if result^.returned = nil then result := free_and_nil(result) @@ -3657,9 +3745,11 @@ var next_conditional: ^ElnaTreeConditionalStatements token: ^ElnaLexerToken begin + token := elna_lexer_peek(cursor); result := malloc(#size(ElnaTreeIfStatement)); result^.kind := ElnaTreeKind.if_statement; + result^.position := token^.position; result^.next := nil; previous_conditional := elna_parser_conditional_statements(cursor, error_list, ElnaLexerKind._then); @@ -3713,6 +3803,7 @@ begin call_result^.kind := ElnaTreeKind.call_statement; call_result^.next := nil; call_result^.call := designator; + call_result^.position := designator^.position; result := call_result end end @@ -3836,12 +3927,13 @@ var token: ^ElnaLexerToken parser_error: ^ElnaErrorUnexpectedToken begin - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeRecordTypeExpression)); result^.kind := ElnaTreeKind.record_type_expression; result^.members := nil; result^.length := 0; + result^.position := token^.position; .elna_parser_record_type_expression_loop; token := elna_lexer_read(cursor); @@ -3903,12 +3995,13 @@ var token: ^ElnaLexerToken parser_error: ^ElnaErrorUnexpectedToken begin - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeEnumerationTypeExpression)); result^.kind := ElnaTreeKind.enumeration_type_expression; result^.members := nil; result^.length := 0; + result^.position.start_location := token^.position.start_location; .elna_parser_enumeration_type_expression_loop; token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); @@ -3931,7 +4024,8 @@ begin elna_lexer_read(cursor); goto elna_parser_enumeration_type_expression_loop elsif token^.kind = ElnaLexerKind.right_paren then - elna_lexer_read(cursor) + token := elna_lexer_read(cursor); + result^.position.end_location := token^.position.end_location else parser_error := elna_error_unexpected_token_create(cursor, 2); parser_error^.expected[1] := ElnaLexerKind.comma; @@ -4055,6 +4149,7 @@ begin result^.kind := ElnaTreeKind.named_type_expression; result^.name := token^.start; + result^.position := token^.position; return result end @@ -4062,12 +4157,15 @@ end proc elna_parser_pointer_type_expression(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreePointerTypeExpression var result: ^ElnaTreePointerTypeExpression + token: ^ElnaLexerToken begin - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreePointerTypeExpression)); result^.kind := ElnaTreeKind.pointer_type_expression; result^.base := elna_parser_type_expression(cursor, error_list); + result^.position := token^.position; + if result^.base = nil then result := free_and_nil(result) end; @@ -4078,22 +4176,28 @@ end proc elna_parser_array_type_expression(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeArrayTypeExpression var result: ^ElnaTreeArrayTypeExpression + token: ^ElnaLexerToken begin - elna_lexer_read(cursor); + token := elna_lexer_read(cursor); result := malloc(#size(ElnaTreeArrayTypeExpression)); result^.kind := ElnaTreeKind.array_type_expression; + result^.position.start_location := token^.position.start_location; result^.length := elna_parser_binary_expression(cursor, error_list); if result^.length = nil then result := free_and_nil(result) else - if elna_parser_expect(cursor, ElnaLexerKind.right_square, error_list) = nil then + token := elna_parser_expect(cursor, ElnaLexerKind.right_square, error_list); + + if token = nil then result := free_and_nil(result) else result^.base := elna_parser_type_expression(cursor, error_list); if result^.base = nil then result := free_and_nil(result) + else + result^.position.end_location := token^.position.end_location end end end; @@ -4301,18 +4405,18 @@ var token: ^ElnaLexerToken begin (* Skip "proc ". *) - elna_lexer_read(cursor); - result := nil; + token := elna_lexer_read(cursor); + result := malloc(#size(ElnaTreeProcedureDeclaration)); + result^.kind := ElnaTreeKind.procedure_declaration; + result^.next := nil; + result^.position := token^.position; (* Skip procedure name. *) token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); if token = nil then + result := free_and_nil(result); goto elna_parser_procedure_declaration_end end; - - result := malloc(#size(ElnaTreeProcedureDeclaration)); - result^.kind := ElnaTreeKind.procedure_declaration; - result^.next := nil; result^.name := token^.start; if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) = nil then @@ -4500,7 +4604,7 @@ begin end (* Returns whether the provided type is array or record. *) -proc elna_type_is_aggregate(_type: ^ElnaType) +proc elna_type_is_aggregate(_type: ^ElnaType) -> Bool var lhs: Word rhs: Word @@ -4782,6 +4886,7 @@ begin result^.kind := ElnaTreeKind.type_declaration; result^.next := nil; result^.name := token^.start; + result^.position := token^.position; if elna_parser_expect(cursor, ElnaLexerKind.equals, error_list) <> nil then result^.type_expression := elna_parser_type_expression(cursor, error_list) @@ -4869,7 +4974,8 @@ begin result^.kind := ElnaTreeKind.variable_declaration; result^.next := nil; result^.name := token^.start; - result^.type_expression := variable_type + result^.type_expression := variable_type; + result^.position := token^.position end end end; @@ -5016,6 +5122,10 @@ begin result := malloc(#size(ElnaTreeModuleDeclaration)); result^.kind := ElnaTreeKind.module_declaration; + result^.position.start_location.line := 1; + result^.position.start_location.column := 1; + result^.position.end_location := result^.position.start_location; + result^.types := elna_parser_type_part(cursor, error_list); if elna_list_empty(error_list) = false then result := free_and_nil(result) @@ -5831,7 +5941,7 @@ begin end end -proc compile() +proc compile() -> Bool var parser_node: Word tac: Word @@ -5859,7 +5969,7 @@ begin else current_error := error_list.first; elna_error_print(current_error) - ind; + end; return compiled end @@ -5919,7 +6029,7 @@ end * * Returns newly allocated, empty symbol table. *) -proc elna_symbol_table_create(parent: ^ElnaSymbolTable) +proc elna_symbol_table_create(parent: ^ElnaSymbolTable) -> ^ElnaSymbolTable var new_symbol_table: ^ElnaSymbolTable begin @@ -6177,7 +6287,7 @@ begin end end -proc elna_lexer_get_transition(current_state: Word, character_class: Word) +proc elna_lexer_get_transition(current_state: Word, character_class: Word) -> Word var column_position: Word target: Word -- cgit v1.2.3