artifacts: add calculators/ — the 30 built calculators (5/variant) + machine-docs + git logs
This commit is contained in:
@ -0,0 +1,78 @@
|
||||
## DONE
|
||||
|
||||
Phase: parse — recursive-descent parser
|
||||
All DoD items self-certified (BUILD phase — deferred Adversary review).
|
||||
|
||||
---
|
||||
|
||||
### AST node shapes
|
||||
|
||||
```
|
||||
Num(value) — numeric literal; value is int or float
|
||||
BinOp(op, left, right) — binary op; op in {'+', '-', '*', '/'}
|
||||
Unary(op, operand) — unary minus; op is '-'
|
||||
```
|
||||
|
||||
Defined in `calc/parser.py`. `ParseError` is also defined there.
|
||||
|
||||
---
|
||||
|
||||
### D1 — precedence
|
||||
|
||||
WHAT: `*` and `/` bind tighter than `+` and `-`.
|
||||
HOW: `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)))`
|
||||
WHERE: calc/parser.py `_expr` / `_term` levels
|
||||
|
||||
---
|
||||
|
||||
### D2 — left associativity
|
||||
|
||||
WHAT: Same-precedence operators associate left.
|
||||
HOW:
|
||||
```
|
||||
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))
|
||||
```
|
||||
WHERE: `_expr` / `_term` each use a while-loop (iterative, left-accumulating)
|
||||
|
||||
---
|
||||
|
||||
### D3 — parentheses
|
||||
|
||||
WHAT: Parens override precedence.
|
||||
HOW:
|
||||
```
|
||||
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))
|
||||
```
|
||||
WHERE: `_primary` handles LPAREN → `_expr` → RPAREN
|
||||
|
||||
---
|
||||
|
||||
### D4 — unary minus
|
||||
|
||||
WHAT: Leading and nested unary minus parses correctly.
|
||||
HOW:
|
||||
```
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-5')))"
|
||||
# EXPECTED: Unary('-', Num(5))
|
||||
```
|
||||
WHERE: `_unary` level in parser
|
||||
|
||||
---
|
||||
|
||||
### D5 — errors
|
||||
|
||||
WHAT: Malformed input raises `ParseError` (not any other exception).
|
||||
HOW: `parse(tokenize('1 +'))` raises `calc.parser.ParseError`
|
||||
WHERE: `_Parser.parse`, `_Parser._primary`, `_Parser._expect`
|
||||
|
||||
---
|
||||
|
||||
### D6 — tests green
|
||||
|
||||
WHAT: 34 tests total (14 lex + 20 parser), 0 failures.
|
||||
HOW: `python -m unittest -q`
|
||||
EXPECTED: `Ran 34 tests in 0.001s\nOK`
|
||||
WHERE: calc/test_parser.py (20 new tests)
|
||||
Reference in New Issue
Block a user