bind!() { /* proc-macro */ }Expand description
即时解析宏:在现有的解析逻辑中快速消费 TokenStream
On-the-fly parsing macro: Quickly consume a TokenStream within existing parsing logic
bind! 宏模拟了一个 let 绑定语句。其中的核心部分 (<input> -> <pattern>) 会被展开为一个表达式,
其求值结果为 syn::Result<Output>。
这意味着你可以像处理普通 Result 一样处理它,例如在后面直接接 ? 操作符、.unwrap() 或者 .map(...)。
§语法
vacro::bind!(let <绑定模式> = (<输入流> -> <Vacro模式>) <后续操作>);- 绑定模式: 标准 Rust 模式,用于接收解析成功后的内容(如变量名
res或元组(a, b))。 - 输入流: 实现了
Into<TokenStream>的变量。 - Vacro模式: 描述语法的模式。
- 后续操作: 针对
Result的操作,如?;、.unwrap();等。
§捕获规则
- 具名捕获 (
#(name: Type)): 宏会生成一个包含这些字段的临时结构体Output。 - 行内捕获 (
#(@: Type)): 宏会返回一个元组(或单个值),按照定义的顺序包含捕获的内容。
§示例
fn parser(input: TokenStream) -> Result<()> {
// 场景 1: 配合 `?` 使用 (推荐)
// 表达式 `(input -> ...)` 返回 Result,后面接 `?` 传播错误
let input1 = input.clone();
bind!(
let func = (input1 -> fn #(name: Ident))?;
);
println!("Function: {}", func.name);
// 场景 2: 配合 `unwrap` 使用
// 如果你确定这里一定能解析成功
let input2 = input.clone();
bind!(
let (arrow, ty) = (input2 -> #(@: Token![->]) #(@: Type)).unwrap();
);
// 场景 3: 手动处理 Result
let input3 = input.clone();
bind!(
let result = (input3 -> #(kw: Token![mod]));
);
if let Ok(output) = result {
// ...
}
Ok(())
}The bind! macro mimics a let binding statement. The core expression (<input> -> <pattern>)
expands to a block that evaluates to syn::Result<Output>.
This means you can treat it like any other Result expression, appending ?, .unwrap(),
or .map(...) directly after it.
§Syntax
vacro::bind!(let <binding> = (<input> -> <pattern>) <operations>);- binding: Standard Rust pattern to receive the parsed content (e.g.,
resor(a, b)). - input: A variable implementing
Into<TokenStream>. - pattern: The Vacro pattern description.
- operations: Operations on the
Result, such as?;,.unwrap();, etc.
§Capture Rules
- Named Capture (
#(name: Type)): Generates a temporaryOutputstruct containing these fields. - Inline Capture (
#(@: Type)): Returns a tuple (or single value) containing captured items in order.
§Example
fn parser(input: TokenStream) -> Result<()> {
// Case 1: Using with `?` (Recommended)
// The expression `(input -> ...)` returns Result, `?` propagates error
let input1 = input.clone();
bind!(
let func = (input1 -> fn #(name: Ident))?;
);
println!("Function: {}", func.name);
// Case 2: Using with `unwrap`
// If you are sure parsing will succeed
let input2 = input.clone();
bind!(
let (arrow, ty) = (input2 -> #(@: Token![->]) #(@: Type)).unwrap();
);
// Case 3: Manually handling Result
let input3 = input.clone();
bind!(
let result = (input3 -> #(kw: Token![mod]));
);
if let Ok(output) = result {
// ...
}
Ok(())
}