§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 bydispatch_declaration()preprocessing perparse.md §DD-1Stage 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
CapsetDeclAST node tocompiler_repo/compiler/ori_ir/src/ast/capset.rs(new file). Fields: name, members, span, visibility, attributes. Derives matchTraitDef/ExternBlock. - Add
Decl::CapsetDecl(CapsetDecl)variant to the module-level declaration enum (compiler_repo/compiler/ori_ir/src/ast/decl.rsor whereverFunction,TypeDecl,TraitDef,ExternBlocklive). - Update exhaustive matches on the declaration enum. Compiler enumerates missing arms.
- Create
compiler_repo/compiler/ori_parse/src/grammar/item/capset.rswithparse_capset_decl(p, visibility, attrs) -> ParseOutcome<CapsetDecl>. - Use
seriescombinator (compiler_repo/compiler/ori_parse/src/series/mod.rs) for the comma-separated member list — no hand-rolled loop. - Wire
dispatch_declaration()incompiler_repo/compiler/ori_parse/src/dispatch.rsto dispatch onTokenKind::Capsetto the new handler. - Trailing semicolon: per
parse.md §DD-2useeat_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
ParseErrorwithE12xxcodes perparse.md §DI-1/§DI-2. Allocate codes (likelyE1280+) from theE1xxxparser range. - Rust Tests:
compiler_repo/compiler/ori_parse/src/grammar/item/capset/tests.rs(sibling) — happy path,pubvariant, single-member, trailing-comma, missing-semicolon, missing-=, missing-name. Use the same harness pattern ascompiler_repo/compiler/ori_parse/src/grammar/item/extern_def/tests.rs. - Phase audit: update
compiler_repo/.claude/rules/parse.md §DD-1to remove the “(Target-only / spec-side only)” note forcapset_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.