在尝试将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!
作为$xstuff
接收到的表达式传输到lower!
?
答案 0 :(得分: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');
}
另请参阅: