4.0 KiB
STATUS — phase lex
Role: Adversary initializes this file to bootstrap the phase. Builder owns updates.
Current state: BUILDING — All gates CLAIMED, awaiting Adversary verification
Gates:
- D1: CLAIMED (awaiting Adversary verification)
- D2: CLAIMED (awaiting Adversary verification)
- D3: CLAIMED (awaiting Adversary verification)
- D4: CLAIMED (awaiting Adversary verification)
Gate D1 — Numbers
WHAT: Integers and floats tokenize to a single NUMBER token with numeric value (int or float). EOF appended.
HOW to verify:
python -c "from calc.lexer import tokenize; r=tokenize('42'); assert r[0].kind=='NUMBER'; assert r[0].value==42; assert isinstance(r[0].value,int); assert r[1].kind=='EOF'; print('D1 int OK')"
python -c "from calc.lexer import tokenize; r=tokenize('3.14'); assert r[0].kind=='NUMBER'; assert abs(r[0].value-3.14)<1e-9; assert isinstance(r[0].value,float); print('D1 float OK')"
python -c "from calc.lexer import tokenize; r=tokenize('.5'); assert r[0].kind=='NUMBER'; assert r[0].value==0.5; print('D1 leading-dot OK')"
python -c "from calc.lexer import tokenize; r=tokenize('10.'); assert r[0].kind=='NUMBER'; assert r[0].value==10.0; print('D1 trailing-dot OK')"
EXPECTED: Each prints its "OK" line, no exceptions.
WHERE: calc/lexer.py at commit 98f1455
Gate D2 — Operators & Parens
WHAT: + - * / ( ) each map to PLUS, MINUS, STAR, SLASH, LPAREN, RPAREN respectively. tokenize("1+2*3") yields NUMBER PLUS NUMBER STAR NUMBER EOF.
HOW to verify:
python -c "
from calc.lexer import tokenize
r = tokenize('1+2*3')
kinds = [t.kind for t in r]
assert kinds == ['NUMBER','PLUS','NUMBER','STAR','NUMBER','EOF'], kinds
print('D2 expression OK')
"
python -c "
from calc.lexer import tokenize
ops = '+-*/()'
expected = ['PLUS','MINUS','STAR','SLASH','LPAREN','RPAREN']
for ch, exp in zip(ops, expected):
r = tokenize(ch)
assert r[0].kind == exp, f'{ch} -> {r[0].kind}'
print('D2 single-ops OK')
"
EXPECTED: Prints D2 expression OK and D2 single-ops OK, no exceptions.
WHERE: calc/lexer.py at commit 98f1455
Gate D3 — Whitespace & Errors
WHAT: Spaces/tabs between tokens are skipped. Invalid characters raise LexError with the offending character and its position in the message.
HOW to verify:
python -c "
from calc.lexer import tokenize
r = tokenize(' 12 + 3 ')
kinds = [t.kind for t in r]
assert kinds == ['NUMBER','PLUS','NUMBER','EOF'], kinds
assert r[0].value == 12
assert r[2].value == 3
print('D3 whitespace OK')
"
python -c "
from calc.lexer import tokenize, LexError
try:
tokenize('1 @ 2')
raise AssertionError('should have raised')
except LexError as e:
msg = str(e)
assert '@' in msg, msg
assert '2' in msg, msg
print('D3 LexError OK:', msg)
"
python -c "
from calc.lexer import tokenize, LexError
try:
tokenize('abc')
raise AssertionError('should have raised')
except LexError as e:
print('D3 letter raises LexError OK')
"
EXPECTED: Prints D3 whitespace OK, D3 LexError OK: ..., D3 letter raises LexError OK.
WHERE: calc/lexer.py at commit 98f1455
Gate D4 — Tests Green
WHAT: calc/test_lexer.py (unittest) passes under python -m unittest, 0 failures, covering D1–D3 including the three mandated cases: " 12 + 3 ", "3.5*(1-2)", and "1 @ 2" raising LexError.
HOW to verify:
python -m unittest -q
EXPECTED output:
..............................
Ran 23 tests in 0.00Xs
OK
(23 tests, 0 failures, 0 errors)
Also run the plan's exact cold-verify commands:
python -c "from calc.lexer import tokenize; print([(t.kind,t.value) for t in tokenize('3.5*(1-2)')])"
# Expected: [('NUMBER', 3.5), ('STAR', '*'), ('LPAREN', '('), ('NUMBER', 1), ('MINUS', '-'), ('NUMBER', 2), ('RPAREN', ')'), ('EOF', None)]
python -c "from calc.lexer import tokenize; tokenize('1 @ 2')"
# Expected: raises LexError (traceback shown)
WHERE: calc/test_lexer.py and calc/lexer.py at commit 98f1455