5

我正在尝试解析逗号分隔的列表。为了简化,我只是使用数字。这些表达式将是有效的:

(1, 4, 3)

()

(4)

我可以想到两种方法来做到这一点,我想知道为什么失败的例子不起作用。我相信这是一个正确的 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]

这是为什么?(这里是语法新手)

4

2 回答 2

3

很酷的问题,在他们的文档中挖掘了一秒钟后,我发现这个/角色的意思是:

尝试匹配第一个表达式,如果不成功,尝试第二个,等等。返回第一个成功匹配的表达式的匹配结果。如果没有表达式匹配,则认为匹配失败。

所以这让我找到了解决方案:

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并且不会发生递归。然后它会抛出一个错误,因为 ')' 不存在。

于 2019-06-12T02:30:43.313 回答
0

在一行中:

some_digits = '(' digit (', ' digit)* ')'

这取决于您想要的值和 PEG 实现,但是通过这种方式提取它们可能更容易。

于 2022-02-15T00:19:32.717 回答