了解 Parboiled2 的“~”组合器

Understanding Parboiled2's '~' Combinator

查看 parboiled2 部分,Rule Combinators and Modifiers:

aba ~ b图我都看不懂。

到目前为止,我发现文档很简单。但是这里有点迷路

你能解释一下每个块吗?

这里是Rule的定义:

class Rule[-I <: HList, +O <: HList]

您链接的文档提供了更多解释,但本质上 I 是规则的输入,O 是规则的输出。冒号符号可能有点令人困惑。 parboiled2 使用堆栈来管理状态。请记住,冒号列表 (HList) 中的类型从左到右是 produced/pushed,从右到左是 consumed/popped。在HListA:B:C中,C是栈顶,必须先消费。

~ 运行先一条规则再下一条。因此,在第一个示例中,Rule[, A] 类型的 a 不消耗任何东西,而 'produces' 一个 A,而 Rule[, B] 类型的 b 不消耗任何东西,并且 'produces'一个B。那么,如果 运行 a 后跟 b,就会产生 A 后跟 B。结果类型是 Rule[, A:B].

当您添加输入时,事情变得更加复杂。您需要确保 a(或第一个规则是什么)生成的类型是 b 将使用的类型。 ~ 就像函数组合一样。如果我们要将gf组合起来得到g . f,我们需要确保f的输出与[=34=的输入是同一类型].

我们来看table中的第三个例子。

  • a 类型为 Rule[A, B:C]
  • b 具有类型 Rule[D:B:C, E:F]

当我们运行a从栈中消费了一个A,栈中加入了一个B,又加入了一个C到堆栈。然后 b 是 运行,首先它消耗了 C,然后是 B,然后它从堆栈中消耗了一个 D。要在正确的时间出现在正确的位置,D 需要在 a 消耗的 A 之下。 b 然后会产生一个 E 然后一个 F.

我们总共消耗了 DABC 不算在内,因为它们是在规则内部生产和消费的。在消耗 DA 之后,我们将 EF 留在堆栈上。所以,a ~ b 的类型是 Rule[D:A, E:F].

README 中的第四个示例给出了一个示例,其中 a 生成错误的类型供 b 使用。在那种情况下 a ~ b 是非法的。