# STATUS — phase parse ## DONE All gates D1–D6 Adversary-verified PASS @2026-06-15T04:22:33Z. No vetoes. Phase complete. --- ## Gates: D1–D6 CLAIMED, awaiting Adversary All six gates implemented and locally verified. Claiming all simultaneously. --- ## AST node shapes (stable contract for evaluator) - `Num(value)` — leaf; `value` is `int` or `float` - `BinOp(op, left, right)` — binary op; `op` is `'PLUS'|'MINUS'|'STAR'|'SLASH'` - `Unary(op, operand)` — unary minus; `op` is `'MINUS'` All nodes are frozen `@dataclass`s with `__repr__` and `__eq__` derived from fields. Defined in `calc/parser.py`. --- ## D1 — precedence (CLAIMED) **WHAT:** `*`/`/` bind tighter than `+`/`-`: `1+2*3` parses as `BinOp('PLUS', Num(1), BinOp('STAR', Num(2), Num(3)))`. **HOW:** ```bash python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('1+2*3')))" ``` **EXPECTED:** ``` BinOp('PLUS', Num(1), BinOp('STAR', Num(2), Num(3))) ``` **WHERE:** `calc/parser.py` — `expr()` loops over `+/-`, `term()` loops over `*//`. --- ## D2 — left associativity (CLAIMED) **WHAT:** Same-precedence operators associate left. - `8-3-2` → `BinOp('MINUS', BinOp('MINUS', Num(8), Num(3)), Num(2))` - `8/4/2` → `BinOp('SLASH', BinOp('SLASH', Num(8), Num(4)), Num(2))` **HOW:** ```bash python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8-3-2')))" python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8/4/2')))" ``` **EXPECTED:** ``` BinOp('MINUS', BinOp('MINUS', Num(8), Num(3)), Num(2)) BinOp('SLASH', BinOp('SLASH', Num(8), Num(4)), Num(2)) ``` **WHERE:** `calc/parser.py` — `while` loops in `expr()` and `term()` fold left. --- ## D3 — parentheses (CLAIMED) **WHAT:** Parens override precedence: `(1+2)*3` → `BinOp('STAR', BinOp('PLUS', Num(1), Num(2)), Num(3))`. **HOW:** ```bash python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('(1+2)*3')))" ``` **EXPECTED:** ``` BinOp('STAR', BinOp('PLUS', Num(1), Num(2)), Num(3)) ``` **WHERE:** `calc/parser.py` — `primary()` handles `LPAREN … RPAREN`. --- ## D4 — unary minus (CLAIMED) **WHAT:** Leading and nested unary minus works. - `-5` → `Unary('MINUS', Num(5))` - `-(1+2)` → `Unary('MINUS', BinOp('PLUS', Num(1), Num(2)))` - `3 * -2` → `BinOp('STAR', Num(3), Unary('MINUS', Num(2)))` **HOW:** ```bash python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-5')))" python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-(1+2)')))" python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('3 * -2')))" ``` **EXPECTED:** ``` Unary('MINUS', Num(5)) Unary('MINUS', BinOp('PLUS', Num(1), Num(2))) BinOp('STAR', Num(3), Unary('MINUS', Num(2))) ``` **WHERE:** `calc/parser.py` — `unary()` intercepts `MINUS` before `primary()`. --- ## D5 — errors (CLAIMED) **WHAT:** Each malformed input raises `ParseError` (not any other exception). **HOW:** ```bash python -c " from calc.lexer import tokenize from calc.parser import parse, ParseError cases = ['1 +', '(1', '1 2', ')(', ''] for src in cases: try: parse(tokenize(src)) print('FAIL — no error for', repr(src)) except ParseError as e: print('OK', repr(src), '->', e) " ``` **EXPECTED (all OK lines):** ``` OK '1 +' -> unexpected token 'EOF' OK '(1' -> expected ')', got 'EOF' OK '1 2' -> unexpected token 'NUMBER' after expression OK ')(' -> unexpected token 'RPAREN' OK '' -> unexpected token 'EOF' ``` **WHERE:** `calc/parser.py` — `primary()` raises on bad token; trailing-token check after `expr()`. --- ## D6 — tests green (CLAIMED) **WHAT:** `python -m unittest -q` runs 39 tests (17 lex + 22 parser), 0 failures. **HOW:** ```bash python -m unittest -q ``` **EXPECTED:** ``` ---------------------------------------------------------------------- Ran 39 tests in ...s OK ``` **WHERE:** `calc/test_parser.py` — 22 tests across 5 classes (TestPrecedence, TestLeftAssociativity, TestParentheses, TestUnaryMinus, TestErrors).