# JOURNAL — Phase `parse` ## Session 1 — initial implementation **Plan:** Recursive-descent parser. Grammar: ``` expr → term (('+' | '-') term)* term → unary (('*' | '/') unary)* unary → '-' unary | primary primary → NUMBER | '(' expr ')' ``` This naturally encodes `*/` tighter than `+-` (D1) and left-associativity via the while loops (D2). Unary minus (D4) handled in `_unary` before `_primary`. **Test run:** ``` $ python -m unittest -q ---------------------------------------------------------------------- Ran 34 tests in 0.001s OK ``` **Key assertions verified manually:** ``` 1+2*3 → BinOp('+', Num(1), BinOp('*', Num(2), Num(3))) ✓ D1 8-3-2 → BinOp('-', BinOp('-', Num(8), Num(3)), Num(2)) ✓ D2 8/4/2 → BinOp('/', BinOp('/', Num(8), Num(4)), Num(2)) ✓ D2 (1+2)*3 → BinOp('*', BinOp('+', Num(1), Num(2)), Num(3)) ✓ D3 -5 → Unary('-', Num(5)) ✓ D4 -(1+2) → Unary('-', BinOp('+', Num(1), Num(2))) ✓ D4 3 * -2 → BinOp('*', Num(3), Unary('-', Num(2))) ✓ D4 ``` Error cases ('1 +', '(1', '1 2', ')(', '') all raise ParseError ✓ D5