Files
agent-orchestrator-benchmark/calculators/builder-adversary-stateless/run-01/machine-docs/STATUS-parse.md

3.3 KiB
Raw Blame History

STATUS — phase parse

DONE

Gates

  • D1 (precedence): PASS @2026-06-15T03:40Z
  • D2 (left assoc): PASS @2026-06-15T03:40Z
  • D3 (parentheses): PASS @2026-06-15T03:40Z
  • D4 (unary minus): PASS @2026-06-15T03:40Z
  • D5 (errors): PASS @2026-06-15T03:40Z
  • D6 (tests green): PASS @2026-06-15T03:40Z

Source files

  • calc/parser.py — AST node definitions + recursive-descent parser
  • calc/test_parser.py — 20 unittest cases covering D1D5

AST shape

Nodes are dataclasses defined in calc/parser.py:

@dataclass
class Num:
    value: Union[int, float]

@dataclass
class BinOp:
    op: str          # '+', '-', '*', '/'
    left: Node
    right: Node

@dataclass
class Unary:
    op: str          # '-'
    operand: Node

Verify commands (cold)

python -m unittest -q

Expected: Ran 36 tests in Xs / OK (0 failures)

python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('1+2*3')))"

Expected: BinOp(op='+', left=Num(value=1), right=BinOp(op='*', left=Num(value=2), right=Num(value=3)))

python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8-3-2')))"

Expected: BinOp(op='-', left=BinOp(op='-', left=Num(value=8), right=Num(value=3)), right=Num(value=2))

python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8/4/2')))"

Expected: BinOp(op='/', left=BinOp(op='/', left=Num(value=8), right=Num(value=4)), right=Num(value=2))

python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('(1+2)*3')))"

Expected: BinOp(op='*', left=BinOp(op='+', left=Num(value=1), right=Num(value=2)), right=Num(value=3))

python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-5')))"

Expected: Unary(op='-', operand=Num(value=5))

python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('-(1+2)')))"

Expected: Unary(op='-', operand=BinOp(op='+', left=Num(value=1), right=Num(value=2)))

python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('3 * -2')))"

Expected: BinOp(op='*', left=Num(value=3), right=Unary(op='-', operand=Num(value=2)))

python -c "
from calc.lexer import tokenize; from calc.parser import parse, ParseError
for expr in ['1 +', '(1', '1 2', ')(', '']:
    try:
        parse(tokenize(expr))
        print(f'{expr!r}: NO ERROR (FAIL)')
    except ParseError as e:
        print(f'{expr!r}: ParseError OK')
"

Expected: all 5 lines print ParseError OK

Gate-specific DoD mapping

D1 — precedence: 1+2*3 parses as 1+(2*3)* is under the right child of +, not the other way.

D2 — left assoc: 8-3-2 → left-leaning tree; 8/4/2 → left-leaning tree. The while-loop in _expr/_term naturally accumulates left.

D3 — parens: (1+2)*3BinOp('*', BinOp('+', ...), Num(3))+ is under *'s left child.

D4 — unary: -5Unary, -(1+2)Unary(BinOp(...)), 3*-2BinOp('*', Num(3), Unary(...)).

D5 — errors: "1 +", "(1", "1 2", ")(", "" all raise ParseError (not Python built-ins).

D6 — tests: python -m unittest -q → 36 tests, 0 failures.