我正在尝试构建一个宏,该宏将使用函数调用列表 ( test2()
) 或标识符 ( test3
) 进行调用:
invoke!(
["str1", "str2"]: i32 => test1(), test2(), test3, test4;
["str3", "str1"]: i32 => test1(), test3;
)
目前,它只支持函数调用:
invoke!(
["str1", "str2"]: i32 => test1(), test2();
["str3", "str1"]: i32 => test1();
)
原始宏代码:
macro_rules! invoke {
( $([$($field:expr),*]: $vtype:ty => $($func:ident$args:tt),*; )+ ) => {
$(
let x = vec![$($field),*];
let y = vec![$($func$args),*];
println!("{:#?}: {:#?}", x, y)
)+
};
}
当我尝试将其更改为支持两种形式时:
macro_rules! invoke {
( $([$($field:expr),*]: $vtype:ty => $($func:ident$args:tt),* $($newfunc:ident),*; )+ ) => {
$(
let x = vec![$($field),*];
let y = vec![$($func$args),*];
let z: Vec<$vtype> = vec![$newfunc()];
println!("{:#?}: {:#?} [{:#?}]", x, y, z)
)+
};
}
我收到一个错误:
error: local ambiguity: multiple parsing options: built-in NTs ident ('func') or ident ('newfunc').
--> src/main.rs:15:34
|
15 | ["str1", "str2"]: i32 => test1(), test2(), test3, test4;
| ^^^^^
我知道可以通过
:tt
构建这个宏,但我找不到方法。Working code sample
Expected and not working code sample
最佳答案
这个宏模式没有意义:
$($func:ident$args:tt),* $($newfunc:ident),*;
这表示要解析零个或多个标识符 (
func
) 后跟零个或多个标识符 ( newfunc
)。如果输入是 ident foo
,那么解析器将无法决定选择哪个语法路径,因为前瞻有限(大概是一个标记)。正如评论中所指出的,最简单的解决方案是引入新的语法来消除这些情况的歧义。
macro_rules! invoke {
( $([$($field:expr),*]: $vtype:ty => $($func:ident$args:tt),* [$($newfunc:ident),*]; )+ ) => {{
$(
let x = vec![$($field),*];
let y = vec![$($func$args),*];
let z: Vec<$vtype> = vec![$($newfunc()),*];
println!("{:#?}: {:#?} [{:#?}]", x, y, z);
)+
}};
}
fn main() {
invoke!(
["str1", "str2"]: i32 => test1(), test2() [test3, test4];
["str3", "str1"]: i32 => test1() [test3];
);
}
fn test1() -> i32 { 42 }
fn test2() -> i32 { 42 }
fn test3() -> i32 { 42 }
fn test4() -> i32 { 42 }
我所知道的宏中没有可选的修饰符。通常,这是通过具有多个并行模式来处理的:
macro_rules! thing {
($name:ident$args:tt) => { println!("a") };
($name:ident) => { println!("b") };
}
fn main() {
thing!(foo); // b
thing!(foo()); // a
}
这似乎对您的情况没有帮助,因为您希望先收集一堆 A,然后再收集一堆 B。这将允许一堆 A 或 B。在语法上,它类似于
(A|B)* # This form
A*B* # What you want
关于macros - 向 "local ambiguity: multiple parsing options"中的多次重复结果添加 ident,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42885668/