0%

§02 Parser — capset_decl dispatch + AST node

Goal

Wire the parser to recognize capset_decl per grammar.ebnf line 281 and construct a CapsetDecl AST node consumed downstream by name resolution.

Implementation Sketch

Per parse.md §DD-1 table, dispatch_declaration() in compiler_repo/compiler/ori_parse/src/dispatch.rs routes top-level forms by leading token. Adding Capset adds one branch. The handler parse_capset_decl() lives in a new file compiler_repo/compiler/ori_parse/src/grammar/item/capset.rs (mirroring siblings like extern_def.rs, trait_def.rs).

The AST node CapsetDecl lives in compiler_repo/compiler/ori_ir/src/ast/ (sibling files: function.rs, trait_def.rs, extern_def.rs). Fields:

  • name: Name (interned identifier — capset names are PascalCase)
  • members: Vec<Name> (interned identifiers — each is a capability or another capset name; resolution is §03’s job)
  • span: Span (full source range)
  • visibility: Visibility (Public / Private)
  • attributes: Vec<Attribute> (consumed by dispatch_declaration() preprocessing per parse.md §DD-1 Stage 2 note)

Series parsing (the comma-separated member list) reuses the series combinator with SeriesConfig { separator: Comma, terminator: Semicolon, trailing: Allowed, ... } (per parse.md §SE-1 / §SE-2) — do NOT open-code the loop (SE-3).

Implementation Items

  • Add CapsetDecl AST node to compiler_repo/compiler/ori_ir/src/ast/capset.rs (new file). Fields: name, members, span, visibility, attributes. Derives match TraitDef/ExternBlock.
  • Add Decl::CapsetDecl(CapsetDecl) variant to the module-level declaration enum (compiler_repo/compiler/ori_ir/src/ast/decl.rs or wherever Function, TypeDecl, TraitDef, ExternBlock live).
  • Update exhaustive matches on the declaration enum. Compiler enumerates missing arms.
  • Create compiler_repo/compiler/ori_parse/src/grammar/item/capset.rs with parse_capset_decl(p, visibility, attrs) -> ParseOutcome<CapsetDecl>.
  • Use series combinator (compiler_repo/compiler/ori_parse/src/series/mod.rs) for the comma-separated member list — no hand-rolled loop.
  • Wire dispatch_declaration() in compiler_repo/compiler/ori_parse/src/dispatch.rs to dispatch on TokenKind::Capset to the new handler.
  • Trailing semicolon: per parse.md §DD-2 use eat_optional_item_semicolon() (capset has no } body, so ; is required for grammar conformance — but lenient per existing parser convention).
  • Error path: malformed declarations emit structured ParseError with E12xx codes per parse.md §DI-1 / §DI-2. Allocate codes (likely E1280+) from the E1xxx parser range.
  • Rust Tests: compiler_repo/compiler/ori_parse/src/grammar/item/capset/tests.rs (sibling) — happy path, pub variant, single-member, trailing-comma, missing-semicolon, missing-=, missing-name. Use the same harness pattern as compiler_repo/compiler/ori_parse/src/grammar/item/extern_def/tests.rs.
  • Phase audit: update compiler_repo/.claude/rules/parse.md §DD-1 to remove the “(Target-only / spec-side only)” note for capset_decl — it ships in this section.

Spec References

  • Proposal §Design (declaration syntax + visibility).
  • Grammar grammar.ebnf:281 (capset_decl = "capset" identifier "=" identifier { "," identifier } ";" .).
  • Spec 20-capabilities.md §20.11.
  • parse.md §DD-1 (top-level dispatch table) + §DD-2 (semicolon rule) + §SE-3 (series combinator).

Tests

  • Rust unit tests in this section.
  • Spec tests (tests/spec/declarations/capsets.ori + tests/spec/capabilities/capset*.ori) — owned by §05; gated on §03 expansion landing first since spec tests exercise full pipeline.

Intelligence Reconnaissance

scripts/intel-query.sh file-symbols "compiler_repo/compiler/ori_parse/src/grammar/item/" --repo ori to inventory sibling parsers before writing capset.rs. scripts/intel-query.sh callers parse_extern_block --repo ori to find the dispatch site convention.