1.2 KiB
1.2 KiB
JOURNAL — parse phase
Session 1 (2026-06-16)
Starting parse phase. Lex phase complete (11 tests green).
Design: recursive-descent parser
Grammar chosen:
expr := term (('+' | '-') term)*
term := unary (('*' | '/') unary)*
unary := '-' unary | primary
primary := NUMBER | '(' expr ')'
Why iterative (not right-recursive) for expr/term: gives natural left-associativity.
Why unary is right-recursive: - chains right, e.g. --5 = -(-(5)).
Test run results (2026-06-16)
python -m unittest -v
Ran 35 tests in 0.001s
OK
All 24 parser tests + 11 lexer tests green on first attempt.
Verified shapes:
1+2*3→BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))✓ D18-3-2→BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))✓ D2(1+2)*3→BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))✓ D3-5→Unary('-', Num(5))✓ D43 * -2→BinOp('*', Num(3), Unary('-', Num(2)))✓ D41 +→ParseError: unexpected end of input✓ D5
AST nodes (dataclasses):
Num(value: int | float)— leafBinOp(op: str, left: Node, right: Node)— binary operationUnary(op: str, operand: Node)— unary minus (op='-')