3.5 KiB
3.5 KiB
REVIEW — Phase parse (Adversary)
Status
All gates PASS. Ready to approve ## DONE.
Gate verdicts
| Gate | Verdict | Timestamp | Evidence |
|---|---|---|---|
| D1 — precedence | PASS | 2026-06-15T00:22:39Z | See below |
| D2 — left associativity | PASS | 2026-06-15T00:22:39Z | See below |
| D3 — parentheses | PASS | 2026-06-15T00:22:39Z | See below |
| D4 — unary minus | PASS | 2026-06-15T00:22:39Z | See below |
| D5 — errors | PASS | 2026-06-15T00:22:39Z | See below |
| D6 — tests green | PASS | 2026-06-15T00:22:39Z | Ran 45 tests in 0.001s OK |
Cold-verification evidence
D6 — tests green
python -m unittest -q
Ran 45 tests in 0.001s
OK
21 lexer + 24 parser tests, 0 failures.
D1 — precedence (cold AST shape check)
1+2*3 → BinOp('+', Num(1), BinOp('*', Num(2), Num(3))) ✓ (* binds tighter)
2*3+4 → BinOp('+', BinOp('*', Num(2), Num(3)), Num(4)) ✓
10-6/2 → BinOp('-', Num(10), BinOp('/', Num(6), Num(2))) ✓
Independently derived: 1+2*3 must have + at root with * in right child — confirmed.
D2 — left associativity (cold AST shape check)
8-3-2 → BinOp('-', BinOp('-', Num(8), Num(3)), Num(2)) ✓ (left-assoc)
8/4/2 → BinOp('/', BinOp('/', Num(8), Num(4)), Num(2)) ✓
1+2+3 → BinOp('+', BinOp('+', Num(1), Num(2)), Num(3)) ✓
2*3*4 → BinOp('*', BinOp('*', Num(2), Num(3)), Num(4)) ✓
1-2-3 → BinOp('-', BinOp('-', Num(1), Num(2)), Num(3)) ✓ (break-it: not right-assoc)
Iterative while-loop in _expr/_term enforces left-assoc by construction.
D3 — parentheses (cold AST shape check)
(1+2)*3 → BinOp('*', BinOp('+', Num(1), Num(2)), Num(3)) ✓
3*(1+2) → BinOp('*', Num(3), BinOp('+', Num(1), Num(2))) ✓
((4)) → Num(4) ✓
8-(3-2) → BinOp('-', Num(8), BinOp('-', Num(3), Num(2))) ✓
((((1+2)))) → BinOp('+', Num(1), Num(2)) ✓ (deep nesting)
D4 — unary minus (cold AST shape check)
-5 → Unary('-', Num(5)) ✓
-(1+2) → Unary('-', BinOp('+', Num(1), Num(2))) ✓
3 * -2 → BinOp('*', Num(3), Unary('-', Num(2))) ✓
--5 → Unary('-', Unary('-', Num(5))) ✓
1 + -2 → BinOp('+', Num(1), Unary('-', Num(2))) ✓
---5 → Unary('-', Unary('-', Unary('-', Num(5)))) ✓ (break-it: triple unary)
6 / -2 → BinOp('/', Num(6), Unary('-', Num(2))) ✓ (break-it: unary in denom)
_unary is right-recursive: '-' _unary | _primary — correct for unary.
D5 — errors (cold: all five plan cases + extras)
'1 +' → OK ParseError
'(1' → OK ParseError
'1 2' → OK ParseError
')(' → OK ParseError
'' → OK ParseError
'*' → OK ParseError (break-it)
')' → OK ParseError (break-it)
'1+2)' → OK ParseError (break-it)
'((1+2)' → OK ParseError (break-it)
All raise ParseError specifically, not a generic exception.
Break-it probes run
- Right-assoc trap (
1-2-3,8-3-2,8/4/2): held — correctly left-assoc - Deep nesting
((((1+2)))): held - Triple unary
---5: held - Unary in denominator
6/-2: held - Float literal
3.14 → Num(3.14): parsed fine - Trailing
)after valid expr1+2): ParseError ✓ - Solo operator
*: ParseError ✓ - Double-unclosed paren
((1+2): ParseError ✓
Adversary findings
None. No defects found. All probes held.