我不确定如何用这句话,所以问题标题很垃圾,但这就是我要做的事情:
我可以写这个宏:
macro_rules! op(
( $v1:ident && $v2:ident ) => { Op::And($v1, $v2) };
( $v1:ident || $v2:ident ) => { Op::Or($v1, $v2) };
);
我可以这样使用:
let _ = op!(Expr || Expr);
let _ = op!(Expr && Expr);
我想要做的是写一个任意的令牌序列,如下所示:
let _ = op!(Expr || Expr || Expr && Expr || Expr);
哪个解析为令牌的Vec,例如:
vec!(T::Expr(e1), T::Or, T::Expr(e2), T::Or, ...)
我可以写一个vec!像宏:
macro_rules! query(
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(temp_vec.push($x);)*
temp_vec
}
};
);
...但我无法看到如何在宏运行时将任意符号(例如&&)转换为标记。
这有可能吗?
围栏链接:http://is.gd/I9F5YV
答案 0 :(得分:1)
似乎在宏扩展期间捕获任意符号匹配是不可能的:正如语言参考所述,“有效的指示符是item,block,stmt,pat,expr,ty(type),ident,path,tt”。所以我建议的最好的方法是使用“ident” - 有效的标记,例如“和”/“或”代替“&&”/“||”,例如:
macro_rules! query_op(
( and ) => { "T::And" };
( or ) => { "T::Or" };
( $e:ident ) => { concat!("T::Expr(", stringify!($e), ")") };
);
macro_rules! query(
( $( $x:ident )* ) => {
{
let mut temp_vec = Vec::new();
$(temp_vec.push(query_op!($x));)*
temp_vec
}
};
);
fn main() {
let q = query!(Expr1 or Expr2 and Expr3 or Expr4);
println!("{:?}", q);
}
输出:
["T::Expr(Expr1)", "T::Or", "T::Expr(Expr2)", "T::And", "T::Expr(Expr3)", "T::Or", "T::Expr(Expr4)"]