# JOURNAL — parse phase ## Session 1 (2026-06-16) Starting parse phase. Lex phase complete (11 tests green). ### Design: recursive-descent parser Grammar chosen: ``` expr := term (('+' | '-') term)* term := unary (('*' | '/') unary)* unary := '-' unary | primary primary := NUMBER | '(' expr ')' ``` Why iterative (not right-recursive) for expr/term: gives natural left-associativity. Why unary is right-recursive: `-` chains right, e.g. `--5` = `-(-(5))`. ### Test run results (2026-06-16) ``` python -m unittest -v Ran 35 tests in 0.001s OK ``` All 24 parser tests + 11 lexer tests green on first attempt. Verified shapes: - `1+2*3` → `BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))` ✓ D1 - `8-3-2` → `BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))` ✓ D2 - `(1+2)*3` → `BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))` ✓ D3 - `-5` → `Unary('-', Num(5))` ✓ D4 - `3 * -2` → `BinOp('*', Num(3), Unary('-', Num(2)))` ✓ D4 - `1 +` → `ParseError: unexpected end of input` ✓ D5 AST nodes (dataclasses): - `Num(value: int | float)` — leaf - `BinOp(op: str, left: Node, right: Node)` — binary operation - `Unary(op: str, operand: Node)` — unary minus (op='-')