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,159 @@
# STATUS — parse phase (Builder)
## DONE
All DoD gates (D1D6) verified PASS by Adversary @2026-06-15T06:13:00Z. No veto. Phase complete.
## Current state
Implementation complete. `calc/parser.py` and `calc/test_parser.py` created. 48 tests pass (24 lex + 24 parser). All gates claimed and Adversary-verified.
## AST Shape Reference
```
Num(value) — value is int or float
BinOp(op, left, right) — op in ('+', '-', '*', '/')
Unary(op, operand) — op is '-'
```
`repr()` of each node class is canonical (used in test assertions and verification commands).
---
## Gates
### D1 — precedence: **CLAIMED**, awaiting Adversary
**WHAT:** `*` and `/` bind tighter than `+` and `-`. `1+2*3``BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))` (not `BinOp('*', BinOp('+', ...), ...)`).
**HOW to verify:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('1+2*3')))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('2*3+1')))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('5-2*3')))"
```
**EXPECTED:**
```
BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))
BinOp('+', BinOp('*', Num(2), Num(3)), Num(1))
BinOp('-', Num(5), BinOp('*', Num(2), Num(3)))
```
**WHERE:** `calc/parser.py``_expr()` calls `_term()` which handles `*`/`/`; `_expr()` handles `+`/`-` at lower priority.
---
### D2 — left associativity: **CLAIMED**, awaiting Adversary
**WHAT:** Same-precedence operators associate left. `8-3-2``BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))`. `8/4/2``BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))`.
**HOW to verify:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8-3-2')))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8/4/2')))"
```
**EXPECTED:**
```
BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))
BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))
```
**WHERE:** `calc/parser.py``_expr()` and `_term()` use `while` loops, wrapping the accumulating left side.
---
### D3 — parentheses: **CLAIMED**, awaiting Adversary
**WHAT:** Parens override precedence. `(1+2)*3``BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))`.
**HOW to verify:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('(1+2)*3')))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('1*(2+3)')))"
```
**EXPECTED:**
```
BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))
BinOp('*', Num(1), BinOp('+', Num(2), Num(3)))
```
**WHERE:** `calc/parser.py``_primary()` handles `LPAREN … RPAREN` by calling `_expr()` recursively.
---
### D4 — unary minus: **CLAIMED**, awaiting Adversary
**WHAT:** Leading and nested unary minus parses correctly. `-5``Unary('-', Num(5))`. `-(1+2)``Unary('-', BinOp('+', Num(1), Num(2)))`. `3 * -2``BinOp('*', Num(3), Unary('-', Num(2)))`.
**HOW to verify:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-5')))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-(1+2)')))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('3 * -2')))"
```
**EXPECTED:**
```
Unary('-', Num(5))
Unary('-', BinOp('+', Num(1), Num(2)))
BinOp('*', Num(3), Unary('-', Num(2)))
```
**WHERE:** `calc/parser.py``_factor()` detects `MINUS` and recurses, returning `Unary('-', operand)`.
---
### D5 — errors: **CLAIMED**, awaiting Adversary
**WHAT:** Malformed input raises `ParseError` (not `LexError`, `IndexError`, etc.). Five required cases: `"1 +"`, `"(1"`, `"1 2"`, `")("`, `""`.
**HOW to verify:**
```bash
python -c "
from calc.lexer import tokenize
from calc.parser import parse, ParseError
errors = ['1 +', '(1', '1 2', ')(', '']
for src in errors:
try:
parse(tokenize(src))
print(f'FAIL: {src!r} did not raise')
except ParseError as e:
print(f'OK: {src!r} -> ParseError: {e}')
except Exception as e:
print(f'FAIL: {src!r} raised wrong exception: {type(e).__name__}: {e}')
"
```
**EXPECTED:**
```
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
```
**WHERE:** `calc/parser.py``parse()`, `_primary()`, `_primary()` RPAREN check.
---
### D6 — tests green: **CLAIMED**, awaiting Adversary
**WHAT:** `calc/test_parser.py` + `calc/test_lexer.py` combined: 48 tests, 0 failures under `python -m unittest`.
**HOW to verify:**
```bash
python -m unittest -q
```
**EXPECTED:**
```
----------------------------------------------------------------------
Ran 48 tests in 0.002s
OK
```
**WHERE:** `calc/test_parser.py` (24 tests covering D1D5), `calc/test_lexer.py` (24 tests from lex phase).