Extract simple expression parser

This commit is contained in:
2025-10-08 12:06:07 +02:00
parent af9ad5b712
commit 8685933fc6

View File

@@ -128,10 +128,13 @@ type
_goto, _goto,
eof eof
); );
NodeKind := ( NodeKind = (
integer_literal, integer_literal,
string_literal, string_literal,
character_literal character_literal,
variable_expression,
field_access_expression,
dereference_expression
); );
const const
@@ -623,21 +626,68 @@ begin
_write_c('\n'); _write_c('\n');
end; 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 var
name: Word; name: Word;
lookup_result: Word;
name_token: Word; name_token: Word;
result: Word;
begin begin
name := _lexer_global_get_start(); name := _lexer_global_get_start();
name_token := _lexer_global_get_end() - name; 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 if lookup_result <> 0 then
_compile_enumeration_value(lookup_result) _compile_local_designator(lookup_result)
else else
_compile_designator(); _compile_global_designator(variable_expression)
_write_z("\tlw t0, (t0)\n\0")
end end
end; end;
@@ -647,7 +697,7 @@ end;
proc _compile_address_expression(); proc _compile_address_expression();
begin begin
_lexer_skip_token(); _lexer_skip_token();
_compile_designator() _compile_designator(0)
end; end;
(** (**
@@ -706,6 +756,7 @@ begin
length := _string_length(token_start); length := _string_length(token_start);
_lexer_skip_token(); _lexer_skip_token();
_node_set_kind(result, NodeKind.string_literal);
_string_literal_node_set_value(result, token_start); _string_literal_node_set_value(result, token_start);
_string_literal_node_set_length(result, length); _string_literal_node_set_length(result, length);
@@ -731,6 +782,52 @@ begin
_write_z("\tadd t0, t0, t1\n\0") _write_z("\tadd t0, t0, t1\n\0")
end; 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(); proc _compile_term();
var var
current_character: Word; current_character: Word;
@@ -739,15 +836,9 @@ var
begin begin
_lexer_read_token(@token_kind); _lexer_read_token(@token_kind);
if token_kind = LexerTokenKind.character then parser_node := _parse_designator();
parser_node := _parse_character_literal(); if parser_node <> 0 then
_compile_character_literal(parser_node) _compile_simple_expression(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)
elsif token_kind = LexerTokenKind.at then elsif token_kind = LexerTokenKind.at then
_compile_address_expression() _compile_address_expression()
elsif token_kind = LexerTokenKind.minus then elsif token_kind = LexerTokenKind.minus then
@@ -755,16 +846,8 @@ begin
elsif token_kind = LexerTokenKind.not then elsif token_kind = LexerTokenKind.not then
_compile_not_expression() _compile_not_expression()
elsif token_kind = LexerTokenKind.identifier then elsif token_kind = LexerTokenKind.identifier then
current_character := _lexer_global_get_start(); _compile_call();
current_character := _load_byte(current_character); _write_z("\tmv t0, a0\n\0")
(* 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
end end
end; end;
@@ -979,24 +1062,20 @@ begin
_write_z("\taddi t0, sp, \0"); _write_z("\taddi t0, sp, \0");
variable_offset := _parameter_info_get_offset(symbol); variable_offset := _parameter_info_get_offset(symbol);
_write_i(variable_offset); _write_i(variable_offset);
_write_c('\n'); _write_c('\n')
_lexer_skip_token()
end; end;
proc _compile_global_designator(); proc _compile_global_designator(variable_expression: Word);
var var
name: Word; name: Word;
token_kind: Word;
token_length: Word; token_length: Word;
begin begin
_write_z("\tla t0, \0"); _write_z("\tla t0, \0");
_lexer_read_token(@token_kind); name := _variable_expression_get_name(variable_expression);
name := _lexer_global_get_start(); token_length := _variable_expression_get_length(variable_expression);
token_length := _lexer_global_get_end() - name;
_write_s(name, token_length);
_lexer_skip_token();
_write_s(name, token_length);
_write_c('\n') _write_c('\n')
end; end;
@@ -1016,9 +1095,7 @@ begin
members := _enumeration_type_get_members(enumeration_type); members := _enumeration_type_get_members(enumeration_type);
members_length := _enumeration_type_get_length(enumeration_type); members_length := _enumeration_type_get_length(enumeration_type);
(* Skip enumeration type name and dot. Read the enumeration value. *) (* Skip dot. Read the enumeration value. *)
_lexer_skip_token();
_lexer_read_token(@token_type);
_lexer_skip_token(); _lexer_skip_token();
_lexer_read_token(@token_type); _lexer_read_token(@token_type);
@@ -1044,35 +1121,45 @@ begin
end end
end; end;
proc _compile_designator(); proc _compile_designator(variable_expression: Word);
var var
name_token: Word; name_token: Word;
lookup_result: Word; lookup_result: Word;
token_kind: Word; token_kind: Word;
name: Word; name: Word;
is_address: Word;
begin begin
_lexer_read_token(@token_kind); is_address := 1;
name := _lexer_global_get_start();
name_token := _lexer_global_get_end() - name;
lookup_result := _symbol_table_lookup(@symbol_table_local, name, name_token);
if lookup_result <> 0 then if variable_expression = 0 then
_compile_local_designator(lookup_result) _lexer_read_token(@token_kind);
else variable_expression := _parse_variable_expression()
_compile_global_designator()
end; end;
name := _variable_expression_get_name(variable_expression);
name_token := _variable_expression_get_length(variable_expression);
_lexer_read_token(@token_kind); _lexer_read_token(@token_kind);
if token_kind = LexerTokenKind.hat then if token_kind = LexerTokenKind.hat then
_compile_variable_expression(variable_expression);
_lexer_skip_token(); _lexer_skip_token();
_write_z("\tlw t0, (t0)\n\0") _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; end;
proc _compile_assignment(); proc _compile_assignment();
var var
token_kind: Word; token_kind: Word;
begin begin
_compile_designator(); _compile_designator(0);
(* Save the assignee address on the stack. *) (* Save the assignee address on the stack. *)
_write_z("\tsw t0, 60(sp)\n\0"); _write_z("\tsw t0, 60(sp)\n\0");