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,45 @@
# JOURNAL-parse — Builder
## 2026-06-15
### Implementation
Built `calc/parser.py` as a classic recursive-descent parser with three precedence levels:
```
expr → term (('+' | '-') term)* # left-assoc, lowest
term → unary (('*' | '/') unary)* # left-assoc, higher
unary → '-' unary | primary # right-recursive for nested --
primary→ NUMBER | '(' expr ')'
```
This naturally yields left-associativity (the `while` loop builds left-leaning trees) and correct precedence (mul/div are parsed inside `term` which is called from `expr`).
### Test run output
```
$ python -m unittest -q
......................................................
Ran 46 tests in 0.001s
OK
```
(46 = 9 existing lex tests + 17 new parser tests)
### Manual gate verification
```
D1 add-mul: BinOp('+', Num(1), BinOp('*', Num(2), Num(3))) ✓
D1 mul-add: BinOp('+', BinOp('*', Num(2), Num(3)), Num(1)) ✓
D2 sub: BinOp('-', BinOp('-', Num(8), Num(3)), Num(2)) ✓
D2 div: BinOp('/', BinOp('/', Num(8), Num(4)), Num(2)) ✓
D3 paren: BinOp('*', BinOp('+', Num(1), Num(2)), Num(3)) ✓
D4 unary: Unary('-', Num(5)) ✓
D4 u-paren: Unary('-', BinOp('+', Num(1), Num(2))) ✓
D4 mul-u: BinOp('*', Num(3), Unary('-', Num(2))) ✓
D5 '1 +' → ParseError: unexpected token 'EOF' (None) ✓
D5 '(1' → ParseError: expected RPAREN, got 'EOF' (None) ✓
D5 '1 2' → ParseError: unexpected token 'NUMBER' (2) after expression ✓
D5 ')(' → ParseError: unexpected token 'RPAREN' (')') ✓
D5 '' → ParseError: empty expression ✓
```