aboutsummaryrefslogtreecommitdiff
path: root/source/parser.elna
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-09 09:55:53 +0200
committerEugen Wissner <belka@caraus.de>2026-10-09 10:33:53 +0200
commit244449004fb62adbfd43b81e8dfce7500ca4a7e4 (patch)
treeb115946fc1efc2edc0de71a4e6d7cce2c50f39f2 /source/parser.elna
parent994e6c95929ad9551901d86617e4678920f8f357 (diff)
downloadelna-244449004fb62adbfd43b81e8dfce7500ca4a7e4.tar.gz
Move export mark after the generic parameters
Diffstat (limited to 'source/parser.elna')
-rw-r--r--source/parser.elna1162
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.