Refs: 002/Req-2, 002/Req-3, 002/Req-4
Part of epic #56, phase 1 (0.5.0). Gated by spike 006 (#57) — approach (sliced grammar vs recursive descent) comes from its verdict. Spec: 002-parser Reqs 2-4 flip planned→active.
Scope
SELECT-core slice (~40 productions):
SELECT [DISTINCT] result-columns FROM table [WHERE expr] [ORDER BY terms] [LIMIT n [OFFSET m]]
- Result columns:
*, expr, expr AS alias
- Expression grammar: literals, column refs (bare +
table.col), unary/binary ops with SQLite precedence, IS [NOT] NULL, [NOT] BETWEEN, [NOT] IN (value-list), [NOT] LIKE [ESCAPE], CASE, CAST, function calls, parens, parameters
- AST: typed nodes, spans everywhere, grouping preserved (002/Req-3)
- Three-way outcome (from spike 006): accept / reject-unsupported ("JOIN not yet supported", pointing at the token) / reject-invalid (syntax error with location) — 002/Req-4 diagnostics
- Roundtrip: parse → print → parse gives identical AST
Oracle parity
Accept/reject parity on the #2 corpus slice: everything sqlite3 accepts in-subset we accept; everything it rejects we reject (unsupported-but-valid is our third state, verified against oracle accepting it).
Acceptance criteria
🤖 Generated with Claude Code
Complexity
Size: Large. This is the real (non-spike) phase-1 parser: pomelo grammar/tokenizer for the SELECT-core slice (~40 productions), typed AST with spans, the accept/unsupported/syntax-error boundary from spike 006, roundtrip printing, oracle-parity corpus run, spec 002 Req 2-4 scenario links, and a fuzz target — substantially more surface than spike 006's throwaway crate.
Token budget: 1.2M (main-loop + any delegated agents/workflows combined).
🤖 Generated with Claude Code
Refs: 002/Req-2, 002/Req-3, 002/Req-4
Part of epic #56, phase 1 (0.5.0). Gated by spike 006 (#57) — approach (sliced grammar vs recursive descent) comes from its verdict. Spec: 002-parser Reqs 2-4 flip planned→active.
Scope
SELECT-core slice (~40 productions):
SELECT [DISTINCT] result-columns FROM table [WHERE expr] [ORDER BY terms] [LIMIT n [OFFSET m]]*, expr,expr AS aliastable.col), unary/binary ops with SQLite precedence,IS [NOT] NULL,[NOT] BETWEEN,[NOT] IN (value-list),[NOT] LIKE [ESCAPE],CASE,CAST, function calls, parens, parametersOracle parity
Accept/reject parity on the #2 corpus slice: everything sqlite3 accepts in-subset we accept; everything it rejects we reject (unsupported-but-valid is our third state, verified against oracle accepting it).
Acceptance criteria
🤖 Generated with Claude Code
Complexity
Size: Large. This is the real (non-spike) phase-1 parser: pomelo grammar/tokenizer for the SELECT-core slice (~40 productions), typed AST with spans, the accept/unsupported/syntax-error boundary from spike 006, roundtrip printing, oracle-parity corpus run, spec 002 Req 2-4 scenario links, and a fuzz target — substantially more surface than spike 006's throwaway crate.
Token budget: 1.2M (main-loop + any delegated agents/workflows combined).
🤖 Generated with Claude Code