了解 Parboiled2 的“~”组合器
Understanding Parboiled2's '~' Combinator
查看 parboiled2 部分,Rule Combinators and Modifiers
:
a
、b
、a ~ b
图我都看不懂。
到目前为止,我发现文档很简单。但是我这里有点迷路
你能解释一下每个块吗?
这里是Rule
的定义:
class Rule[-I <: HList, +O <: HList]
您链接的文档提供了更多解释,但本质上 I
是规则的输入,O
是规则的输出。冒号符号可能有点令人困惑。 parboiled2
使用堆栈来管理状态。请记住,冒号列表 (HList
) 中的类型从左到右是 produced/pushed,从右到左是 consumed/popped。在HList
A:B:C
中,C
是栈顶,必须先消费。
~
运行先一条规则再下一条。因此,在第一个示例中,Rule[, A]
类型的 a
不消耗任何东西,而 'produces' 一个 A
,而 Rule[, B]
类型的 b
不消耗任何东西,并且 'produces'一个B
。那么,如果 运行 a
后跟 b
,就会产生 A
后跟 B
。结果类型是 Rule[, A:B]
.
当您添加输入时,事情变得更加复杂。您需要确保 a
(或第一个规则是什么)生成的类型是 b
将使用的类型。 ~
就像函数组合一样。如果我们要将g
和f
组合起来得到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
.
我们总共消耗了 D
和 A
。 B
和 C
不算在内,因为它们是在规则内部生产和消费的。在消耗 D
和 A
之后,我们将 E
和 F
留在堆栈上。所以,a ~ b
的类型是 Rule[D:A, E:F]
.
README 中的第四个示例给出了一个示例,其中 a
生成错误的类型供 b
使用。在那种情况下 a ~ b
是非法的。
查看 parboiled2 部分,Rule Combinators and Modifiers
:
a
、b
、a ~ b
图我都看不懂。
到目前为止,我发现文档很简单。但是我这里有点迷路
你能解释一下每个块吗?
这里是Rule
的定义:
class Rule[-I <: HList, +O <: HList]
您链接的文档提供了更多解释,但本质上 I
是规则的输入,O
是规则的输出。冒号符号可能有点令人困惑。 parboiled2
使用堆栈来管理状态。请记住,冒号列表 (HList
) 中的类型从左到右是 produced/pushed,从右到左是 consumed/popped。在HList
A:B:C
中,C
是栈顶,必须先消费。
~
运行先一条规则再下一条。因此,在第一个示例中,Rule[, A]
类型的 a
不消耗任何东西,而 'produces' 一个 A
,而 Rule[, B]
类型的 b
不消耗任何东西,并且 'produces'一个B
。那么,如果 运行 a
后跟 b
,就会产生 A
后跟 B
。结果类型是 Rule[, A:B]
.
当您添加输入时,事情变得更加复杂。您需要确保 a
(或第一个规则是什么)生成的类型是 b
将使用的类型。 ~
就像函数组合一样。如果我们要将g
和f
组合起来得到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
.
我们总共消耗了 D
和 A
。 B
和 C
不算在内,因为它们是在规则内部生产和消费的。在消耗 D
和 A
之后,我们将 E
和 F
留在堆栈上。所以,a ~ b
的类型是 Rule[D:A, E:F]
.
README 中的第四个示例给出了一个示例,其中 a
生成错误的类型供 b
使用。在那种情况下 a ~ b
是非法的。