artifacts: add calculators/ — the 30 built calculators (5/variant) + machine-docs + git logs
This commit is contained in:
@ -0,0 +1,100 @@
|
||||
# STATUS — parse phase (Builder)
|
||||
|
||||
## DONE
|
||||
|
||||
All DoD items self-certified (BUILD phase — deferred Adversary review).
|
||||
|
||||
## DoD Checklist
|
||||
|
||||
- **D1 — precedence:** PASS. `*`/`/` bind tighter than `+`/`-`. `1+2*3` → `BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))`.
|
||||
- **D2 — left associativity:** PASS. `8-3-2` → `BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))`; `8/4/2` → `BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))`.
|
||||
- **D3 — parentheses:** PASS. `(1+2)*3` → `BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))`.
|
||||
- **D4 — unary minus:** PASS. `-5` → `Unary('-', Num(5))`; `3 * -2` → `BinOp('*', Num(3), Unary('-', Num(2)))`.
|
||||
- **D5 — errors:** PASS. All five specified inputs (`"1 +"`, `"(1"`, `"1 2"`, `")("`, `""`) raise `ParseError`.
|
||||
- **D6 — tests green:** PASS. 35 tests total (11 lexer + 24 parser), 0 failures.
|
||||
|
||||
## Verification Commands (for Adversary cold-verify)
|
||||
|
||||
```bash
|
||||
# From repo root
|
||||
python -m unittest -q
|
||||
# Expected: Ran 35 tests in X.XXXs / OK (exit 0)
|
||||
|
||||
# D1 — precedence
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('1+2*3')))"
|
||||
# Expected: BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))
|
||||
|
||||
# D2 — left associativity
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8-3-2')))"
|
||||
# Expected: 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')))"
|
||||
# Expected: BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))
|
||||
|
||||
# D3 — parentheses
|
||||
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))
|
||||
|
||||
# D4 — unary minus
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-5')))"
|
||||
# Expected: Unary('-', Num(5))
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('3 * -2')))"
|
||||
# Expected: BinOp('*', Num(3), Unary('-', Num(2)))
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-(1+2)')))"
|
||||
# Expected: Unary('-', BinOp('+', Num(1), Num(2)))
|
||||
|
||||
# D5 — errors (each must raise ParseError, not crash with different exception)
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse, ParseError
|
||||
try:
|
||||
parse(tokenize('1 +'))
|
||||
print('FAIL: no error')
|
||||
except ParseError as e:
|
||||
print('OK:', e)"
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse, ParseError
|
||||
try:
|
||||
parse(tokenize('(1'))
|
||||
print('FAIL: no error')
|
||||
except ParseError as e:
|
||||
print('OK:', e)"
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse, ParseError
|
||||
try:
|
||||
parse(tokenize('1 2'))
|
||||
print('FAIL: no error')
|
||||
except ParseError as e:
|
||||
print('OK:', e)"
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse, ParseError
|
||||
try:
|
||||
parse(tokenize(')('))
|
||||
print('FAIL: no error')
|
||||
except ParseError as e:
|
||||
print('OK:', e)"
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse, ParseError
|
||||
try:
|
||||
parse(tokenize(''))
|
||||
print('FAIL: no error')
|
||||
except ParseError as e:
|
||||
print('OK:', e)"
|
||||
```
|
||||
|
||||
## AST Shape Reference
|
||||
|
||||
Nodes (all `dataclass`es in `calc/parser.py`):
|
||||
|
||||
| Class | Fields | Example |
|
||||
|-------|--------|---------|
|
||||
| `Num` | `value: int \| float` | `Num(42)`, `Num(3.5)` |
|
||||
| `BinOp` | `op: str, left: Node, right: Node` | `BinOp('+', Num(1), Num(2))` |
|
||||
| `Unary` | `op: str, operand: Node` | `Unary('-', Num(5))` |
|
||||
|
||||
`ParseError` inherits from `Exception`.
|
||||
|
||||
## Files Produced
|
||||
|
||||
- `calc/parser.py` — `ParseError`, `Num`, `BinOp`, `Unary`, `Node`, `parse()`
|
||||
- `calc/test_parser.py` — 24 unittest cases covering D1–D5
|
||||
Reference in New Issue
Block a user