program → (func_decl | struct_decl)+ ;
==== STATEMENTS ====
statement → declaration
| for_stmt
| while_stmt
| if_stmt
| return_stmt
| expr_stmt
| block ;
==== DECLARATIONS ====
declaration → func_decl
| struct_decl
| var_decl
| sym_decl ;
func_decl → "df" ident "(" params? ")" type? block ;
struct_decl → "struct" ident "{" struct_fields? "}" ;
var_decl → "let" ident ":" type "=" initializer ";" ;
sym_decl → "sym" ident "=" ident ";" ;
for_stmt → "for" ident "in" expr_no_init ".." expr_no_init block
| "for" ident "in" expr_no_init block ;
while_stmt → "while" expr_no_init block ;
if_stmt → "if" expr_no_init block ("else" block)? ;
return_stmt → "return" expr ";" ;
block → "{" statement* "}" ;
expr_stmt → expr ";" ;
==== EXPRESSIONS ====
expr → assignment ;
assignment → ident ("." ident)* "=" initializer
| initializer ;
initializer → logic_or struct_init? ;
expr_no_init → logic_or ;
logic_or → logic_and ("or" logic_and)* ;
logic_and → equality ("and" equality)* ;
equality → inequality (("==" | "!=") inequality)* ;
inequality → term ((">" | ">=" | "<" | "<=") term)* ;
term → factor (("+" | "-") factor)* ;
factor → unary (("*" | "/") unary)* ;
unary → ("!" | "-") unary | call ;
call → primary ("(" args? ")" | "[" expr "]" | "." ident)* ;
struct_init → "{" ident ":" expr ("," ident ":" expr)* "}" ;
primary → "true" | "false" | ident | number | string | "(" expr ")" ;
==== LITERALS ====
ident → letter (letter | digit | "_")* ;
type → ident ;
string → "\"" [^"]* "\"" ;
number → "0" | [1-9] digit* ("." digit+)? ;
letter → [a-zA-Z] ;
digit → [0-9] ;
==== UTILITIES ====
params → ident ":" type ("," ident ":" type)* ;
struct_fields → ("pub")? ident ":" type ("," ("pub")? ident ":" type)* ;
args → expr ("," expr)* ;