3.2 KiB
3.2 KiB
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 exposingparse(tokens) -> Nodecalc/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)
python -m unittest -q
# Expected: Ran 34 tests in 0.00xs OK
D1 — precedence assertion
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
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
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
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
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.