fix(grammar): Correct ambiguities and restructure expression parsing

Signed-off-by: erick-alcachofa <erick@artichoke.dev>

The grammar contained several structural issues and ambiguities,
particularly in expression parsing, operator precedence, and the
`export` keyword. This commit restructures significant parts of the
grammar to resolve these problems and improve its formal correctness,
making it more suitable for parser generation.

The most relevant changes include:

* **Centralized Export Handling:** Corrects the definition of exports by
  introducing a top-level `<declaration>` rule that distinguishes
  between `<exportable_declaration>` and `<non_exportable_declaration>`.
  This removes the repetitive and ambiguous `export?` prefix from
  multiple individual declarations (`module`, `struct`, `fn`, etc.).

* **Unified Postfix Operations:** Integrates scoped access into the
  suffix operations . This provides an unambiguous and unified
  definition for these common constructs.

* **Updated Identifier Chain Issue:** Several rules in the precedence
  chain ultimately resolved into starting with an identifier, this
  caused ambiguitiy and issues for parsing, this was refactored in order
  to correctly handle the cases.

* **Reduced Ambiguity in Statements:** Refactors complex rules like
  `<variable_declaration>` and `<else_statement>` into smaller, more
  explicit sub-rules (`<variable_declaration_tail>`,
  `<else_statement_tail>`). This eliminates potential parsing conflicts
  and improves the overall clarity of the grammar.

* **Simplified Access Expressions:** Removes the separate
  `<scoped_access_expression>` and `<reflection_expression>` rules.
  Their logic has been integrated directly into the more generic and
  powerful postfix expression system, simplifying the grammar.
This commit is contained in:
erick-alcachofa 2025-10-11 11:30:27 -06:00
parent 6809b7ea1d
commit de58de2a9a
Signed by: me
GPG Key ID: 6FA5F8643444BAFA

View File

