我正在尝试匹配structRust 宏中的 a 。我需要把它
struct稍微拆开才能得到它的名字。我认为块匹配器可以解决这个问题。考虑一下,例如:
macro_rules! multi {
(struct $name:ident $block:block) => {
enum George {$name}
}
}
multi!{
struct Fred {
a:String
}
}
Run Code Online (Sandbox Code Playgroud)
扩展到
enum George { Fred, }
Run Code Online (Sandbox Code Playgroud)
这是正确的。
但是,如果我将其转回 a struct,则会失败。
macro_rules! multi {
(struct $name:ident $block:block) => {
struct $name $block
}
}
Run Code Online (Sandbox Code Playgroud)
这给出了这个错误。
macro_rules! multi {
(struct $name:ident $block:block) => {
enum George {$name}
}
}
multi!{
struct Fred {
a:String
}
}
Run Code Online (Sandbox Code Playgroud)
看起来像是{a: String}被视为单个令牌,而不是被重新解析;但这就是里面应该发生的事情。
匹配$:block器用于块表达式,即一组包含零个或多个 Rust 语句和项以及可选尾随返回值的花括号。例如以下是块:
{
let x = 1;
}
Run Code Online (Sandbox Code Playgroud)
{
#[derive(Default)]
struct S;
S::default()
}
Run Code Online (Sandbox Code Playgroud)
Rust 中作为块的花括号的示例有:
if和else条款,for、while、 和循环的循环体loop。结构体字段周围的大括号不是一个块,因为它们不应该包含零个或多个 Rust 语句和项目,后跟可选的尾部返回值。相反,它们应该包含结构字段的名称和类型。
在宏中,您可以使用模式匹配任意一组花括号{ $($tt:tt)* },这意味着“包含任意数量的任意标记的花括号”。
macro_rules! multi {
(struct $name:ident { $($tt:tt)* }) => {
struct $name { $($tt)* }
};
}
multi! {
struct Fred {
a: String,
}
}
Run Code Online (Sandbox Code Playgroud)