artifacts: add calculators/ — the 30 built calculators (5/variant) + machine-docs + git logs
This commit is contained in:
@ -0,0 +1,66 @@
|
||||
# JOURNAL — parse phase (Builder)
|
||||
|
||||
## 2026-06-15 — Initial implementation
|
||||
|
||||
**Design decisions:**
|
||||
|
||||
Grammar used (standard precedence climbing via two layers):
|
||||
```
|
||||
expr := term (('+' | '-') term)*
|
||||
term := factor (('*' | '/') factor)*
|
||||
factor := '-' factor | primary
|
||||
primary := NUMBER | '(' expr ')'
|
||||
```
|
||||
|
||||
Left associativity falls out of the `while` loop pattern in `_expr()` and `_term()` — each new BinOp wraps the accumulated left node.
|
||||
|
||||
Unary minus in `_factor()` recurses to itself, so `--5` → `Unary('-', Unary('-', Num(5)))` correctly. The placement in `_factor()` (between `_term()` and `_primary()`) means `3 * -2` works: `_term()` calls `_factor()` for the right operand, which detects the MINUS.
|
||||
|
||||
**Verification runs:**
|
||||
|
||||
D1:
|
||||
```
|
||||
$ python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('1+2*3')))"
|
||||
BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))
|
||||
```
|
||||
|
||||
D2:
|
||||
```
|
||||
$ python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8-3-2')))"
|
||||
BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))
|
||||
$ python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8/4/2')))"
|
||||
BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))
|
||||
```
|
||||
|
||||
D3:
|
||||
```
|
||||
$ python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('(1+2)*3')))"
|
||||
BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))
|
||||
```
|
||||
|
||||
D4:
|
||||
```
|
||||
$ python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-5')))"
|
||||
Unary('-', Num(5))
|
||||
$ python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-(1+2)')))"
|
||||
Unary('-', BinOp('+', Num(1), Num(2)))
|
||||
$ python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('3 * -2')))"
|
||||
BinOp('*', Num(3), Unary('-', Num(2)))
|
||||
```
|
||||
|
||||
D5 (all 5 required error cases + extras):
|
||||
```
|
||||
OK: '1 +' -> ParseError: unexpected token 'EOF'
|
||||
OK: '(1' -> ParseError: unclosed parenthesis, got 'EOF'
|
||||
OK: '1 2' -> ParseError: unexpected token 'NUMBER'
|
||||
OK: ')(' -> ParseError: unexpected token 'RPAREN'
|
||||
OK: '' -> ParseError: empty input
|
||||
```
|
||||
|
||||
D6:
|
||||
```
|
||||
$ python -m unittest -q
|
||||
----------------------------------------------------------------------
|
||||
Ran 48 tests in 0.002s
|
||||
OK
|
||||
```
|
||||
Reference in New Issue
Block a user