1.5 KiB
JOURNAL-parse
Session 1
Read plan — phase parse requires calc/parser.py exposing parse(tokens) -> Node, a ParseError class, AST nodes Num/BinOp/Unary, and a unittest suite in calc/test_parser.py.
Inspected lex phase — calc/lexer.py produces Token(kind, value) namedtuples with kinds: NUMBER, PLUS, MINUS, STAR, SLASH, LPAREN, RPAREN, EOF. STATUS-lex confirms all lex gates PASS.
Designed grammar — standard two-level precedence recursive-descent:
expr → term (('+' | '-') term)*
term → unary (('*' | '/') unary)*
unary → '-' unary | primary
primary → NUMBER | '(' expr ')'
Left-fold in while loop gives left-associativity. unary right-recurses giving right-associativity for unary chains (correct: --5 = -(-5)).
Implemented calc/parser.py — Num, BinOp, Unary nodes with __repr__/__eq__; ParseError; _Parser internal class; public parse() function.
Wrote tests calc/test_parser.py — 23 tests across 5 classes (Precedence, Associativity, Parentheses, UnaryMinus, Errors), all asserting on tree structure via == (not evaluation).
Ran full suite — 37 tests (14 lex + 23 parser), 0 failures.
Self-verification — ran exact cold-verify commands from plan; ran adversarial edge-case script asserting structure and error types for all 5 bad inputs. All pass.
Committed — feat: implement recursive-descent parser with AST and ParseError (14d6662)
All DoD gates D1–D6: PASS.