Context
In procedural macro development, we often encounter situations where "a position can be one of multiple types". For example, a macro argument can be either a string literal or an identifier; or like syn::Item, it can be either fn or struct.
Currently, vacro's define! and capture! can only describe linear sequences. To support this polymorphism, we need to introduce Enum Parsing, allowing users to define a set of possible matching branches. vacro will automatically generate try/fork logic and encapsulate the result in a generated Enum.
Target
- Branching Syntax: Introduce new DSL syntax to describe branch selection.
- Auto Enum Generation: Automatically generate the corresponding Rust
enum definition.
- Backtracking Logic: Generate backtracking parsing code based on
input.fork(), trying branches sequentially.
Architecture Design
1. Syntax Design
It is recommended to use syntax similar to struct initialization:
// Syntax: #( <CaptureName> : <EnumName> { <Type1>, <Type2> } )
define!(MyMacro:
kw::input
#(content: MyContent {
syn::ItemFn,
ItemStruct
})
);
2. AST Changes (src/ast/capture.rs)
Add an Enum variant to the new Matcher enum:
pub enum Matcher {
SynType(Type),
Nested(Vec<Pattern>),
// New Variant
Enum {
enum_name: Ident,
variants: Vec<Matcher>, // Matcher (SynType)
},
}
3. Codegen Strategy (src/codegen/)
For Matcher::Enum, the generated parsing code should follow this logic:
// Pseudo-code logic
let _fork = input.fork();
if let Ok(v) = _fork.parse::<syn::ItemFn>() {
input.advance_to(&_fork); // Confirm consumption
return MyContent::Func(v);
}
let _fork = input.fork();
if let Ok(v) = _fork.parse::<syn::ItemStruct>() {
input.advance_to(&_fork);
return MyContent::Struct(v);
}
return Err(Error::new(span, "Expected Func or Struct"));
Task List
Phase 1: AST & Parser Support
Phase 2: Code Generation (Definition)
Phase 3: Code Generation (Logic)
Phase 4: Testing
Context
In procedural macro development, we often encounter situations where "a position can be one of multiple types". For example, a macro argument can be either a string literal or an identifier; or like
syn::Item, it can be eitherfnorstruct.Currently,
vacro'sdefine!andcapture!can only describe linear sequences. To support this polymorphism, we need to introduce Enum Parsing, allowing users to define a set of possible matching branches.vacrowill automatically generate try/fork logic and encapsulate the result in a generated Enum.Target
enumdefinition.input.fork(), trying branches sequentially.Architecture Design
1. Syntax Design
It is recommended to use syntax similar to struct initialization:
2. AST Changes (
src/ast/capture.rs)Add an
Enumvariant to the newMatcherenum:3. Codegen Strategy (
src/codegen/)For
Matcher::Enum, the generated parsing code should follow this logic:Task List
Phase 1: AST & Parser Support
Enumvariant to theMatcherenum insrc/ast/capture.rs.src/syntax/capture.rsparser:Enum { variant, ... }syntax structure.Phase 2: Code Generation (Definition)
src/codegen/output.rs(generate_output):Matcher::Enumis detected, generate apub enum EnumName { ... }definition instead of astructfield.Phase 3: Code Generation (Logic)
src/codegen/logic/capture.rs(Compiler):compile_enum_matcherfunction.fork->parse->advanceattempt chain.Erroraggregation ("Expected one of: ...").Phase 4: Testing
A | Btype selection.