2.9 KiB
2.9 KiB
STATUS — phase parse
DONE
Claimed gates: D1, D2, D3, D4, D5, D6
Commit: fa50146a5acbc9e7cf65a1e60e0b0fba2d8bd2ea (main)
Files: calc/parser.py, calc/test_parser.py
What is claimed
- D1 — precedence:
*//bind tighter than+/- - D2 — left associativity: same-precedence ops are left-associative
- D3 — parentheses: parens override default precedence
- D4 — unary minus: leading and nested unary minus handled
- D5 — errors: malformed inputs raise
ParseError(not any other exception) - D6 — tests green:
python -m unittest -q→ 36 tests, 0 failures
How to verify (exact commands)
# D6 — all tests green
python -m unittest -q
# D1 — mul binds tighter than add
python -c "from calc.lexer import tokenize; from calc.parser import parse; t=parse(tokenize('1+2*3')); print(t); assert str(t)==\"BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))\""
# D2 — left associativity subtraction
python -c "from calc.lexer import tokenize; from calc.parser import parse; t=parse(tokenize('8-3-2')); print(t); assert str(t)==\"BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))\""
# D2 — left associativity division
python -c "from calc.lexer import tokenize; from calc.parser import parse; t=parse(tokenize('8/4/2')); print(t); assert str(t)==\"BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))\""
# D3 — parens override precedence
python -c "from calc.lexer import tokenize; from calc.parser import parse; t=parse(tokenize('(1+2)*3')); print(t); assert str(t)==\"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'))); print(parse(tokenize('-(1+2)'))); print(parse(tokenize('3 * -2')))"
# D5 — all five error inputs raise ParseError
python -c "
from calc.lexer import tokenize
from calc.parser import parse, ParseError
for src in ['1 +', '(1', '1 2', ')(', '']:
try:
parse(tokenize(src))
print('FAIL — no error for', repr(src))
except ParseError:
print('OK', repr(src))
"
Expected output
D6: Ran 36 tests ... OK
D1: BinOp('+', Num(1), BinOp('*', Num(2), Num(3))) (no assertion error)
D2-sub: BinOp('-', BinOp('-', Num(8), Num(3)), Num(2)) (no assertion error)
D2-div: BinOp('/', BinOp('/', Num(8), Num(4)), Num(2)) (no assertion error)
D3: BinOp('*', BinOp('+', Num(1), Num(2)), Num(3)) (no assertion error)
D4:
Unary('-', Num(5))
Unary('-', BinOp('+', Num(1), Num(2)))
BinOp('*', Num(3), Unary('-', Num(2)))
D5: Five lines all starting with OK
AST shape reference
Num(value) # numeric literal; value: int | float
BinOp(op, left, right) # binary op; op in {'+', '-', '*', '/'}
Unary(op, operand) # unary op; op == '-'
Precedence (high → low): unary-minus > * / > + -
Associativity: left for all binary operators