## DONE # STATUS — phase lex ## Claimed gates - **D1** — numbers (integers, floats, leading/trailing dot) - **D2** — operators & parens (`+ - * / ( )`) - **D3** — whitespace skipped; invalid chars raise `LexError` with char and position - **D4** — test suite 13/13 green, 0 failures ## How to verify (exact commands) ```bash cd # D4 — run all tests python -m unittest -q # D1+D2 — manual check for 3.5*(1-2) python -c "from calc.lexer import tokenize; print([(t.kind,t.value) for t in tokenize('3.5*(1-2)')])" # D3 — must raise LexError python -c "from calc.lexer import tokenize; tokenize('1 @ 2')" ``` ## Expected results ``` # python -m unittest -q Ran 13 tests in 0.000s OK # 3.5*(1-2) [('NUMBER', 3.5), ('STAR', '*'), ('LPAREN', '('), ('NUMBER', 1), ('MINUS', '-'), ('NUMBER', 2), ('RPAREN', ')'), ('EOF', None)] # 1 @ 2 — exits non-zero with: calc.lexer.LexError: unexpected character '@' at position 2 ``` ## Files - `calc/__init__.py` — package marker - `calc/lexer.py` — `Token`, `LexError`, `tokenize()` - `calc/test_lexer.py` — 13 unittest cases covering D1–D3 ## Commit SHA `80d7ee3` — feat: add calc lexer with Token, LexError, tokenize() — phase lex D1-D4