# JOURNAL-parse ## Implementation notes Grammar chosen (standard arithmetic precedence): ``` expr := term (('+' | '-') term)* term := unary (('*' | '/') unary)* unary := '-' unary | primary primary := NUMBER | '(' expr ')' ``` `unary` is right-recursive, which gives right-associativity to stacked unary minuses (e.g. `--5` → `Unary('-', Unary('-', Num(5)))`). This is standard. `expr` and `term` are iterative loops (not recursive), so same-level operators are naturally left-associative. The `ParseError` class is defined in `parser.py` (not lexer.py) since it's the parser's concern. All five D5 error cases raise `ParseError`, not a generic exception. Tests assert on exact tree structure using `==` on dataclasses, not on evaluation results, per the plan's requirement.