@ -11,16 +11,29 @@
/* A program is a sequence of top-level declarations and statements. */
<program> =
( <import_statement>
| <module_statement>
| <alias_statement>
| <struct_declaration>
| <enum_declaration>
| <function_declaration> )*
<declaration>*
<eof>
<declaration> =
"export" <exportable_declaration>
| <non_exportable_declaration>
<exportable_declaration> =
<module_statement>
| <struct_declaration>
| <enum_declaration>
| <function_declaration>
non_exportable_declaration =
<import_statement>
| <alias_statement>
| <module_statement>
| <struct_declaration>
| <enum_declaration>
| <function_declaration>
<module_statement> =
"export"? "module" <namespaced_identifier> "{"
"module" <namespaced_identifier> "{"
( <module_statement>
| <alias_statement>
| <struct_declaration>
@ -42,7 +55,7 @@
/* Rules for defining functions, structs, enums, and their components. */
<function_declaration> =
"export"? "fn" <identifier> <generic_params>? "(" <fn_params_list>? ")" ( "->" <type> )? <code_block>
"fn" <identifier> <generic_params>? "(" <fn_params_list>? ")" ( "->" <type> )? <code_block>
<fn_params_list> =
"this" <type> ("," <fn_param> ( "," <fn_param> )* )?
@ -52,7 +65,7 @@
<identifier> ":" <type>
<struct_declaration> =
"export"? "struct" <identifier> <generic_params>? "{" <struct_members> "}"
"struct" <identifier> <generic_params>? "{" <struct_members> "}"
<struct_members> =
<struct_member> ( "," <struct_member> )*
@ -61,7 +74,7 @@
<identifier> ":" <type>
<enum_declaration> =
"export"? "enum" <identifier> <generic_params>? "{" <enum_members> "}"
"enum" <identifier> <generic_params>? "{" <enum_members> "}"
<enum_members> =
<enum_member> ( "," <enum_member> )*
@ -88,20 +101,23 @@
<statement> =
<variable_declaration> ";"
| <if_statement>
| <loop_statement>
| <defer_statement> ";"
| <errdefer_statement> ";"
| <return_statement> ";"
| <break_statement> ";"
| <continue_statement> ";"
| <expression> ";"
| <alias_statement>
| <match_statement>
| <switch_statement>
| <loop_statement>
| <expression> ";"
<variable_declaration> =
<variable_declarator> <identifier> ( ":" <type> )? "=" <expression>
| <variable_declarator> <identifier> ":" <type> ( "=" <expression> )?
<variable_declarator> <identifier> <variable_declaration_tail>
<variable_declaration_tail> =
":" <type> ( "=" <expression> )?
| "=" <expression>
<variable_declarator> =
"let"
@ -112,8 +128,11 @@
<else_statement>?
<else_statement> =
"else" <variable_unwrapper>? <code_block>
| "else" <if_statement>
"else" <else_statement_tail>
<else_statement_tail> =
<if_statement>
| <variable_unwrapper>? <code_block>
<variable_unwrapper> =
"|" <identifier> "|"
@ -152,7 +171,7 @@
"switch" "(" <expression> ")" "{" <switch_case>* <default_case>? "}"
<match_case> =
( <type_name> | <scoped_access_expression> ) ( "(" <identifier> ")" )? "->" <code_block>
<type_name> ( "(" <identifier> ")" )? "->" <code_block>
<switch_case> =
<expression> "->" <code_block>
@ -204,45 +223,41 @@
<prefix_expression> ( <multiply_op> <prefix_expression> )*
<prefix_expression> =
<prefix_op>* <primary_expression>
<prefix_op>* <postfix_expression>
<primary_expression> =
<primary_type_expression> ( <suffix_op> | <fn_call_arguments> )*
<postfix_expression> =
<primary_expression> ( <suffix_op> | <fn_call_arguments> )*
/* --- Primary Expressions & Literals --- */
/* The highest-precedence expressions, including literals and grouped expressions. */
<primary_type_expression> =
<primary_expression> =
<grouped_expression>
| <scoped_access_expression>
| <reflection_expression>
| <struct_literal>
| <type_name>
| <char_literal>
| <literal>
| <access_expression> ( "{" <struct_literal_body> "}" )?
<access_expression> =
<identifier> ( "<" <types_list> ">" )?
<literal> =
<char_literal>
| <null_literal>
| <string_literal>
| <number_literal>
| <boolean_literal>
| <identifier>
<grouped_expression> =
"(" <expression> ")"
<scoped_access_expression> =
<type_name> "::" <identifier>
<reflection_expression> =
( <type_name> | <scoped_access_expression> ) ".@" <identifier>?
<fn_call_arguments> =
"(" <expression_list> ")"
<expression_list> =
(<expression> ",")* <expression>?
<struct_literal> =
<type> "{" ( <named_field_list> | <positional_field_list> )? ","? "}"
<struct_literal_body> =
( <named_field_list> | <positional_field_list> )? ","?
<named_field_list> =
<named_field_init> ( "," <named_field_init> )*
@ -278,15 +293,23 @@
<prefix_op> = "!" | "-" | "~" | "&" | "*"
<suffix_op> =
"[" <expression>? ":" <expression>? "]"
| "[" <expression> "]"
"[" <array_access_tail>
| "." <identifier>
| "::" <identifier> ( "<" <types_list> ">" )?
| "->" <identifier>
| ".@" <identifier>?
| ".[" <expression> "]"
| ".#"
| ".*"
<array_access_tail> =
<expression> <slice_or_index_tail>
| ":" <expression>? "]"
<slice_or_index_tail> =
"]"
| ":" <expression>? "]"
/* --- Type System --- */
/* Rules for defining types, type names, and type qualifiers. */
@ -307,11 +330,10 @@
| "?" <type_qualifier_chain_after_optional>?
<type_name> =
<namespaced_identifier> ( "<" <types_list> ">" )?
<access_expression> ( "::" <identifier> ( "<" <types_list> ">" )? )*
<namespaced_identifier> =
<identifier>
| <identifier> "::" <namespaced_identifier>
<identifier> ( "::" identifier )*
<types_list> =
<type> ( "," <types_list> )*