# STATUS-parse Commit: 14d6662 ## AST Shape (contract for eval phase) ``` Num(value) — numeric literal; value is int or float BinOp(op, left, right) — binary operation; op in ('+', '-', '*', '/') Unary(op, operand) — unary minus; op == '-' ``` All nodes support `__repr__` and `__eq__`. Import from `calc.parser`. ## Gate Verification ### D1 — precedence **What:** `*` and `/` bind tighter than `+` and `-` **Command:** `python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('1+2*3')))"` **Expected:** `BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))` **Observed:** ``` BinOp('+', Num(1), BinOp('*', Num(2), Num(3))) ``` Result: **PASS** ### D2 — left associativity **What:** Same-precedence operators fold left: `8-3-2` → `(8-3)-2`; `8/4/2` → `(8/4)/2` **Command:** ```python str(parse(tokenize('8-3-2'))) == "BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))" str(parse(tokenize('8/4/2'))) == "BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))" ``` **Observed:** Both assertions pass (confirmed via edge-case script) Result: **PASS** ### D3 — parentheses **What:** `(1+2)*3` places `+` under `*` **Command:** ```python str(parse(tokenize('(1+2)*3'))) == "BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))" ``` **Observed:** Assertion passes (confirmed via edge-case script) Result: **PASS** ### D4 — unary minus **What:** `-5`, `-(1+2)`, `3 * -2` all parse correctly **Commands:** ```python str(parse(tokenize('-5'))) == "Unary('-', Num(5))" str(parse(tokenize('-(1+2)'))) == "Unary('-', BinOp('+', Num(1), Num(2)))" str(parse(tokenize('3 * -2'))) == "BinOp('*', Num(3), Unary('-', Num(2)))" ``` **Observed:** All three assertions pass (confirmed via edge-case script) Result: **PASS** ### D5 — errors **What:** `"1 +"`, `"(1"`, `"1 2"`, `")("`, `""` each raise `ParseError` (not any other exception) **Command:** ```python for bad in ['1 +', '(1', '1 2', ')(', '']: try: parse(tokenize(bad)); raise AssertionError(...) except ParseError: pass ``` **Observed:** All five inputs raised `ParseError`; spot check of `"1 +"`: ``` calc.parser.ParseError: unexpected end of expression ``` Result: **PASS** ### D6 — tests green **What:** `python -m unittest -q` passes, 0 failures, 37 tests total (14 lexer + 23 parser) **Command:** `python -m unittest -q` **Observed:** ``` Ran 37 tests in 0.001s OK ``` Result: **PASS** ## DONE