artifacts: add calculators/ — the 30 built calculators (5/variant) + machine-docs + git logs

This commit is contained in:
2026-06-16 15:39:42 +00:00
parent 64bc360fc0
commit bb85aa9f11
728 changed files with 34148 additions and 0 deletions

View File

@ -0,0 +1,44 @@
# JOURNAL-parse.md
## 2026-06-15T01:21Z — Parser implementation
### Approach
Implemented a classic recursive-descent parser with three precedence levels:
- `_expr()`: handles `+` / `-` (lowest precedence, left-associative)
- `_term()`: handles `*` / `/` (middle precedence, left-associative)
- `_unary()`: handles unary `-` (right-associative by recursion)
- `_primary()`: handles NUMBER literals and `(` expr `)`
Left-associativity falls out naturally from the while-loop accumulation pattern in `_expr()` and `_term()`: each iteration wraps the running `node` as the left child of a new `BinOp`.
Unary minus recurses into itself (`_unary()` calls `_unary()`) which gives right-associativity for `--5``Unary('-', Unary('-', Num(5)))`.
### Verification run
```
$ python -m unittest -q
Ran 43 tests in 0.001s
OK
```
Manual shape checks:
```
D1 1+2*3: BinOp('+', Num(1), BinOp('*', Num(2), Num(3))) ✓
D2 8-3-2: BinOp('-', BinOp('-', Num(8), Num(3)), Num(2)) ✓
D2 8/4/2: BinOp('/', BinOp('/', Num(8), Num(4)), Num(2)) ✓
D3 (1+2)*3: BinOp('*', BinOp('+', Num(1), Num(2)), Num(3)) ✓
D4 -5: Unary('-', Num(5)) ✓
D4 -(1+2): Unary('-', BinOp('+', Num(1), Num(2))) ✓
D4 3*-2: BinOp('*', Num(3), Unary('-', Num(2))) ✓
D5 '1 +': ParseError: unexpected end of input ✓
D5 '(1': ParseError: expected 'RPAREN' but got 'EOF' ✓
D5 '1 2': ParseError: unexpected token after expression ✓
D5 ')(': ParseError: unexpected token 'RPAREN' ✓
D5 '': ParseError: empty expression ✓
```
### Error handling design
- Empty token list (just EOF): caught in `parse()` before entering `_expr()`
- Trailing operator (`1 +`): `_primary()` sees EOF, raises ParseError
- Unclosed paren (`(1`): `_consume('RPAREN')` fails with ParseError
- Extra number (`1 2`): `parse()` checks `peek() != EOF` after `_expr()` returns
- `)` before `(`: `_primary()` sees RPAREN, not a valid primary, raises ParseError