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

4.5 KiB
Raw Blame History

STATUS — Phase parse (Builder)

DONE

All gates D1D6 Adversary-verified PASS @2026-06-15T06:32:30Z. Phase parse complete.

Current State

Gates D1 through D6 implemented, claimed, and Adversary-verified. Phase complete.


Gate D1 — precedence — CLAIMED, awaiting Adversary

WHAT: * and / bind tighter than + and -. 1+2*3 parses as BinOp('+', Num(1), BinOp('*', Num(2), Num(3))), not BinOp('+', BinOp('+',…)).

HOW:

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

EXPECTED:

BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))
BinOp('+', BinOp('*', Num(2), Num(3)), Num(4))

WHERE: calc/parser.py — commit 64d0252


Gate D2 — left associativity — CLAIMED, awaiting Adversary

WHAT: Same-precedence operators associate left. 8-3-2(8-3)-2; 8/4/2(8/4)/2.

HOW:

python -c "from calc.lexer import tokenize; from calc.parser import parse; print(parse(tokenize('8-3-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(3)), Num(2))
BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))

WHERE: calc/parser.py — commit 64d0252


Gate D3 — parentheses — CLAIMED, awaiting Adversary

WHAT: Parens override precedence. (1+2)*3 parses with + under *.

HOW:

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

EXPECTED:

BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))
BinOp('+', Num(2), Num(3))

WHERE: calc/parser.py _primary() method — commit 64d0252


Gate D4 — unary minus — CLAIMED, awaiting Adversary

WHAT: Leading and nested unary minus parses correctly: -5, -(1+2), 3 * -2.

HOW:

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

EXPECTED:

Unary('-', Num(5))
Unary('-', BinOp('+', Num(1), Num(2)))
BinOp('*', Num(3), Unary('-', Num(2)))
Unary('-', Unary('-', Num(5)))

WHERE: calc/parser.py _unary() method — commit 64d0252


Gate D5 — errors — CLAIMED, awaiting Adversary

WHAT: Malformed input raises ParseError (not any other exception) for all five plan cases.

HOW:

python -c "
from calc.lexer import tokenize
from calc.parser import parse, ParseError

cases = ['1 +', '(1', '1 2', ')(' , '']
for src in cases:
    try:
        parse(tokenize(src))
        print(f'FAIL: {src!r} did not raise')
    except ParseError as e:
        print(f'OK ParseError: {src!r} -> {e}')
    except Exception as e:
        print(f'FAIL wrong exc: {src!r} -> {type(e).__name__}: {e}')
"

EXPECTED:

OK ParseError: '1 +' -> unexpected end of expression
OK ParseError: '(1' -> expected ')' but got 'EOF' ('')
OK ParseError: '1 2' -> unexpected token 'NUMBER' (2)
OK ParseError: ')(' -> unexpected token 'RPAREN' (')')
OK ParseError: '' -> empty expression

WHERE: calc/parser.py parse(), _primary(), _expr() — commit 64d0252


Gate D6 — tests green — CLAIMED, awaiting Adversary

WHAT: calc/test_parser.py (unittest) passes with 0 failures, covering D1D5. Total 35 tests pass (15 lexer + 20 parser).

HOW:

python -m unittest -q

EXPECTED:

Ran 35 tests in 0.00Xs

OK

Test coverage in calc/test_parser.py:

  • TestPrecedence (4 tests): D1 — 1+2*3, 2*3+4, 6-2*3, 1+6/2
  • TestAssociativity (4 tests): D2 — 8-3-2, 8/4/2, 1+2+3, 2*3*4
  • TestParentheses (3 tests): D3 — (1+2)*3, ((2+3)), 3*(2+1)
  • TestUnaryMinus (4 tests): D4 — -5, -(1+2), 3 * -2, --5
  • TestErrors (5 tests): D5 — 1 +, (1, 1 2, )(, ""

All tests assert on tree structure via assertEqual on dataclass instances (not on evaluation).

WHERE: calc/test_parser.py, calc/parser.py — commit 64d0252