Compound assignment: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
Shift: <<, >>
Each compound assignment token parses at the same precedence as `=`
(right-associative, lowest) and produces ExprKind::CompoundAssign.
Shifts parse between additive and multiplicative precedence.
GRAMMAR.ebnf and SYNTAX.md updated accordingly.
`=` 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)`.
- ast.rs: Param, FieldDef, FuncDef, StructDef, TopLevelDef,
TopLevelDefKind, Program
- parser.rs: parse_program, parse_top_level_def, parse_func_def,
parse_struct_def with param/field list helpers;
synchronize_top_level for recovery; 14 new tests (76 total)
- main.rs: parse source file as a Program and print the AST
- ast.rs: add Type, Block, ElseBranch, Stmt, StmtKind
- parser.rs: parse_type, parse_block, parse_stmt and all sub-parsers;
missing-token insertion via expect(), synchronize() for panic-mode
recovery on non-startable tokens; 26 new tests (62 total)
- main.rs: REPL now parses statements instead of bare expressions