Reputation: 321
I'm calling a macro within a macro, i.e
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);
}
The compiler complains about me calling baz
within the parse_rule
invocation:
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)
Why does it not expand?
Upvotes: 0
Views: 1722
Reputation: 430524
Macros are are invoked with their unexpanded arguments. macro_call!(arg)
is three token trees, not one:
macro_rules! example {
($($x:tt)+) => {
$(eprintln!(">{}<", stringify!($x));)*
}
}
fn main() {
example!(macro_call!(arg));
}
>macro_call<
>!<
>(arg)<
Your macro only allows for a single token tree ($args: tt
). That matches the macro's name, leaving the !
. That isn't matched by anything, so you get your error.
You probably want $args: expr
.
is there a way to expand it before? I want to parse some of the elements of the array manually
There's no "more eager" expansion, that I know of. It has been suggested in various RFCs (e.g. Eager Macro Expansion — 2320).
I'd suggest reflowing your code such that parse_rule
calls foo
/ bar
itself, or baking the logic of foo
/ bar
directly into parse_rule
. Internal rules are quite common for this.
See also:
Upvotes: 5