我正在尝试解析逗号分隔的列表。为了简化起见,我只是使用数字。这些表达式将有效:
(1, 4, 3)
()
(四)
我可以想到两种方法来做到这一点,我想知道为什么失败的示例不起作用。我相信这是一个正确的 BNF,但我无法让它作为 PEG 工作。谁能解释为什么?我试图更好地了解PEG解析逻辑。
我正在这里使用在线浏览器解析器生成器进行测试: https://pegjs.org/online
这不起作用:
list = '(' some_digits? ')'
some_digits = digit / ', ' some_digits
digit = [0-9]
(实际上,它解析正常,喜欢()或(1)但无法识别(1,2)
但这确实有效:
list = '(' some_digits? ')'
some_digits = digit another_digit*
another_digit = ', ' digit
digit = [0-9]
为什么?(语法新手在这里)
很酷的问题,在他们的文档中挖掘了一秒钟后,我发现/
字符的意思是:
尝试匹配第一个表达式,如果不成功,请尝试 第二个,等等。返回第一个成功匹配结果 匹配的表达式。如果没有匹配的表达式,请考虑匹配 失败。
因此,这让我找到了解决方案:
list = '(' some_digits? ')'
some_digits = digit ', ' some_digits / digit
digit = [0-9]
这样做的原因:
输入: (1, 4)
- 吃'('
- 检查是否有一些数字?
- 检查some_digits - 第一个条件:
- 吃 '1'
- 吃', '
- 检查some_digits - 第一个条件:
- 吃 '4'
- 吃不下', '
- 检查some_digits - 第二个条件:
- 吃 '4'
- 成功
- 成功
- 吃')'
- 成功
如果颠倒some_digits
条件的顺序,遇到的第一个数字会被digit
吃掉,并且不会发生递归。然后它会抛出一个错误,因为")"不存在。
在一行中:
some_digits = '(' digit (', ' digit)* ')'
这取决于你想要的值和PEG实现,但这样提取它们可能会更容易。