From 8685933fc6e85ae84442a79ec6fcb61f5c30e479 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 8 Oct 2025 12:06:07 +0200 Subject: [PATCH] Extract simple expression parser --- boot/stage15.elna | 189 +++++++++++++++++++++++++++++++++------------- 1 file changed, 138 insertions(+), 51 deletions(-) diff --git a/boot/stage15.elna b/boot/stage15.elna index 6200fbd..1c283e9 100644 --- a/boot/stage15.elna +++ b/boot/stage15.elna @@ -128,10 +128,13 @@ type _goto, eof ); - NodeKind := ( + NodeKind = ( integer_literal, string_literal, - character_literal + character_literal, + variable_expression, + field_access_expression, + dereference_expression ); const @@ -623,21 +626,68 @@ begin _write_c('\n'); end; -proc _compile_variable_expression(); +proc _variable_expression_size(); + return 12 +end; + +proc _variable_expression_get_name(this: Word); +begin + this := this + 4; + return this^ +end; + +proc _variable_expression_set_name(this: Word, value: Word); +begin + this := this + 4; + this^ := value +end; + +proc _variable_expression_get_length(this: Word); +begin + this := this + 8; + return this^ +end; + +proc _variable_expression_set_length(this: Word, value: Word); +begin + this := this + 8; + this^ := value +end; + +proc _parse_variable_expression(); var name: Word; - lookup_result: Word; name_token: Word; + result: Word; begin name := _lexer_global_get_start(); name_token := _lexer_global_get_end() - name; - lookup_result := _symbol_table_lookup(@symbol_table_global, name, name_token); + _lexer_skip_token(); + result := memory_free_pointer; + memory_free_pointer := memory_free_pointer + _variable_expression_size(); + + _node_set_kind(result, NodeKind.variable_expression); + _variable_expression_set_name(result, name); + _variable_expression_set_length(result, name_token); + + return result +end; + +proc _compile_variable_expression(variable_expression: Word); +var + name: Word; + name_token: Word; + lookup_result: Word; +begin + name := _variable_expression_get_name(variable_expression); + name_token := _variable_expression_get_length(variable_expression); + + lookup_result := _symbol_table_lookup(@symbol_table_local, name, name_token); if lookup_result <> 0 then - _compile_enumeration_value(lookup_result) + _compile_local_designator(lookup_result) else - _compile_designator(); - _write_z("\tlw t0, (t0)\n\0") + _compile_global_designator(variable_expression) end end; @@ -647,7 +697,7 @@ end; proc _compile_address_expression(); begin _lexer_skip_token(); - _compile_designator() + _compile_designator(0) end; (** @@ -706,6 +756,7 @@ begin length := _string_length(token_start); _lexer_skip_token(); + _node_set_kind(result, NodeKind.string_literal); _string_literal_node_set_value(result, token_start); _string_literal_node_set_length(result, length); @@ -731,6 +782,52 @@ begin _write_z("\tadd t0, t0, t1\n\0") end; +proc _parse_simple_expression(); +var + current_character: Word; + parser_node: Word; + token_kind: Word; +begin + parser_node := 0; + _lexer_read_token(@token_kind); + + if token_kind = LexerTokenKind.character then + parser_node := _parse_character_literal() + elsif token_kind = LexerTokenKind.integer then + parser_node := _parse_integer_literal() + elsif token_kind = LexerTokenKind.string then + parser_node := _parse_string_literal() + elsif token_kind = LexerTokenKind.identifier then + current_character := _lexer_global_get_start(); + current_character := _load_byte(current_character); + + (* This is a call if the statement starts with an underscore. *) + if current_character <> '_' then + parser_node := _parse_variable_expression() + end + end; + return parser_node +end; + +proc _parse_designator(); + return _parse_simple_expression() +end; + +proc _compile_simple_expression(parser_node: Word); +begin + if _node_get_kind(parser_node) = NodeKind.character_literal then + _compile_character_literal(parser_node) + elsif _node_get_kind(parser_node) = NodeKind.string_literal then + _compile_string_literal(parser_node) + elsif _node_get_kind(parser_node) = NodeKind.integer_literal then + _compile_integer_literal(parser_node) + elsif _node_get_kind(parser_node) = NodeKind.variable_expression then + if _compile_designator(parser_node) = 1 then + _write_z("\tlw t0, (t0)\n\0") + end + end +end; + proc _compile_term(); var current_character: Word; @@ -739,15 +836,9 @@ var begin _lexer_read_token(@token_kind); - if token_kind = LexerTokenKind.character then - parser_node := _parse_character_literal(); - _compile_character_literal(parser_node) - elsif token_kind = LexerTokenKind.string then - parser_node := _parse_string_literal(); - _compile_string_literal(parser_node) - elsif token_kind = LexerTokenKind.integer then - parser_node := _parse_integer_literal(); - _compile_integer_literal(parser_node) + parser_node := _parse_designator(); + if parser_node <> 0 then + _compile_simple_expression(parser_node) elsif token_kind = LexerTokenKind.at then _compile_address_expression() elsif token_kind = LexerTokenKind.minus then @@ -755,16 +846,8 @@ begin elsif token_kind = LexerTokenKind.not then _compile_not_expression() elsif token_kind = LexerTokenKind.identifier then - current_character := _lexer_global_get_start(); - current_character := _load_byte(current_character); - - (* This is a call if the statement starts with an underscore. *) - if current_character = '_' then - _compile_call(); - _write_z("\tmv t0, a0\n\0") - else - _compile_variable_expression() - end + _compile_call(); + _write_z("\tmv t0, a0\n\0") end end; @@ -979,24 +1062,20 @@ begin _write_z("\taddi t0, sp, \0"); variable_offset := _parameter_info_get_offset(symbol); _write_i(variable_offset); - _write_c('\n'); - _lexer_skip_token() + _write_c('\n') end; -proc _compile_global_designator(); +proc _compile_global_designator(variable_expression: Word); var name: Word; - token_kind: Word; token_length: Word; begin _write_z("\tla t0, \0"); - _lexer_read_token(@token_kind); - name := _lexer_global_get_start(); - token_length := _lexer_global_get_end() - name; - _write_s(name, token_length); - _lexer_skip_token(); + name := _variable_expression_get_name(variable_expression); + token_length := _variable_expression_get_length(variable_expression); + _write_s(name, token_length); _write_c('\n') end; @@ -1016,9 +1095,7 @@ begin members := _enumeration_type_get_members(enumeration_type); members_length := _enumeration_type_get_length(enumeration_type); - (* Skip enumeration type name and dot. Read the enumeration value. *) - _lexer_skip_token(); - _lexer_read_token(@token_type); + (* Skip dot. Read the enumeration value. *) _lexer_skip_token(); _lexer_read_token(@token_type); @@ -1044,35 +1121,45 @@ begin end end; -proc _compile_designator(); +proc _compile_designator(variable_expression: Word); var name_token: Word; lookup_result: Word; token_kind: Word; name: Word; + is_address: Word; begin - _lexer_read_token(@token_kind); - name := _lexer_global_get_start(); - name_token := _lexer_global_get_end() - name; - lookup_result := _symbol_table_lookup(@symbol_table_local, name, name_token); + is_address := 1; - if lookup_result <> 0 then - _compile_local_designator(lookup_result) - else - _compile_global_designator() + if variable_expression = 0 then + _lexer_read_token(@token_kind); + variable_expression := _parse_variable_expression() end; + name := _variable_expression_get_name(variable_expression); + name_token := _variable_expression_get_length(variable_expression); + _lexer_read_token(@token_kind); if token_kind = LexerTokenKind.hat then + _compile_variable_expression(variable_expression); _lexer_skip_token(); _write_z("\tlw t0, (t0)\n\0") - end + elsif token_kind = LexerTokenKind.dot then + lookup_result := _symbol_table_lookup(@symbol_table_global, name, name_token); + if lookup_result <> 0 then + _compile_enumeration_value(lookup_result) + end; + is_address := 0 + else + _compile_variable_expression(variable_expression) + end; + return is_address end; proc _compile_assignment(); var token_kind: Word; begin - _compile_designator(); + _compile_designator(0); (* Save the assignee address on the stack. *) _write_z("\tsw t0, 60(sp)\n\0");