fix(grammar): Simplify and improve EBNF definition

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

The EBNF grammar definition contained several redundancies,
inconsistencies, and minor omissions. This commit refactors the grammar
to make it more concise, readable, and robust for parsing.

Key changes include:

- **Rule Simplification**: Redundant intermediate rules (`fn_params`,
  `statements`, `assign_expression`) have been removed. Rules like
  `code_block` and `import_target` are now more concisely expressed
  using standard EBNF operators (`?`, `*`).

- **EOF Enforcement**: The top-level `program` rule now requires an
  `<eof>` token. This is a crucial fix to ensure the parser consumes the
  entire file and fails on trailing invalid tokens.

- **Optional Generics**: Generic parameters (`<... >`) are now correctly
  marked as optional on `function`, `struct`, and `enum` declarations,
  which was the original intent.

- **Flexible For-Loops**: The update/increment expression (the third
  part) in a C-style `for` loop is now optional, aligning with behavior
  in languages like C and C++.

- **Primary Expressions**: Primary type expressions failed to parse
  correctly namespaced elements and types, now it's fixed and improved.
This commit is contained in:
erick-alcachofa 2025-10-05 14:49:50 -06:00
parent bb58b17528
commit f5be339f43
Signed by: me
GPG Key ID: 6FA5F8643444BAFA

View File

@ -7,7 +7,6 @@
================================================================================
*/
/* --- Program Structure --- */
/* A program is a sequence of top-level declarations and statements. */
@ -18,6 +17,7 @@
| <struct_declaration>
| <enum_declaration>
| <function_declaration> )*
<eof>
<module_statement> =
"export"? "module" <namespaced_identifier> "{"
@ -32,8 +32,7 @@
"import" <import_target> ";"
<import_target> =
<namespaced_identifier>
| <namespaced_identifier> "::" "*"
<namespaced_identifier> ( "::" "*" )?
<alias_statement> =
"using" <identifier> "=" <namespaced_identifier> ";"
@ -43,10 +42,7 @@
/* Rules for defining functions, structs, enums, and their components. */
<function_declaration> =
"export"? "fn" <identifier> <generic_params> "(" <fn_params> ")" ( "->" <type> )? <code_block>
<fn_params> =
<fn_params_list>?
"export"? "fn" <identifier> <generic_params>? "(" <fn_params_list>? ")" ( "->" <type> )? <code_block>
<fn_params_list> =
"this" <type> ("," <fn_param> ( "," <fn_param> )* )?
@ -56,7 +52,7 @@
<identifier> ":" <type>
<struct_declaration> =
"export"? "struct" <identifier> <generic_params> "{" <struct_members> "}"
"export"? "struct" <identifier> <generic_params>? "{" <struct_members> "}"
<struct_members> =
<struct_member> ( "," <struct_member> )*
@ -65,7 +61,7 @@
<identifier> ":" <type>
<enum_declaration> =
"export"? "enum" <identifier> <generic_params> "{" <enum_members> "}"
"export"? "enum" <identifier> <generic_params>? "{" <enum_members> "}"
<enum_members> =
<enum_member> ( "," <enum_member> )*
@ -74,7 +70,7 @@
<identifier> ( "(" <type> ")" )?
<generic_params> =
( "<" <generic_params_list> ">" )?
"<" <generic_params_list> ">"
<generic_params_list> =
<generic_param> ( "," <generic_param> )*
@ -87,10 +83,7 @@
/* Rules for code blocks, variable declarations, and control structures. */
<code_block> =
"{" <statements>? "}"
<statements> =
<statement> ( <statement> )*
"{" <statement>* "}"
<statement> =
<variable_declaration> ";"
@ -101,7 +94,7 @@
| <return_statement> ";"
| <break_statement> ";"
| <continue_statement> ";"
| <expression_statement>
| <expression> ";"
| <alias_statement>
| <match_statement>
| <switch_statement>
@ -135,7 +128,7 @@
)
<c_for_statement> =
"for" "(" <variable_declaration>? ";" <expression> ";" <expression> ")"
"for" "(" <variable_declaration>? ";" <expression> ";" <expression>? ")"
<code_block>
<range_for_statement> =
@ -182,17 +175,11 @@
<return_statement> =
"return" <expression>?
<expression_statement> =
<expression> ";"
/* --- Expressions & Operator Precedence --- */
/* The full expression hierarchy, from lowest to highest precedence. */
<expression> =
<assign_expression>
<assign_expression> =
<bool_or_expression> ( ( <assign_op> | <compound_assign_op> ) <expression> )?
<bool_or_expression> =
@ -227,16 +214,17 @@
/* The highest-precedence expressions, including literals and grouped expressions. */
<primary_type_expression> =
<char_literal>
<grouped_expression>
| <scoped_access_expression>
| <reflection_expression>
| <struct_literal>
| <type_name>
| <char_literal>
| <null_literal>
| <string_literal>
| <number_literal>
| <boolean_literal>
| <grouped_expression>
| <identifier>
| <struct_literal>
| <scoped_access_expression>
| <reflection_expression>
<grouped_expression> =
"(" <expression> ")"
@ -245,7 +233,7 @@
<type_name> "::" <identifier>
<reflection_expression> =
( <primary_expression> | <type_name> | <scoped_access_expression> ) ".@" <identifier>?
( <type_name> | <scoped_access_expression> ) ".@" <identifier>?
<fn_call_arguments> =
"(" <expression_list> ")"
@ -292,9 +280,10 @@
<suffix_op> =
"[" <expression>? ":" <expression>? "]"
| "[" <expression> "]"
| ".[" <expression> "]"
| "." <identifier>
| "->" <identifier>
| ".@" <identifier>?
| ".[" <expression> "]"
| ".#"
| ".*"
@ -302,7 +291,7 @@
/* Rules for defining types, type names, and type qualifiers. */
<type> =
<type_qualifier_chain> <type_name>
<type_qualifier_chain>? <type_name>
<type_qualifier_chain> =
( "*" | "[]" ) <type_qualifier_chain>?
@ -345,4 +334,4 @@
<nonzero_digit> = [1-9]
<empty> = E /* Represents an empty terminal string */
<eof> = /* End Of File */