rust 一旦标记作为文字使用,Decl宏不匹配硬编码值?

aamkag61  于 2023-06-06  发布在  其他
关注(0)|答案(1)|浏览(187)

我正在写一个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
}

我可以通过使用不同的语法来解决这个问题,但是我非常困惑为什么它首先会发生。有人能帮我理解吗?

guykilcj

guykilcj1#

参考文献:

转发匹配的分片

举例来说,当将匹配的片段转发到另一个宏时,第二个宏中的匹配器将看到片段类型的不透明AST。第二个宏不能使用文字标记来匹配匹配器中的片段,只能使用相同类型的片段说明符。identlifetimett片段类型是个例外,* 可以 * 通过文字标记匹配。以下说明了此限制:

macro_rules! foo {
    ($l:expr) => { bar!($l); }
// ERROR:               ^^ no rules expected this token in macro call
}

macro_rules! bar {
    (3) => {}
}

foo!(3);

下面举例说明了如何在匹配tt片段后直接匹配令牌:

// compiles OK
macro_rules! foo {
    ($l:tt) => { bar!($l); }
}

macro_rules! bar {
   (3) => {}
}

foo!(3);

可悲的是没有变通办法;唯一的解决方案是使用proc-macros。

相关问题