Fix: add assignment as right-associative expression

`=` was missing from the Pratt table, causing `a = b;` to fail with
"expected `;`, found `=`". Assignment is now BinaryOp::Assign with
binding power (2, 2) — lowest precedence, right-associative — so
`a = b = c` parses as `a = (b = c)`.
This commit is contained in:
2026-03-10 18:10:35 +01:00
parent 546dc119d0
commit 1a4e464d5e
4 changed files with 100 additions and 24 deletions

View File

@@ -33,7 +33,23 @@ top_level_def = func_def
(* Expressions *)
(* ================================================================ *)
expr = or_expr ;
expr = assign_expr ;
(* --- Assignment (lowest-precedence binary operator) --- *)
(* *)
(* Uses token `=`; right-associative via recursion. *)
(* The optional form encodes at-most-one assignment target: chains *)
(* like `a = b = c` parse as `a = (b = c)` thanks to right *)
(* recursion. *)
(* *)
(* LL(1): after or_expr, peek at next token. *)
(* "=" consume and recurse into assign_expr *)
(* other return the or_expr as-is *)
(* "=" is not in FIRST(stmt), so expr_stmt can still be *)
(* distinguished from other statement kinds. *)
assign_expr = or_expr , [ "=" , assign_expr ] ;
(* --- Logical OR (lowest-precedence binary operator) --- *)
@@ -165,7 +181,9 @@ arg_list = [ expr , { "," , expr } ] ;
(* if_stmt and while_stmt use expr_ns for their condition. *)
(* All other expression positions use the full expr. *)
expr_ns = or_expr_ns ;
expr_ns = assign_expr_ns ;
assign_expr_ns = or_expr_ns , [ "=" , assign_expr_ns ] ;
or_expr_ns = and_expr_ns , { "or" , and_expr_ns } ;
and_expr_ns = bitor_expr_ns , { "and" , bitor_expr_ns } ;