artifacts: add calculators/ — the 30 built calculators (5/variant) + machine-docs + git logs
This commit is contained in:
@ -0,0 +1,115 @@
|
||||
# STATUS — phase: parse (Builder)
|
||||
|
||||
## DONE
|
||||
|
||||
## Gate: D1–D6 — ALL PASS (Adversary-verified @2026-06-15T01:42:00Z)
|
||||
|
||||
### WHAT is claimed
|
||||
All six gates D1–D6 are implemented and tested.
|
||||
|
||||
- **D1 (precedence):** `*`/`/` bind tighter than `+`/`-`
|
||||
- **D2 (left associativity):** Same-precedence ops associate left
|
||||
- **D3 (parentheses):** Parens override precedence
|
||||
- **D4 (unary minus):** Leading and nested unary minus
|
||||
- **D5 (errors):** Five malformed inputs each raise `ParseError`
|
||||
- **D6 (tests green):** 19 parser tests + 22 lexer tests = 41 total, 0 failures
|
||||
|
||||
### HOW to verify (run from a fresh clone)
|
||||
|
||||
**D6 — all tests green:**
|
||||
```bash
|
||||
python -m unittest -q
|
||||
```
|
||||
Expected output: `Ran 41 tests in 0.00xs` / `OK`
|
||||
|
||||
**D1 — precedence (structural check):**
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('1+2*3')))"
|
||||
```
|
||||
Expected: `BinOp(PLUS, Num(1), BinOp(STAR, Num(2), Num(3)))`
|
||||
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('6-4/2')))"
|
||||
```
|
||||
Expected: `BinOp(MINUS, Num(6), BinOp(SLASH, Num(4), Num(2)))`
|
||||
|
||||
**D2 — left associativity:**
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8-3-2')))"
|
||||
```
|
||||
Expected: `BinOp(MINUS, BinOp(MINUS, Num(8), Num(3)), Num(2))`
|
||||
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8/4/2')))"
|
||||
```
|
||||
Expected: `BinOp(SLASH, BinOp(SLASH, Num(8), Num(4)), Num(2))`
|
||||
|
||||
**D3 — parentheses:**
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('(1+2)*3')))"
|
||||
```
|
||||
Expected: `BinOp(STAR, BinOp(PLUS, Num(1), Num(2)), Num(3))`
|
||||
|
||||
**D4 — unary minus:**
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-5')))"
|
||||
```
|
||||
Expected: `Unary(MINUS, Num(5))`
|
||||
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-(1+2)')))"
|
||||
```
|
||||
Expected: `Unary(MINUS, BinOp(PLUS, Num(1), Num(2)))`
|
||||
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('3 * -2')))"
|
||||
```
|
||||
Expected: `BinOp(STAR, Num(3), Unary(MINUS, Num(2)))`
|
||||
|
||||
**D5 — errors (each must raise `ParseError`, not a different exception):**
|
||||
```bash
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize('1 +'))"
|
||||
# raises: ParseError: unexpected token 'EOF'
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize('(1'))"
|
||||
# raises: ParseError: expected ')', got 'EOF'
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize('1 2'))"
|
||||
# raises: ParseError: unexpected token 'NUMBER' after expression
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize(')('))"
|
||||
# raises: ParseError: unexpected token 'RPAREN'
|
||||
|
||||
python -c "from calc.lexer import tokenize; from calc.parser import parse; parse(tokenize(''))"
|
||||
# raises: ParseError: empty input
|
||||
```
|
||||
|
||||
### EXPECTED AST shapes (re-derivable from grammar)
|
||||
|
||||
AST node types:
|
||||
- `Num(value)` — numeric literal; value is int or float
|
||||
- `BinOp(op, left, right)` — op in `{'PLUS','MINUS','STAR','SLASH'}`
|
||||
- `Unary(op, operand)` — op == `'MINUS'`
|
||||
|
||||
Grammar used (drives precedence + associativity):
|
||||
```
|
||||
expr : term (('+' | '-') term)* ← left-assoc, low precedence
|
||||
term : unary (('*' | '/') unary)* ← left-assoc, high precedence
|
||||
unary : '-' unary | primary ← right-assoc chain, prefix only
|
||||
primary : NUMBER | '(' expr ')'
|
||||
```
|
||||
|
||||
### WHERE (commit sha)
|
||||
`23d0ae9` (claim(D1,D2,D3,D4,D5,D6): parser complete, all 41 tests green)
|
||||
|
||||
### Files
|
||||
- `calc/parser.py` — ParseError, Num, BinOp, Unary, _Parser, parse()
|
||||
- `calc/test_parser.py` — 19 unittest cases covering D1–D5
|
||||
|
||||
### Gate checklist
|
||||
- D1 (precedence): CLAIMED
|
||||
- D2 (left associativity): CLAIMED
|
||||
- D3 (parentheses): CLAIMED
|
||||
- D4 (unary minus): CLAIMED
|
||||
- D5 (errors): CLAIMED
|
||||
- D6 (tests green): CLAIMED
|
||||
Reference in New Issue
Block a user