While trying to create a macro to ease the reading of my code, I found a "local ambiguity" in the macro. I cannot really understand how this is ambiguous though: in each arm of my bracket, the value I'm parsing is preceded by a unique prefix.
macro_rules! test {
(rule_a=$value: expr $(, $($rest: tt)*),*) => {
println!("Rule A: {}", stringify!($value));
test!($($($rest)*),*)
};
(rule_b=$value: ident $(, $($rest: tt)*),*) => {
println!("Rule B: {}", stringify!($value));
test!($($($rest)*),*)
};
(rule_c=$value: ident $(, $($rest: tt)*),*) => {
println!("Rule C: {}", stringify!($value));
test!($($($rest)*),*)
};
() => {
println!("End");
};
}
fn main() {
// Working
test!(rule_a="Great test", rule_b=i32);
// Working
test!(rule_a="Great test", rule_c=i64);
// "Local ambiguity"
test!(rule_a="Great test", rule_b=i32, rule_c=i64);
}
error: local ambiguity when calling macro `test`: multiple parsing options: built-in NTs tt ('rest') or 1 other option.
--> src/main.rs:25:42
|
25 | test!(rule_a="Great test", rule_b=i32, rule_c=i64);
| ^
How am I supposed to solve this problem? I tried looking around, but did not really found any useful resources to help solve this...
,
is a valid token, so it matches both $rest:tt
and the ,
in ),*
. You need to make the first ,
optional, then have any further ,
be part of $rest
.
macro_rules! test {
(rule_a = $value:expr $(, $($rest:tt)* )?) => {
println!("Rule A: {}", stringify!($value));
test!($($($rest)*),*)
};
(rule_b = $value:ident $(, $($rest:tt)* )?) => {
println!("Rule B: {}", stringify!($value));
test!($($($rest)*),*)
};
(rule_c = $value:ident $(, $($rest:tt)* )?) => {
println!("Rule C: {}", stringify!($value));
test!($($($rest)*)?)
};
() => {
println!("End");
};
}