Skip to content

Add tree shapes for code generation to the conformance suite - #9

Merged
vrenken merged 1 commit into
developfrom
claude/project-thread-tkcvqq
Oct 23, 2026
Merged

vrenken merged 1 commit into
developfrom
claude/project-thread-tkcvqq

Conversation

@vrenken

@vrenken vrenken commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Requested by Peter · project thread

The first of the three codegen PRs. It lays the shared foundation: the shape of each tree, meaning what can stand at each position among its children. The Rust and TypeScript code generators will type nodes and visitor parameters from it.

What's in it

  • conformance/tools/shapes.py is the reference analysis. It works on the BNF rules Lark compiles a grammar into, and follows what Lark's tree builder does with them: filtered tokens, inlined _rules and ?rules, aliases, templates, imports, maybe_placeholders placeholders, and the helper rules that *, + and ~ become.
  • generate.py adds a shapes field to every case. It fails when a tree Lark builds doesn't match the shapes, and all 1,400 trees in the suite match.
  • sources/codegen.json has new hand-written cases: the purchase order grammar, inlining, placeholders, repetitions, kept tokens, templates and multiple start rules.
  • Rust: etalii_lark::codegen::Shapes::of(&lark). TypeScript: shapesOf(lark). Both compute the shapes from their own compiled grammars, and their conformance runs compare them on all 883 cases. Both match on every case.
  • .NET: ShapeConformanceTests compares the source generator's shapes with the spec. The generator reads the grammar text, so it is coarser on 414 cases, which are listed in known-failures/dotnet-shapes.txt. The causes are unnamed anonymous terminals, templates, imports and recursive rules. A second check makes sure its shapes still fit every tree Lark builds, and they do. So the generator never mistypes a child; it only types fewer of them. The .NET generator itself is unchanged.
  • The conformance README documents the format.

Testing

  • python conformance/tools/generate.py: the existing cases are unchanged apart from the new shapes field.
  • cargo test --release, cargo clippy -D warnings, cargo fmt --check
  • npm run typecheck, npm test
  • dotnet test (net10.0): 2925 tests pass.

Generated by Claude Code

The code generators type each tree by its shape: what can stand at each
position among its children. conformance/tools/shapes.py defines the shapes
on Lark's compiled BNF rules, following what the tree builder does with
them (filtered tokens, inlined _rules and ?rules, aliases, templates,
imports, placeholders, and the helper rules of *, + and ~).

generate.py adds the shapes to every case and fails when a tree Lark builds
doesn't match them; all 1,400 trees in the suite do. New hand-written cases
in sources/codegen.json cover the purchase order grammar, inlining,
placeholders, repetitions, kept tokens and templates.

Rust (etalii_lark::codegen::Shapes) and TypeScript (shapesOf) compute the
same shapes from their own compiled grammars, and their conformance runs
compare them. The .NET source generator is compared too: it is coarser on
the cases in known-failures/dotnet-shapes.txt, and a check makes sure its
shapes still fit every tree.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHXTnmdnhE64asNUmffcLr
@vrenken vrenken self-assigned this Oct 23, 2026
@vrenken
vrenken merged commit 29b9be8 into develop Oct 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants