Reputation: 109
The following code is a simple test of macro_rule!
's limit. It correctly prints [1, 2]
as the target.
macro_rules! test {
($target:tt) => {
println!("{:?}", $target);
};
($target:tt, $($rest:tt),*) => {
test!($target)
};
([$target:tt, $($inner_rest:tt),*],$($rest:tt),*) => {
test!($target)
}
}
fn main() {
test![[1, 2], [[5, 6], 3], 4];
}
However, if I change [[1,2]
to [[1,2],3]
, the compiler complains:
<anon>:16:15: 16:16 error: mismatched types:
expected `[_; 2]`,
found `_`
(expected array of 2 elements,
found integral variable) [E0308]
<anon>:16 test![[[1,2],3],[[5,6],3],4];
^
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
<anon>:4:5: 4:30 note: in this expansion of println! (defined in <std macros>)
<anon>:7:6: 7:20 note: in this expansion of test! (defined in <anon>)
<anon>:16:2: 16:31 note: in this expansion of test! (defined in <anon>)
<anon>:16:15: 16:16 help: see the detailed explanation for E0308
error: aborting due to previous error
playpen: application terminated with error code 101
Is there a way to let the macro recursively deal with brackets and print the first item? I have studied the example given by the Rust documentation, but still have no idea about how to implement it in my case.
Upvotes: 2
Views: 993
Reputation: 59135
You asked it to parse an expression, so that's exactly what it tried to do.
The first thing it sees is [[1, 2], 3]
which is invalid because it's an array literal where the first element is of type [i32; 2]
and the second element is of type i32
. So, it fails.
If you want to macro to deal with recursive syntax, you're going to have to write it to handle it. I have no idea what you're trying to do ("deal with bracket" how?), so I can't offer a concrete example. Try adding an extra rule before the existing ones that explicitly deals with [[$($stuff:tt)*] ...
. Rules are processed top-to-bottom, so you need to put the most specific rule first. The following prints out [1, 2]
:
macro_rules! test {
([$target:tt, $($inner_rest:tt),*], $($rest:tt),*) => {
test!($target)
};
($target:tt) => {
println!("{:?}", $target);
};
($target:tt, $($rest:tt),*) => {
test!($target)
};
}
fn main() {
test![[[1,2],3],[[5,6],3],4];
}
Upvotes: 3