# STATUS-parse Phase: `parse` Builder: CLAIMING D1–D6 ## Claims | Gate | DoD item | Status | |------|----------|--------| | D1 | Correct precedence: `*`/`/` bind tighter than `+`/`-` | CLAIMED | | D2 | Left associativity for same-precedence operators | CLAIMED | | D3 | Parentheses override precedence | CLAIMED | | D4 | Unary minus (leading, nested, after operator) | CLAIMED | | D5 | Malformed input raises `ParseError` | CLAIMED | | D6 | `calc/test_parser.py` passes: 34 tests, 0 failures | CLAIMED | ## Implementation - **`calc/parser.py`** — recursive-descent parser exposing `parse(tokens) -> Node` - **`calc/test_parser.py`** — unittest suite covering D1–D5 (34 tests) ### AST node shapes ``` Num(value) # value: int | float BinOp(op, left, right) # op: '+' | '-' | '*' | '/' Unary(op, operand) # op: '-' ``` ## Verify (cold) ```bash python -m unittest -q # Expected: Ran 34 tests in 0.00xs OK ``` ### D1 — precedence assertion ```bash 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))) ``` The `*` is in the subtree (right of `+`), proving `*` binds tighter. ### D2 — left associativity assertions ```bash python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8-3-2')))" # Expected: BinOp('-', BinOp('-', Num(8), Num(3)), Num(2)) python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8/4/2')))" # Expected: BinOp('/', BinOp('/', Num(8), Num(4)), Num(2)) ``` ### D3 — parentheses assertion ```bash python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('(1+2)*3')))" # Expected: BinOp('*', BinOp('+', Num(1), Num(2)), Num(3)) ``` ### D4 — unary minus assertions ```bash python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-5')))" # Expected: Unary('-', Num(5)) python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-(1+2)')))" # Expected: Unary('-', BinOp('+', Num(1), Num(2))) python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('3 * -2')))" # Expected: BinOp('*', Num(3), Unary('-', Num(2))) ``` ### D5 — error assertions ```bash python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize('1 +'))" 2>&1 | grep ParseError # Expected: line containing "calc.parser.ParseError" python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize('(1'))" 2>&1 | grep ParseError python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize('1 2'))" 2>&1 | grep ParseError python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize(')('))" 2>&1 | grep ParseError python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize(''))" 2>&1 | grep ParseError ``` All five raise `calc.parser.ParseError`. ## Commit Implemented at HEAD (see `git log --oneline -1` after push). ## DONE All D1–D6 gates verified PASS by Adversary at 2026-06-15T03:28Z (commit d97df78). Phase complete.