为什么不能生锈macro_rules!pat 后跟“<”?

Tho*_*eia 3 macros rust

在 L-System 符号中,模式看起来像这样:

A(a)<A(x)>B(b, c) if a+b+c < 10 => B(a+b, a+c)A(x+a+b+c)
Run Code Online (Sandbox Code Playgroud)

我正在尝试编写 rust 宏来扩展这些。所以我有这样的事情:

macro_rules! test {
    ($lc:pat < $a:pat > $rc:pat) => { ... };
}
Run Code Online (Sandbox Code Playgroud)

但它不会让我。它说:

error: `$a:pat` is followed by `>`, which is not allowed for `pat` fragments
 --> src/main.rs:7:23
  |
7 |     ($lc:pat < $a:pat > $rc:pat) => { log_syntax!($lc); log_syntax!($a); log_syntax!($rc); };
  |                       ^ not allowed after `pat` fragments
  |
  = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
Run Code Online (Sandbox Code Playgroud)

为什么在 pat 类型之后不允许这些?我可以匹配什么来获得这个?

我不能使用,tt因为显然不允许使用括号。

Pet*_*all 5

macro_rulesRust 词法分析器发出了输入宏的令牌;属于 Rust 解析器的同一个词法分析器。词法分析器允许许多无效的 Rust 标记序列,在解析正常的 Rust 代码时,这些标记会被管道中的语法规则捕获。然而,词法分析器知道某种级别的上下文,例如,它可以根据它是在处理类型还是表达式来区分<<(左移运算符)和<<(嵌套类型参数的开始)之类的东西。

在许多情况下,宏可以匹配无效的 Rust 标记流,但实现谨慎地禁止词法分析器可能会愉快地发出的许多组合。这样做的原因是允许语言开发人员在不破坏现有宏的情况下灵活地执行诸如添加新语法之类的操作。这条线可能看起来相当随意,部分原因是历史——语言的发展方式以及人们早期发布的宏——但这条线必须在某处划定。

我们保证在摄取有效 Rust 代码的宏(以及许多摄取无效 Rust 代码的宏)中向前兼容,但代价是不允许大量创造性应用程序。随着时间的推移,随着语言和编译器变得越来越稳定,规则可能会逐渐放松,但我想这会慢慢发生,如果有的话。

您的宏匹配无效 Rust 的输入:模式永远不会出现在<和之间>。不幸的是,它也不允许在宏中使用,您可能只需要选择不同的语法。

程序宏的限制较少,也可以作为一种选择。