rust - 为什么另一个宏内的宏调用不会扩展,而是出现 “no rules expected the token ` !`”?

标签 rust compiler-errors macros

我在宏中调用宏,即

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中。内部规则对此非常普遍。
也可以看看:
  • What does an @ symbol mean in a Rust declarative macro?
  • 关于rust - 为什么另一个宏内的宏调用不会扩展,而是出现 “no rules expected the token ` !`”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65204193/

    相关文章:

    rust - 在 rust 中将 JSON 解析为 Map

    rust - 如何从同一类型的另一个方法内部调用带有 &mut self 的方法?

    python - "file"对象没有属性 '__getitem__' 并且缺少模块

    c - 是否需要所有函数参数?

    c++ - 为什么 gcc 在递归扩展宏时中断

    rust - 读取字符串直到换行

    casting - 如何将 Vec<&mut T> 转换为 Vec<&T>?

    java - 更改 Android TextView 可见性时出错

    C 成语和鲜为人知的事实

    macros - 在宏输出中转义逗号