2.3 KiB
2.3 KiB
Adversary Review — phase parse
Verdicts
| Gate | Result | Evidence |
|---|---|---|
| D1 | PASS | parse(tokenize('1+2*3')) → BinOp('+', Num(1), BinOp('*', Num(2), Num(3))) |
| D2 | PASS | 8-3-2 → BinOp('-', BinOp('-', Num(8), Num(3)), Num(2)); 8/4/2 → BinOp('/', BinOp('/', Num(8), Num(4)), Num(2)) |
| D3 | PASS | (1+2)*3 → BinOp('*', BinOp('+', Num(1), Num(2)), Num(3)) |
| D4 | PASS | -5 → Unary('-', Num(5)); -(1+2) → Unary('-', BinOp('+', ...)); 3 * -2 → BinOp('*', Num(3), Unary('-', Num(2))); --5 → Unary('-', Unary('-', Num(5))) |
| D5 | PASS | All 5 cases '1 +', '(1', '1 2', ')(', '' raise ParseError (not any other exception) |
| D6 | PASS | python -m unittest -q → Ran 33 tests in 0.001s OK |
Cold-run commands executed
python -m unittest -q
python -c "... parse(tokenize('1+2*3'))" # D1
python -c "... parse(tokenize('4+6/2'))" # D1
python -c "... parse(tokenize('8-3-2'))" # D2
python -c "... parse(tokenize('8/4/2'))" # D2
python -c "... parse(tokenize('(1+2)*3'))" # D3
python -c "... parse(tokenize('-5'))" # D4
python -c "... parse(tokenize('-(1+2)'))" # D4
python -c "... parse(tokenize('3 * -2'))" # D4
python -c "... parse(tokenize('--5'))" # D4 extra
python -c "... [all 5 error cases]" # D5
Extra edge cases (adversarial):
()→ ParseError ✓1++2→ ParseError ✓ (no unary plus)1 + + 2→ ParseError ✓*3→ ParseError ✓1*(2+3)*4→BinOp('*', BinOp('*', Num(1), BinOp('+', Num(2), Num(3))), Num(4))✓-1+2→BinOp('+', Unary('-', Num(1)), Num(2))✓1+2*3+4→BinOp('+', BinOp('+', Num(1), BinOp('*', Num(2), Num(3))), Num(4))✓
Notes
- The
if not tokens: raise ParseError("Empty token list")guard inparse()is dead code —tokenize("")always appends an EOF token so the list is never empty. The empty-string case still raisesParseErrorcorrectly viaprimary()seeing EOF. Not a bug; harmless dead code. - Grammar structure (expr → term → unary → primary) correctly encodes precedence and left-associativity by construction.
Summary
review(parse): PASS D1,D2,D3,D4,D5,D6 — cold-verified all gates @2026-06-15T02:00Z