diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-10-09 09:55:53 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-10-09 10:33:53 +0200 |
| commit | 244449004fb62adbfd43b81e8dfce7500ca4a7e4 (patch) | |
| tree | b115946fc1efc2edc0de71a4e6d7cce2c50f39f2 /source/parser.elna | |
| parent | 994e6c95929ad9551901d86617e4678920f8f357 (diff) | |
| download | elna-244449004fb62adbfd43b81e8dfce7500ca4a7e4.tar.gz | |
Move export mark after the generic parameters
Diffstat (limited to 'source/parser.elna')
| -rw-r--r-- | source/parser.elna | 1162 |
1 files changed, 0 insertions, 1162 deletions
diff --git a/source/parser.elna b/source/parser.elna deleted file mode 100644 index 3912b65..0000000 --- a/source/parser.elna +++ /dev/null @@ -1,1162 +0,0 @@ -(* This Source Code Form is subject to the terms of the Mozilla Public License, - v. 2.0. If a copy of the MPL was not distributed with this file, You can - obtain one at https://mozilla.org/MPL/2.0/. *) -module -import common, sys.posix.cstdlib, lexer, ast, diagnostic - -proc elna_parser_expect*(cursor: ^ElnaLexerCursor; expected: ElnaLexerKind; error_list: ^ElnaList) -> ^ElnaLexerToken -var - token: ^ElnaLexerToken - parser_error: ^ElnaErrorUnexpectedToken -begin - elna_lexer_skip_empty_lines(cursor); - token := elna_lexer_peek(cursor); - - if token^.kind = expected then - token := elna_lexer_read(cursor) - else - token := nil; - parser_error := elna_error_unexpected_token_create(cursor, 1u); - parser_error^.expected[1] := expected; - elna_list_append(error_list, cast(parser_error: ^ElnaListNode)) - end -return token - -proc elna_parser_escape*(current_position: ^const Word8; result: ^Word8) -> Word -var - parsed_length: Word - next_character: Word8 - pos: ^const Word8 -begin - pos := current_position; - next_character := pos^; - - if next_character = '\\' then - parsed_length := 2u; - pos := pos + 1u; - next_character := pos^; - - if next_character = '\\' then - result^ := 92u8 - elsif next_character = 'n' then - result^ := 10u8 - elsif next_character = 't' then - result^ := 9u8 - elsif next_character = 'f' then - result^ := 12u8 - elsif next_character = 'r' then - result^ := 13u8 - elsif next_character = 'v' then - result^ := 11u8 - elsif next_character = '"' then - result^ := 34u8 - elsif next_character = '\'' then - result^ := 39u8 - elsif next_character = '0' then - result^ := 0u8 - else - result^ := next_character - end - else - parsed_length := 1u; - result^ := next_character - end -return parsed_length - -proc elna_parser_integer_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeIntegerLiteral -var - token: ^ElnaLexerToken - result: ^ElnaTreeIntegerLiteral - i: Word := 1u - val: Word := 0u -begin - result := malloc#[ElnaTreeIntegerLiteral](#size(ElnaTreeIntegerLiteral)); - token := elna_lexer_read(cursor); - result^.kind := ElnaTreeKind.integer_literal; - result^.type_decoration := nil; - result^.position := token^.position; - - while i <= token^.start.length do - val := val * 10u + cast(token^.start[i] - '0': Word); - i := i + 1u - end; - result^.value := val -return result - -proc elna_parser_boolean_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeBooleanLiteral -var - token: ^ElnaLexerToken - result: ^ElnaTreeBooleanLiteral -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeBooleanLiteral](#size(ElnaTreeBooleanLiteral)); - result^.kind := ElnaTreeKind.boolean_literal; - result^.value := token^.start = "true"; - result^.type_decoration := nil; - result^.position := token^.position -return result - -proc elna_parser_nil_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNilLiteral -var - token: ^ElnaLexerToken - result: ^ElnaTreeNilLiteral -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeNilLiteral](#size(ElnaTreeNilLiteral)); - result^.kind := ElnaTreeKind.null; - result^.type_decoration := nil; - result^.position := token^.position -return result - -proc elna_parser_character_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeCharacterLiteral -var - result: ^ElnaTreeCharacterLiteral - token: ^ElnaLexerToken -begin - result := malloc#[ElnaTreeCharacterLiteral](#size(ElnaTreeCharacterLiteral)); - token := elna_lexer_read(cursor); - result^.kind := ElnaTreeKind.character_literal; - result^.position := token^.position; - result^.type_decoration := nil; - elna_parser_escape(token^.start.ptr + 1u, @result^.value) -return result - -proc elna_parser_variable_expression*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeVariableExpression -var - result: ^ElnaTreeVariableExpression - token: ^ElnaLexerToken -begin - result := malloc#[ElnaTreeVariableExpression](#size(ElnaTreeVariableExpression)); - token := elna_lexer_read(cursor); - result^.kind := ElnaTreeKind.variable_expression; - result^.name := token^.start; - result^.position := token^.position; - result^.type_decoration := nil -return result - -proc elna_parser_string_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeStringLiteral -var - result: ^ElnaTreeStringLiteral - token: ^ElnaLexerToken - current_position: ^const Word8 - parsed_length: Word - parsed_total: Word - target_start, target_position: ^Word8 -begin - result := malloc#[ElnaTreeStringLiteral](#size(ElnaTreeStringLiteral)); - token := elna_lexer_read(cursor); - target_start := malloc#[Word8](token^.start.length); - target_position := target_start; - current_position := token^.start.ptr + 1u; - parsed_total := 2u; - - result^.kind := ElnaTreeKind.string_literal; - result^.position := token^.position; - result^.type_decoration := nil; - - while parsed_total < token^.start.length do - parsed_length := elna_parser_escape(current_position, target_position); - current_position := current_position + parsed_length; - parsed_total := parsed_total + parsed_length; - target_position := target_position + 1u - end; - result^.value := target_start[1 to cast(target_position - target_start: Word)] -return result - -proc elna_parser_trait_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeTraitExpression -var - result: ^ElnaTreeTraitExpression - token: ^ElnaLexerToken -begin - result := malloc#[ElnaTreeTraitExpression](#size(ElnaTreeTraitExpression)); - result^.kind := ElnaTreeKind.trait_expression; - 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); - if result^.argument = nil then - result := free_and_nil(result) - elsif elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list) = nil then - result := free_and_nil(result) - end - else - result := free_and_nil(result) - end -return result - -proc elna_parser_cast_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeCastExpression -var - result: ^ElnaTreeCastExpression := nil - token: ^ElnaLexerToken - start_location: ElnaLocation -begin - token := elna_lexer_read(cursor); - start_location := token^.position.start_location; - - if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) <> nil then - result := malloc#[ElnaTreeCastExpression](#size(ElnaTreeCastExpression)); - result^.kind := ElnaTreeKind._cast; - result^.position.start_location := start_location; - result^.type_decoration := nil; - result^.expression := elna_parser_binary_expression(cursor, error_list); - if result^.expression = nil then - result := free_and_nil(result) - elsif elna_parser_expect(cursor, ElnaLexerKind.colon, error_list) = nil then - result := free_and_nil(result) - else - result^.type_expression := elna_parser_type_expression(cursor, error_list); - if result^.type_expression = nil then - result := free_and_nil(result) - else - token := elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list); - if token = nil then - result := free_and_nil(result) - else - result^.position.end_location := token^.position.end_location - end - end - end - end -return result - -proc elna_parser_simple_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeExpression -var - token: ^ElnaLexerToken - result: ^ElnaTreeExpression := nil -begin - token := elna_lexer_peek(cursor); - case token^.kind of - ElnaLexerKind.character: - result := cast(elna_parser_character_literal(cursor): ^ElnaTreeExpression) - | ElnaLexerKind.integer: - result := cast(elna_parser_integer_literal(cursor): ^ElnaTreeExpression) - | ElnaLexerKind.string: - result := cast(elna_parser_string_literal(cursor): ^ElnaTreeExpression) - | ElnaLexerKind.boolean: - result := cast(elna_parser_boolean_literal(cursor): ^ElnaTreeExpression) - | ElnaLexerKind.null: - result := cast(elna_parser_nil_literal(cursor): ^ElnaTreeExpression) - | ElnaLexerKind._cast: - result := cast(elna_parser_cast_expression(cursor, error_list): ^ElnaTreeExpression) - | ElnaLexerKind.trait: - result := cast(elna_parser_trait_expression(cursor, error_list): ^ElnaTreeExpression) - | ElnaLexerKind.identifier: - result := cast(elna_parser_variable_expression(cursor): ^ElnaTreeExpression) - else - end -return result - -proc elna_parser_dereference_expression*(cursor: ^ElnaLexerCursor; - simple_expression: ^ElnaTreeExpression) -> ^ElnaTreeDereferenceExpression -var - result: ^ElnaTreeDereferenceExpression - token: ^ElnaLexerToken -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeDereferenceExpression](#size(ElnaTreeDereferenceExpression)); - result^.kind := ElnaTreeKind.dereference_expression; - result^.pointer := simple_expression; - result^.type_decoration := nil; - result^.position := token^.position -return result - -proc elna_parser_field_access_expression*(cursor: ^ElnaLexerCursor; - aggregate: ^ElnaTreeExpression) -> ^ElnaTreeFieldAccessExpression -var - result: ^ElnaTreeFieldAccessExpression - token: ^ElnaLexerToken -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeFieldAccessExpression](#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 - -proc elna_parser_array_access_expression*(cursor: ^ElnaLexerCursor; - array: ^ElnaTreeExpression; error_list: ^ElnaList) -> ^ElnaTreeArrayAccessExpression -var - result: ^ElnaTreeArrayAccessExpression - token: ^ElnaLexerToken -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeArrayAccessExpression](#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) - 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 - -proc elna_parser_call*(cursor: ^ElnaLexerCursor; callee: ^ElnaTreeExpression; error_list: ^ElnaList) -> ^ElnaTreeCall -var - result: ^ElnaTreeCall - argument_entry: ^ElnaTreeExpressionList - token: ^ElnaLexerToken - parser_error: ^ElnaErrorUnexpectedToken - reading_args: Bool := true -begin - result := malloc#[ElnaTreeCall](#size(ElnaTreeCall)); - result^.kind := ElnaTreeKind.call; - result^.type_decoration := nil; - result^.arguments := nil; - result^.count := 0u; - result^.callee := cast(callee: ^ElnaTreeVariableExpression); - - 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 - token := elna_lexer_read(cursor); - result^.position.end_location := token^.position.end_location - else - while reading_args do - if result^.arguments = nil then - result^.arguments := malloc#[ElnaTreeExpressionList](#size(ElnaTreeExpressionList)); - argument_entry := result^.arguments - else - argument_entry^.next := malloc#[ElnaTreeExpressionList](#size(ElnaTreeExpressionList)); - argument_entry := argument_entry^.next - end; - argument_entry^.next := nil; - argument_entry^.expression := elna_parser_binary_expression(cursor, error_list); - if argument_entry^.expression = nil then - result := free_and_nil(result); - reading_args := false - else - result^.count := result^.count + 1u; - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.comma then - elna_lexer_read(cursor) - elsif token^.kind = ElnaLexerKind.right_paren then - token := elna_lexer_read(cursor); - result^.position.end_location := token^.position.end_location; - reading_args := false - else - parser_error := elna_error_unexpected_token_create(cursor, 2u); - parser_error^.expected[1] := ElnaLexerKind.comma; - parser_error^.expected[2] := ElnaLexerKind.right_paren; - elna_list_append(error_list, cast(parser_error: ^ElnaListNode)); - result := free_and_nil(result); - reading_args := false - end - end - end - end -return result - -proc elna_parser_designator*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeExpression -var - simple_expression: ^ElnaTreeExpression - token: ^ElnaLexerToken - continue_loop: Bool := true -begin - simple_expression := elna_parser_simple_expression(cursor, error_list); - if simple_expression <> nil then - while continue_loop do - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.hat then - simple_expression := cast(elna_parser_dereference_expression(cursor, simple_expression): ^ElnaTreeExpression) - elsif token^.kind = ElnaLexerKind.dot then - simple_expression := cast(elna_parser_field_access_expression(cursor, simple_expression): ^ElnaTreeExpression) - elsif token^.kind = ElnaLexerKind.left_square then - simple_expression := cast(elna_parser_array_access_expression(cursor, simple_expression, error_list): ^ElnaTreeExpression); - if simple_expression = nil then - continue_loop := false - end - elsif token^.kind = ElnaLexerKind.left_paren then - simple_expression := cast(elna_parser_call(cursor, simple_expression, error_list): ^ElnaTreeExpression); - if simple_expression = nil then - continue_loop := false - end - else - continue_loop := false - end - end - end -return simple_expression - -proc elna_parser_unary_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeExpression -var - unary_result: ^ElnaTreeUnaryExpression - result: ^ElnaTreeExpression - op_kind: ElnaLexerKind - has_op: Bool := false - token: ^ElnaLexerToken -begin - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.at or token^.kind = ElnaLexerKind.minus or token^.kind = ElnaLexerKind.not then - op_kind := token^.kind; - has_op := true; - elna_lexer_read(cursor) - end; - result := elna_parser_designator(cursor, error_list); - if result <> nil & has_op then - unary_result := malloc#[ElnaTreeUnaryExpression](#size(ElnaTreeUnaryExpression)); - unary_result^.kind := ElnaTreeKind.unary_expression; - unary_result^.operand := result; - unary_result^.operator := op_kind; - unary_result^.position := token^.position; - unary_result^.type_decoration := nil; - result := cast(unary_result: ^ElnaTreeExpression) - end -return result - -proc elna_parser_binary_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeExpression -var - lhs_node: ^ElnaTreeExpression - rhs_node: ^ElnaTreeExpression := nil - bin_result: ^ElnaTreeBinaryExpression - token: ^ElnaLexerToken -begin - lhs_node := elna_parser_unary_expression(cursor, error_list); - token := elna_lexer_peek(cursor); - - case token^.kind of - ElnaLexerKind.plus, - ElnaLexerKind.minus, - ElnaLexerKind.multiplication, - ElnaLexerKind.and, - ElnaLexerKind._or, - ElnaLexerKind._xor, - ElnaLexerKind.equals, - ElnaLexerKind.remainder, - ElnaLexerKind.division, - ElnaLexerKind.less_than, - ElnaLexerKind.greater_than, - ElnaLexerKind.less_equal, - ElnaLexerKind.not_equal, - ElnaLexerKind.greater_equal: - elna_lexer_read(cursor); - rhs_node := elna_parser_unary_expression(cursor, error_list) - else - end; - - if rhs_node <> nil then - bin_result := malloc#[ElnaTreeBinaryExpression](#size(ElnaTreeBinaryExpression)); - bin_result^.kind := ElnaTreeKind.binary_expression; - bin_result^.lhs := lhs_node; - bin_result^.rhs := rhs_node; - bin_result^.operator := token^.kind; - bin_result^.position := token^.position; - bin_result^.type_decoration := nil; - lhs_node := cast(bin_result: ^ElnaTreeExpression) - end -return lhs_node - -proc elna_parser_label_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeLabelDeclaration -var - result: ^ElnaTreeLabelDeclaration - token: ^ElnaLexerToken -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeLabelDeclaration](#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^.label := token^.start; - result^.position.end_location := token^.position.end_location - else - result := free_and_nil(result) - end -return result - -proc elna_parser_assign_statement*(cursor: ^ElnaLexerCursor; assignee: ^ElnaTreeExpression; error_list: ^ElnaList) -> ^ElnaTreeAssignStatement -var - token: ^ElnaLexerToken - result: ^ElnaTreeAssignStatement -begin - result := malloc#[ElnaTreeAssignStatement](#size(ElnaTreeAssignStatement)); - result^.kind := ElnaTreeKind.assign_statement; - result^.next := nil; - result^.assignee := assignee; - result^.assignment := nil; - - 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) - end -return result - -proc elna_parser_return_statement*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeReturnStatement -var - token: ^ElnaLexerToken - result: ^ElnaTreeReturnStatement -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeReturnStatement](#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) - end -return result - -proc elna_parser_conditional_statements*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList; - block_keyword: ElnaLexerKind) -> ^ElnaTreeConditionalStatements -var - result: ^ElnaTreeConditionalStatements -begin - result := malloc#[ElnaTreeConditionalStatements](#size(ElnaTreeConditionalStatements)); - elna_lexer_read(cursor); - result^.condition := elna_parser_binary_expression(cursor, error_list); - if result^.condition = nil then - result := free_and_nil(result) - else - if elna_parser_expect(cursor, block_keyword, error_list) <> nil then - result^.statements := elna_parser_statements(cursor, error_list) - end; - if elna_list_empty(error_list) then - result^.next := nil - else - result := free_and_nil(result) - end - end -return result - -proc elna_parser_if_statement*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeIfStatement -var - result: ^ElnaTreeIfStatement - previous_conditional: ^ElnaTreeConditionalStatements - next_conditional: ^ElnaTreeConditionalStatements - token: ^ElnaLexerToken - reading_elsif: Bool := true -begin - token := elna_lexer_peek(cursor); - result := malloc#[ElnaTreeIfStatement](#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); - result^.conditionals := previous_conditional; - - while reading_elsif do - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind._elsif then - next_conditional := elna_parser_conditional_statements(cursor, error_list, ElnaLexerKind._then); - previous_conditional^.next := next_conditional; - previous_conditional := next_conditional - elsif token^.kind = ElnaLexerKind._else then - elna_lexer_read(cursor); - result^._else := elna_parser_statements(cursor, error_list); - reading_elsif := false - else - result^._else := nil; - reading_elsif := false - end - end; - elna_parser_expect(cursor, ElnaLexerKind._end, error_list) -return result - -proc elna_parser_statement*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeStatement -var - result: ^ElnaTreeStatement := nil - call_result: ^ElnaTreeCallStatement - designator: ^ElnaTreeExpression - token: ^ElnaLexerToken -begin - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind._if then - result := cast(elna_parser_if_statement(cursor, error_list): ^ElnaTreeStatement) - elsif token^.kind = ElnaLexerKind._return then - result := cast(elna_parser_return_statement(cursor, error_list): ^ElnaTreeStatement) - elsif token^.kind = ElnaLexerKind.dot then - result := cast(elna_parser_label_declaration(cursor, error_list): ^ElnaTreeStatement) - elsif token^.kind = ElnaLexerKind.identifier then - designator := elna_parser_designator(cursor, error_list); - if designator <> nil then - if designator^.kind <> ElnaTreeKind.call then - result := cast(elna_parser_assign_statement(cursor, designator, error_list): ^ElnaTreeStatement) - else - call_result := malloc#[ElnaTreeCallStatement](#size(ElnaTreeCallStatement)); - call_result^.kind := ElnaTreeKind.call_statement; - call_result^.next := nil; - call_result^.call := cast(designator: ^ElnaTreeCall); - call_result^.position := designator^.position; - result := cast(call_result: ^ElnaTreeStatement) - end - end - end -return result - -proc elna_parser_statements*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeStatement -var - previous_statement: ^ElnaTreeStatement - next_statement: ^ElnaTreeStatement - first_statement: ^ElnaTreeStatement - token: ^ElnaLexerToken -begin - elna_lexer_skip_empty_lines(cursor); - first_statement := elna_parser_statement(cursor, error_list); - previous_statement := first_statement; - if previous_statement <> nil then - token := elna_lexer_peek(cursor); - while token^.kind = ElnaLexerKind.semicolon & elna_list_empty(error_list) do - elna_lexer_read(cursor); - elna_lexer_skip_empty_lines(cursor); - next_statement := elna_parser_statement(cursor, error_list); - previous_statement^.next := next_statement; - previous_statement := next_statement; - token := elna_lexer_peek(cursor) - end - end; - elna_lexer_skip_empty_lines(cursor) -return first_statement - -proc elna_parser_named_type_expression*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNamedTypeExpression -var - result: ^ElnaTreeNamedTypeExpression - token: ^ElnaLexerToken -begin - result := malloc#[ElnaTreeNamedTypeExpression](#size(ElnaTreeNamedTypeExpression)); - token := elna_lexer_read(cursor); - result^.kind := ElnaTreeKind.named_type_expression; - result^.name := token^.start; - result^.position := token^.position -return result - -proc elna_parser_pointer_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreePointerTypeExpression -var - result: ^ElnaTreePointerTypeExpression - token: ^ElnaLexerToken -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreePointerTypeExpression](#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 -return result - -proc elna_parser_array_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeArrayTypeExpression -var - result: ^ElnaTreeArrayTypeExpression - token: ^ElnaLexerToken -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeArrayTypeExpression](#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 - 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 -return result - -proc elna_parser_record_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeRecordTypeExpression -var - entry: ^ElnaTreeField - result: ^ElnaTreeRecordTypeExpression - previous_entry: ^ElnaTreeField - token: ^ElnaLexerToken - parser_error: ^ElnaErrorUnexpectedToken - reading_members: Bool := true -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeRecordTypeExpression](#size(ElnaTreeRecordTypeExpression)); - result^.kind := ElnaTreeKind.record_type_expression; - result^.members := nil; - result^.length := 0u; - result^.position := token^.position; - - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.left_paren then - elna_lexer_read(cursor); - token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); - if token = nil then - result := free_and_nil(result); - reading_members := false - else - result^.parent := token^.start; - if elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list) = nil then - result := free_and_nil(result); - reading_members := false - end - end - end; - - while reading_members & result <> nil do - token := elna_lexer_read(cursor); - if token^.kind = ElnaLexerKind._end then - reading_members := false - elsif token^.kind <> ElnaLexerKind.identifier then - parser_error := elna_error_unexpected_token_create(cursor, 2u); - parser_error^.expected[1] := ElnaLexerKind._end; - parser_error^.expected[2] := ElnaLexerKind.identifier; - elna_list_append(error_list, cast(parser_error: ^ElnaListNode)); - result := free_and_nil(result); - reading_members := false - else - entry := malloc#[ElnaTreeField](#size(ElnaTreeField)); - result^.length := result^.length + 1u; - entry^.name := token^.start; - if elna_parser_expect(cursor, ElnaLexerKind.colon, error_list) = nil then - result := free_and_nil(result); - reading_members := false - else - entry^.type_expression := elna_parser_type_expression(cursor, error_list); - if entry^.type_expression = nil then - result := free_and_nil(result); - reading_members := false - else - entry^.next := nil; - if result^.members = nil then - result^.members := entry - else - previous_entry^.next := entry - end; - previous_entry := entry; - - token := elna_lexer_read(cursor); - if token^.kind = ElnaLexerKind.semicolon then - (* continue *) - elsif token^.kind = ElnaLexerKind._end then - reading_members := false - else - parser_error := elna_error_unexpected_token_create(cursor, 2u); - parser_error^.expected[1] := ElnaLexerKind._end; - parser_error^.expected[2] := ElnaLexerKind.semicolon; - elna_list_append(error_list, cast(parser_error: ^ElnaListNode)); - reading_members := false - end - end - end - end - end -return result - -proc elna_parser_enumeration_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeEnumerationTypeExpression -var - result: ^ElnaTreeEnumerationTypeExpression - entry: ^ElnaTreeEnumeration - previous_entry: ^ElnaTreeEnumeration - token: ^ElnaLexerToken - parser_error: ^ElnaErrorUnexpectedToken - reading_members: Bool := true -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeEnumerationTypeExpression](#size(ElnaTreeEnumerationTypeExpression)); - result^.kind := ElnaTreeKind.enumeration_type_expression; - result^.members := nil; - result^.length := 0u; - result^.position.start_location := token^.position.start_location; - - while reading_members & result <> nil do - token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); - if token = nil then - result := free_and_nil(result); - reading_members := false - else - entry := malloc#[ElnaTreeEnumeration](#size(ElnaTreeEnumeration)); - result^.length := result^.length + 1u; - entry^.name := token^.start; - entry^.next := nil; - if result^.members = nil then - result^.members := entry - else - previous_entry^.next := entry - end; - previous_entry := entry; - - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.comma then - elna_lexer_read(cursor) - elsif token^.kind = ElnaLexerKind.right_paren then - token := elna_lexer_read(cursor); - result^.position.end_location := token^.position.end_location; - reading_members := false - else - parser_error := elna_error_unexpected_token_create(cursor, 2u); - parser_error^.expected[1] := ElnaLexerKind.comma; - parser_error^.expected[2] := ElnaLexerKind.right_paren; - elna_list_append(error_list, cast(parser_error: ^ElnaListNode)); - result := free_and_nil(result); - reading_members := false - end - end - end -return result - -proc elna_parser_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeTypeExpression -var - result: ^ElnaTreeTypeExpression := nil - token: ^ElnaLexerToken - parser_error: ^ElnaErrorUnexpectedToken -begin - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.identifier then - result := cast(elna_parser_named_type_expression(cursor): ^ElnaTreeTypeExpression) - elsif token^.kind = ElnaLexerKind.left_paren then - result := cast(elna_parser_enumeration_type_expression(cursor, error_list): ^ElnaTreeTypeExpression) - elsif token^.kind = ElnaLexerKind._record then - result := cast(elna_parser_record_type_expression(cursor, error_list): ^ElnaTreeTypeExpression) - elsif token^.kind = ElnaLexerKind.hat then - result := cast(elna_parser_pointer_type_expression(cursor, error_list): ^ElnaTreeTypeExpression) - elsif token^.kind = ElnaLexerKind.left_square then - result := cast(elna_parser_array_type_expression(cursor, error_list): ^ElnaTreeTypeExpression) - else - parser_error := elna_error_unexpected_token_create(cursor, 5u); - parser_error^.expected[1] := ElnaLexerKind.identifier; - parser_error^.expected[2] := ElnaLexerKind.left_paren; - parser_error^.expected[3] := ElnaLexerKind._record; - parser_error^.expected[4] := ElnaLexerKind.hat; - parser_error^.expected[5] := ElnaLexerKind.left_square; - elna_list_append(error_list, cast(parser_error: ^ElnaListNode)) - end -return result - -proc elna_parser_variable_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeVariableDeclaration -var - var_type: ^ElnaTreeTypeExpression - result: ^ElnaTreeVariableDeclaration := nil - token: ^ElnaLexerToken -begin - token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); - if token <> nil then - if elna_parser_expect(cursor, ElnaLexerKind.colon, error_list) <> nil then - var_type := elna_parser_type_expression(cursor, error_list); - if var_type <> nil then - result := malloc#[ElnaTreeVariableDeclaration](#size(ElnaTreeVariableDeclaration)); - result^.kind := ElnaTreeKind.variable_declaration; - result^.next := nil; - result^.name := token^.start; - result^.type_expression := var_type; - result^.position := token^.position - end - end - end -return result - -proc elna_parser_parameters*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeVariableDeclaration -var - parameters: ^ElnaTreeVariableDeclaration := nil - token: ^ElnaLexerToken - current_declaration: ^ElnaTreeVariableDeclaration - next_declaration: ^ElnaTreeVariableDeclaration - reading: Bool := true -begin - token := elna_lexer_peek(cursor); - if token^.kind <> ElnaLexerKind.right_paren then - while reading do - next_declaration := elna_parser_variable_declaration(cursor, error_list); - if next_declaration = nil then - parameters := free_and_nil(parameters); - reading := false - else - if parameters = nil then - parameters := next_declaration - else - current_declaration^.next := cast(next_declaration: ^ElnaTreeDeclaration) - end; - current_declaration := next_declaration; - - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.comma or token^.kind = ElnaLexerKind.semicolon then - elna_lexer_read(cursor) - else - reading := false - end - end - end - end -return parameters - -proc elna_parser_procedure_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeProcedureDeclaration -var - result: ^ElnaTreeProcedureDeclaration - token: ^ElnaLexerToken -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeProcedureDeclaration](#size(ElnaTreeProcedureDeclaration)); - result^.kind := ElnaTreeKind.procedure_declaration; - result^.next := nil; - result^.position := token^.position; - - token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list); - if token = nil then - result := free_and_nil(result) - else - result^.name := token^.start; - - if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) = nil then - result := free_and_nil(result) - else - result^.parameters := elna_parser_parameters(cursor, error_list); - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - elsif elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list) = nil then - result := free_and_nil(result) - else - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.arrow then - elna_lexer_read(cursor); - result^.return_type := elna_parser_type_expression(cursor, error_list); - if result^.return_type = nil then - result := free_and_nil(result) - end - else - result^.return_type := nil - end; - - if result <> nil then - token := elna_lexer_peek(cursor); - result^.is_extern := token^.kind = ElnaLexerKind._extern; - if result^.is_extern then - elna_lexer_read(cursor); - result^.temporaries := nil; - result^.body := nil - else - result^.temporaries := elna_parser_var_part(cursor, error_list); - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - else - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind._begin then - elna_lexer_read(cursor); - result^.body := elna_parser_statements(cursor, error_list); - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - elsif elna_parser_expect(cursor, ElnaLexerKind._end, error_list) = nil then - result := free_and_nil(result) - end - elsif token^.kind = ElnaLexerKind._return then - result^.body := cast(elna_parser_return_statement(cursor, error_list): ^ElnaTreeStatement); - if result^.body = nil then - result := free_and_nil(result) - end - end - end - end - end - end - end - end -return result - -proc elna_parser_procedures*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeProcedureDeclaration -var - parser_node: ^ElnaTreeProcedureDeclaration - result: ^ElnaTreeProcedureDeclaration := nil - current_declaration: ^ElnaTreeProcedureDeclaration - token: ^ElnaLexerToken - reading: Bool := true -begin - while reading do - elna_lexer_skip_empty_lines(cursor); - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind._proc then - parser_node := elna_parser_procedure_declaration(cursor, error_list); - if parser_node <> nil then - if result = nil then - result := parser_node - else - current_declaration^.next := cast(parser_node: ^ElnaTreeDeclaration) - end; - current_declaration := parser_node - else - reading := false - end - else - reading := false - end - end -return result - -proc elna_parser_type_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeTypeDeclaration -var - result: ^ElnaTreeTypeDeclaration - token: ^ElnaLexerToken -begin - token := elna_lexer_read(cursor); - result := malloc#[ElnaTreeTypeDeclaration](#size(ElnaTreeTypeDeclaration)); - 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) - else - result := free_and_nil(result) - end -return result - -proc elna_parser_type_part*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeDeclaration -var - parser_node: ^ElnaTreeDeclaration - result: ^ElnaTreeDeclaration := nil - current_declaration: ^ElnaTreeDeclaration - token: ^ElnaLexerToken - reading: Bool := true -begin - elna_lexer_skip_empty_lines(cursor); - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind._type then - elna_lexer_read(cursor); - while reading do - elna_lexer_skip_empty_lines(cursor); - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.identifier then - parser_node := cast(elna_parser_type_declaration(cursor, error_list): ^ElnaTreeDeclaration); - if parser_node <> nil then - if result = nil then - result := parser_node - else - current_declaration^.next := parser_node - end; - current_declaration := parser_node; - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.semicolon then - elna_lexer_read(cursor) - end - else - reading := false - end - else - reading := false - end - end - end -return result - -proc elna_parser_var_part*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeVariableDeclaration -var - result: ^ElnaTreeVariableDeclaration := nil - variable_node: ^ElnaTreeVariableDeclaration - current_declaration: ^ElnaTreeVariableDeclaration - token: ^ElnaLexerToken - reading: Bool := true -begin - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind._var then - elna_lexer_read(cursor); - while reading do - elna_lexer_skip_empty_lines(cursor); - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.identifier then - variable_node := elna_parser_variable_declaration(cursor, error_list); - if variable_node <> nil then - if result = nil then - result := variable_node - else - current_declaration^.next := cast(variable_node: ^ElnaTreeDeclaration) - end; - current_declaration := variable_node; - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind.semicolon then - elna_lexer_read(cursor) - end - else - reading := false - end - else - reading := false - end - end - end -return result - -proc elna_parser_program_body*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeStatement -var - result: ^ElnaTreeStatement := nil - token: ^ElnaLexerToken -begin - elna_lexer_skip_empty_lines(cursor); - token := elna_lexer_peek(cursor); - if token^.kind = ElnaLexerKind._begin then - elna_lexer_read(cursor); - result := elna_parser_statements(cursor, error_list); - if elna_parser_expect(cursor, ElnaLexerKind._end, error_list) = nil then - result := free_and_nil(result) - elsif elna_parser_expect(cursor, ElnaLexerKind.dot, error_list) = nil then - result := free_and_nil(result) - end - elsif token^.kind = ElnaLexerKind._end then - elna_lexer_read(cursor); - if elna_parser_expect(cursor, ElnaLexerKind.dot, error_list) = nil then - result := free_and_nil(result) - end - end -return result - -proc elna_parser_module_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeModuleDeclaration -var - result: ^ElnaTreeModuleDeclaration -begin - result := malloc#[ElnaTreeModuleDeclaration](#size(ElnaTreeModuleDeclaration)); - result^.kind := ElnaTreeKind.module_declaration; - result^.position.start_location := { ElnaLocation; line: 1u, column: 1u }; - 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) - end; - - if result <> nil then - result^.globals := elna_parser_var_part(cursor, error_list); - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end - end; - - if result <> nil then - result^.procedures := elna_parser_procedures(cursor, error_list); - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end - end; - - if result <> nil then - result^.body := elna_parser_program_body(cursor, error_list); - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end - end -return result - -end. |
