我在宏中调用宏,即
macro_rules! foo {
(yes) => {
true
};
() => {
false
};
}
macro_rules! baz {
() => {
[(); 0]
};
($args: tt) => {
$args
};
}
macro_rules! parse_rule {
($rule: tt, $args: tt, $newline: expr) => {
println!("The rule is {}, with args {:?}", $rule, $args);
if $newline {
println!()
}
};
}
macro_rules! bar {
($($rule: tt $([$($args: tt),*])? $($flag: ident)?);+) => {
$(parse_rule!($rule, baz!($([$($args),*])?), foo!($($flag)?)));+
}
}
fn main() {
bar!("hi" yes; "there" ["are", "some", "args"]; "no" yes);
}
编译器提示我在baz
调用中调用parse_rule
:error: no rules expected the token `!`
--> src/main.rs:30:33
|
19 | macro_rules! parse_rule {
| ----------------------- when calling this macro
...
30 | $(parse_rule!($rule, baz!($([$($args),*])?), foo!($($flag)?)));+
| ^ no rules expected this token in macro call
...
35 | bar!("hi" yes; "there" ["are", "some", "args"]; "no" yes);
| ---------------------------------------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
为什么不扩展?
最佳答案
宏将使用其未扩展的参数来调用。 macro_call!(arg)
是的三棵 token 树,而不是一棵:
macro_rules! example {
($($x:tt)+) => {
$(eprintln!(">{}<", stringify!($x));)*
}
}
fn main() {
example!(macro_call!(arg));
}
>macro_call<
>!<
>(arg)<
您的宏仅允许使用单个 token 树($args: tt
)。匹配宏的名称,保留!
。没有任何匹配,因此您会遇到错误。您可能需要
$args: expr
。is there a way to expand it before? I want to parse some of the elements of the array manually
据我所知,没有“更渴望”的扩展。在各种RFC(例如Eager Macro Expansion — 2320)中都提出了建议。
我建议您对代码进行重排,以便
parse_rule
调用foo
/bar
本身,或者将foo
/bar
的逻辑直接烘焙到parse_rule
中。内部规则对此非常普遍。也可以看看:
关于rust - 为什么另一个宏内的宏调用不会扩展,而是出现 “no rules expected the token ` !`”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65204193/