macros - 如何在宏中匹配 Rust 的 `if` 表达式?

标签 macros rust rust-macros

我正在尝试编写一个宏来重写某些 Rust 控制流,但我在匹配 if 表达式时遇到困难。问题在于谓词是一个表达式,但是 expr 不允许后跟 block{

我最好的方法是使用 tt:

macro_rules! branch {
    (
        if $pred:tt 
            $r1:block
        else
            $r2:block
    ) => {
        if $pred { 
            $r1
        } else {
            $r2
        }
    };
}

这适用于单标记或分组谓词:

branch! {
    if (foo == bar) {
        1
    } else {
        2
    }
}

但如果谓词未分组则失败:

branch! {
    if foo == bar {
        1
    } else {
        2
    }
}
error: no rules expected the token `==`

我还尝试在谓词中使用 tt 的重复模式:

macro_rules! branch {
    (
        if $($pred:tt)+
            $r1:block
        else
            $r2:block
    ) => {
        if $($pred)+ { 
            $r1
        } else {
            $r2
        }
    };
}

但这会产生一个错误,因为现在不清楚后续 block 是否也应与 tt 匹配:

error: local ambiguity: multiple parsing options: built-in NTs tt ('pred') or block ('r1').

有没有办法做到这一点,还是我坚持发明特殊语法以在宏中使用?

最佳答案

你可以使用 TT muncher解析谓词:

macro_rules! branch {
    {
        if $($rest:tt)*
    } => {
        branch_parser! {
            predicate = ()
            rest = ($($rest)*)
        }
    };
}

macro_rules! branch_parser {
    {
        predicate = ($($predicate:tt)*)
        rest = ({ $($then:tt)* } else { $($else:tt)* })
    } => {
        println!("predicate: {}", stringify!($($predicate)*));
        println!("then: {}", stringify!($($then)*));
        println!("else: {}", stringify!($($else)*));
    };

    {
        predicate = ($($predicate:tt)*)
        rest = ($next:tt $($rest:tt)*)
    } => {
        branch_parser! {
            predicate = ($($predicate)* $next)
            rest = ($($rest)*)
        }
    };
}

fn main() {
    branch! {
        if foo == bar {
            1
        } else {
            2
        }
    }
}

输出:

predicate: foo == bar
then: 1
else: 2

关于macros - 如何在宏中匹配 Rust 的 `if` 表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51932944/

相关文章:

rust - 在 Rust 中多次使用具有相同变量名的 let 关键字

rust - 如何使用宏根据架构定义具有不同调用约定的函数?

rust - 为什么 Rust 认为我的私有(private)类型必须是公共(public)的,除非我使用 pub(crate)?

struct - 如何在不为每个字段重复 `pub` 的情况下创建所有字段都是公共(public)的公共(public)结构?

c++ - 将参数从可变参数函数转发到固定参数函数

c++ - "class _LIBCPP_TEMPLATE_VIS vector"中宏_LIBCPP_TEMPLATE_VIS的用法是什么

c - 为什么某些预处理器宏不展开,除非它们是另一个宏的参数?

rust - String::from ("") & "".to_string() 在 Rust 中有何不同?

c - 为什么在枚举中#define 相同的项目?

rust - 在其他情况下返回特征 : In some cases works, 的特征