You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 23:42:07