如何在Rust的macro_rules模式中使用&和|符号
解决Rust宏中直接匹配
&/|运算符的问题 你遇到的核心问题是Rust宏的expr片段会贪婪匹配完整的合法表达式——a & b本身在Rust中是一个合法的位与表达式,所以$value_1:expr会直接把a & b整个吞掉,导致你的前两个宏模式永远无法触发,只会走到最后一个Value分支。
解决方案:使用primary片段+递归宏
利用Rust宏内置的primary片段(仅匹配原子表达式,不包含二元运算符),配合递归宏可以正确拆分&/|左右的操作数,无需额外括号。
修改后的完整代码:
enum Term { Or(Box<Term>, Box<Term>), And(Box<Term>, Box<Term>), Value(u8), } macro_rules! term { // 处理 & 运算:匹配原子左操作数 + & + 剩余token流,递归处理右侧 ($lhs:primary & $($rest:tt)+) => { Term::And(Box::new(term!($lhs)), Box::new(term!($($rest)+))) }; // 处理 | 运算,逻辑同上 ($lhs:primary | $($rest:tt)+) => { Term::Or(Box::new(term!($lhs)), Box::new(term!($($rest)+))) }; // 处理括号包裹的表达式,递归解析内部内容 (($e:expr)) => { term!($e) }; // 处理单个值 ($val:expr) => { Term::Value($val) }; }
使用示例
fn main() { // 无需额外括号,直接解析嵌套运算 let nested = term!(1 & 2 | 3 & 4); // 等价于 Term::Or( // Box::new(Term::And(Box::new(Term::Value(1)), Box::new(Term::Value(2)))), // Box::new(Term::And(Box::new(Term::Value(3)), Box::new(Term::Value(4)))) // ) // 原生运算符表达式需要括号包裹,因为primary不匹配带二元运算符的表达式 let with_rust_ops = term!((1 + 2) & (3 * 4)); // 等价于 Term::And(Box::new(Term::Value(3)), Box::new(Term::Value(12))) }
注意事项
如果操作数本身是包含Rust原生二元运算符(如+、*)的表达式,仍然需要用括号包裹——这是合理的,否则宏无法区分你是要使用Rust原生运算符还是自定义的&/|来构造Term。
内容的提问来源于stack exchange,提问作者er1t
相关产品推荐
相关产品推荐

