【问题标题】:Why cant rust macro_rules! pat be followed by "<"?为什么不能生锈macro_rules!拍后跟“<”?
【发布时间】:2020-10-19 23:01:19
【问题描述】:

在 L-System 表示法中,模式看起来像这样:

A(a)<A(x)>B(b, c) if a+b+c < 10 => B(a+b, a+c)A(x+a+b+c)

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

macro_rules! test {
    ($lc:pat < $a:pat > $rc:pat) => { ... };
}

但它不会让我。它说:

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`

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

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

【问题讨论】:

  • 这里的 A(a)A(x)B(b, c) 是否应该代表任意的 Rust 模式,就像您在 matchif let 表达式中可能发现的那样?还是它们实际上是一些更受限制的语法,恰好是 pat 可以匹配的子集?如果是后者,您可以编写一个 TT-muncher,将输入拆分为 &lt;&gt;,然后一举匹配。

标签: rust macros


【解决方案1】:

Rust 词法分析器已经发出了输入macro_rules 宏的令牌;同一个词法分析器,它是 Rust 解析器的一部分。词法分析器允许许多无效的 Rust 标记序列,当解析正常的 Rust 代码时,这些标记序列将被管道中的语法规则捕获。但是,词法分析器知道某种级别的上下文,例如,它可以根据是否处理类型或表达。

在许多情况下,宏可以匹配不是有效 Rust 的令牌流,但出于谨慎的考虑,实现会出错,以禁止词法分析器可能会愉快地发出许多组合。这样做的原因是允许语言开发人员在不破坏现有宏的情况下灵活地执行诸如添加新语法之类的事情。这条线可能看起来相当武断,部分原因是历史 - 语言如何发展以及人们早期发布的宏 - 但这条线必须在某个地方划定。

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

您的宏匹配无效 Rust 的输入:模式永远不会出现在 &lt;&gt; 之间。不幸的是,宏中也不允许这样做,您可能不得不选择不同的语法。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2012-12-18
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    相关资源
    最近更新 更多