0

higher!尝试将宏接收到的表达式传递给宏时,我不理解这种失败lower!

// A low-level macro using only Rust primitives.
macro_rules! lower {
    (x, $a:expr) => {
        println!("x is {}", $a);
    };
    (x($b:expr), $a:expr) => {
        println!("x({}) is rather {}", $b, $a);
    };
}

// A higher-level macro using my own previous macro.
macro_rules! higher {
    ($xstuff:expr, $a:expr) => {
        // Here, I expect transferring the expression $xstuff to lower!.. but it fails.
        lower!($xstuff, $a)
    };
}

fn main() {
    lower!(x, '5'); // x is 5
    lower!(x(8), '6'); // x(8) is rather 6

    higher!(x(7), '9'); 
}
error: no rules expected the token `x(7)`
  --> src/main.rs:15:16
   |
2  | macro_rules! lower {
   | ------------------ when calling this macro
...
15 |         lower!($xstuff, $a)
   |                ^^^^^^^ no rules expected this token in macro call
...
23 |     higher!(x(7), '9'); 
   |     ------------------- in this macro invocation

我希望最后一个标记符合 中的规则lower!,但编译器告诉我这是出乎意料的。我在这里想念什么?如何转移higher!as $xstuffto收到的表达式lower!

4

1 回答 1

1

在调用 之后higher!x(7)已将其解析为宏变量持有的完整表达式$xstuff

    ($xstuff:expr, $a:expr) => { /* ... */ }
//           ^~~~

但是,这两个宏规则都不lower!接受任意表达式作为第一个参数,它们只接受令牌x

    (x, $a:expr) => { /* ... */ }
//   ^
    (x($b:expr), $a:expr) => { /* ... */ }
//   ^

最简单的解决方法是x在更高的宏中设置相同的限制:

macro_rules! higher {
    (x($xstuff:expr), $a:expr) => {
        lower!(x($xstuff), $a)
    };
}

另一种解决方案(改变调用语法)是不立即解析x(7)为表达式,而是一个标记树的集合。您需要在调用站点添加其他分组,以便解析器知道何时停止:

macro_rules! higher {
    (($($xstuff:tt)*), $a:expr) => {
        lower!($($xstuff)*, $a)
    };
}

fn main() {
    higher!((x(7)), '9');
}

也可以看看:

于 2019-06-20T16:33:25.597 回答