如何在宏中匹配 Rust 的 if 表达式?
How to match Rust's `if` expressions in a macro?
我正在尝试编写一个宏来重写某些 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
}
};
}
但这会产生错误,因为现在还不清楚后续块是否也应与 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
我正在尝试编写一个宏来重写某些 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
}
};
}
但这会产生错误,因为现在还不清楚后续块是否也应与 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