我正在写一个TT muncher decl宏来解析正则表达式。
我使用的语法示例如下:
regex!(a b c ( a b c )) // equivalent to r"abc(abc)"
regex!('n' s o m e t h i n g) // equivalent to r"\nsomething"
为此,我需要使用$char:ident
或$char:literal
来分别匹配字符或转义字符。
不过,我遇到了一个问题。看起来,一旦标记作为文字匹配,它就不能再与硬编码的值匹配。
下面是rustc 1.69.0上的一个可复制示例:
macro_rules! is_a {
('a') => {"Found literal a"};
($any:literal) => {"Not literal a?"};
(a) => {"Found ident a"};
($any:ident) => {"Not ident a?"};
}
macro_rules! to_lit {
($any:literal) => {is_a!($any)};
}
macro_rules! to_ident {
($any:ident) => {is_a!($any)};
}
fn test() {
println!("{}", is_a!('a')); // Found literal a
println!("{}", is_a!(a)); // Found ident a
println!("{}", to_lit!('a')); // Not literal a?
println!("{}", to_ident!(a)); // Found ident a
}
我可以通过使用不同的语法来解决这个问题,但是我非常困惑为什么它首先会发生。有人能帮我理解吗?
1条答案
按热度按时间guykilcj1#
参考文献:
转发匹配的分片
举例来说,当将匹配的片段转发到另一个宏时,第二个宏中的匹配器将看到片段类型的不透明AST。第二个宏不能使用文字标记来匹配匹配器中的片段,只能使用相同类型的片段说明符。
ident
、lifetime
和tt
片段类型是个例外,* 可以 * 通过文字标记匹配。以下说明了此限制:下面举例说明了如何在匹配
tt
片段后直接匹配令牌:可悲的是没有变通办法;唯一的解决方案是使用proc-macros。