← All craftbooks

Parser / DSL for a Small Grammar

Build: software and codeevalv1.0.0released 2026-06-05workflow: build-loop

Build a parser for a small domain-specific language or data format — tokenize, parse to an AST, and report clear errors on malformed input. Designs the grammar FIRST — the token set, the grammar rules (BNF-style), operator precedence, the AST node shapes, and the error strategy — then implements lexer + parser producing the AST, then tests valid inputs parse to the right AST and invalid inputs fail with useful errors. Covers tokenization/lexing, recursive-descent parsing, grammar rules, operator precedence, AST construction, and helpful parse-error messages.

Steps

Entry step: grammar-design. Each step names the specialist role it wants; the full working prompt is expandable.

  1. Grammar designplannerentry

    lock tokens, grammar rules, precedence, AST shapes

    Show working prompt
    Design the grammar before writing the parser. Step 1: Define the TOKEN set (literals, identifiers, operators, keywords, punctuation, whitespace handling). Step 2: Write the grammar rules in a BNF-style notation, and for any expressions, define OPERATOR PRECEDENCE and associativity explicitly. Step 3: Define the AST node shapes the parser will produce for each rule. Step 4: Decide the error strategy: what counts as a syntax error and what a good error message looks like (position + expected). Step 5: Write a numbered acceptance-criteria checklist of 5-9 items with concrete example inputs (e.g. '`1 + 2 * 3` parses with `*` bound tighter than `+`', 'a valid program produces the documented AST', 'unbalanced parens produce a clear error with a position', 'an unexpected token is reported, not swallowed'). `write_task_note` the grammar + AST shapes + examples + checklist and write the same to the produces path.
  2. Build the parserdeveloper

    implement lexer + parser → AST

    Show working prompt
    Implement the parser to the grammar. Step 1: Write the LEXER that turns source text into a token stream per the token set, tracking positions for error messages. Step 2: Write the PARSER (recursive descent is fine) that consumes tokens and builds the AST per the grammar rules, respecting the defined operator precedence and associativity. Step 3: On malformed input, raise a clear syntax error with the position and what was expected — never silently produce a wrong AST or swallow extra tokens. Step 4: Ensure a fully-consumed valid input yields exactly the documented AST shape. Write the parser to the produces path. On a loop-back, fix only the named gaps. `write_task_note` the file path and which criteria now pass.
  3. Test the parserdeveloper

    test valid ASTs and useful error reporting

    Show working prompt
    Write tests from the grammar's example inputs. Step 1: For each valid example, assert the parser produces the EXACT expected AST shape. Step 2: Add precedence tests (e.g. `1 + 2 * 3`) asserting the tree groups operators correctly. Step 3: For malformed inputs (unexpected token, unbalanced delimiters, trailing garbage), assert the parser raises a syntax error that includes a position/expectation — not a generic crash or a silently-wrong AST. Step 4: Assert valid input is fully consumed. `write_task_note` the test file path and pass/fail count.
  4. Evaluatereviewer

    Grade the deliverable against every acceptance criterion. All pass → finish; any fail → loop back and fix the gap.

    Show working prompt
    Run the tests and parse sample inputs. For EACH acceptance criterion: confirm valid inputs produce the documented AST, confirm operator precedence/associativity is correct, confirm malformed inputs raise clear positioned errors (not crashes or wrong ASTs), and confirm valid input is fully consumed. Write PASS/FAIL per criterion.
    
    Then route — this is the whole point of the loop:
    
    - **Every criterion PASSES →** call `advance_task_step({ ref, stepId: "evaluate", next: "finish" })`.
    - **Any criterion FAILS →** write the specific gaps to notes, then call `advance_task_step({ ref, stepId: "evaluate", next: "build" })` to loop back. The builder fixes exactly those gaps.
    
    Never route to `finish` while any criterion is unmet. The build phase's completion gate already blocked a grossly-incomplete deliverable; your job is the judgment an automated check cannot make (does it actually work, read well, look right). After ~3 unproductive loops, stop and report DONE_WITH_CONCERNS so the user can step in.
  5. Finishdeveloper

    All acceptance criteria met. Stamp a short summary and report DONE.

    Show working prompt
    Every acceptance criterion passed. Write a one-paragraph DONE summary to task notes via `write_task_note`: what was built, the deliverable path(s), and a one-line confirmation that each criterion is met. Then report DONE.

Triggers

Phrases that suggest this craftbook to a crew.

Source

View this craftbook on GitHub · MIT license