3.7 KiB
REVIEW — phase lex (Adversary)
Last updated: 2026-06-15T05:08:00Z
Status
All 4 gates PASSED. Phase is DONE pending Builder writing "## DONE" to STATUS.
Gates
| Gate | Status | Timestamp | Notes |
|---|---|---|---|
| D1 | PASS | 2026-06-15T05:06:00Z | All number forms correct |
| D2 | PASS | 2026-06-15T05:07:00Z | All operators/parens correct |
| D3 | PASS | 2026-06-15T05:07:30Z | Whitespace skipped, LexError raised with char+position |
| D4 | PASS | 2026-06-15T05:08:00Z | 23 tests, 0 failures; all plan cold-verify commands pass |
Detailed verdicts
lex/D1: PASS @2026-06-15T05:06:00Z
Cold-start verification from own clone. All Builder-provided checks pass:
tokenize('42')→[NUMBER(42), EOF], value isint✓tokenize('3.14')→NUMBER(3.14)float ✓tokenize('.5')→NUMBER(0.5)float ✓tokenize('10.')→NUMBER(10.0)float ✓- list-equality with
Token('NUMBER',42)andToken('EOF',None)✓
Independent break-it probes:
tokenize('')→[EOF]✓tokenize('0')→NUMBER(0)int ✓tokenize('999999999999')→ large int ✓- NOTED (not D1 scope):
tokenize('.')raisesValueErrornotLexError— filed as finding F1
lex/D2: PASS @2026-06-15T05:07:00Z
Cold-start verification. All Builder-provided checks pass:
tokenize('1+2*3')→ kinds['NUMBER','PLUS','NUMBER','STAR','NUMBER','EOF']✓- All 6 single-char operators tokenize to correct kinds ✓
Independent break-it probes:
- Tab whitespace skipped ✓
- Operator value is the character itself (e.g.
'+') — acceptable per design ✓ - Nested parens
((1))tokenize correctly ✓
lex/D3: PASS @2026-06-15T05:07:30Z
Cold-start verification. All Builder-provided checks pass:
tokenize(' 12 + 3 ')→['NUMBER','PLUS','NUMBER','EOF'], values 12 and 3 ✓tokenize('1 @ 2')raisesLexErrorwith@and position2in message ✓tokenize('abc')raisesLexError✓
Independent break-it probes:
- Tab whitespace skipped ✓
tokenize('$')raisesLexErrorat position 0 ✓- NOTED:
tokenize('.')raises bareValueErrornotLexError— same as F1 below - NOTED:
tokenize('1.2.3')raises bareValueErrornotLexError— F1 covers this
DoD for D3 specifies @, $, letters as examples of invalid chars. The standalone-dot
edge case is not in the explicit DoD and the plan's mandated test suite does not include it.
PASS granted; finding F1 is advisory for the Builder's consideration.
lex/D4: PASS @2026-06-15T05:08:00Z
Cold-start verification. Plan's exact commands run:
python -m unittest -q→Ran 23 tests in 0.000s OK✓tokenize('3.5*(1-2)')→[('NUMBER',3.5),('STAR','*'),('LPAREN','('),('NUMBER',1),('MINUS','-'),('NUMBER',2),('RPAREN',')'),('EOF',None)]✓tokenize('1 @ 2')→ raisescalc.lexer.LexError: unexpected character '@' at position 2✓
Mandated test cases present in calc/test_lexer.py:
" 12 + 3 "✓ (line 79, 84)"3.5*(1-2)"✓ (line 71, 118)"1 @ 2"raises LexError ✓ (lines 93, 105, 112)
Adversary findings
F1 (advisory) — malformed float literals raise ValueError not LexError
Severity: Low — not in explicit DoD, no test covers it.
Repro:
from calc.lexer import tokenize
tokenize('.') # raises ValueError, not LexError
tokenize('1.2.3') # raises ValueError, not LexError
Expected: LexError (consistent with the module's error contract).
Actual: ValueError: could not convert string to float: '.'
Recommendation: Wrap the float() call in a try/except and re-raise as LexError.
This is advisory — does not block DONE since it falls outside D1–D3's explicit DoD requirements.