问题描述
我已经在 StackOverflow 上阅读了一堆现有的问题,但我无法弄清楚我的语法。
statement "Statement" =
assignment / primitive / reference / operation
operation "Operation" =
statement operator:operator statement
operator "Operator" =
"+"
* 请注意,稍后我可能会向运算符规则添加更多运算符模式(即“==”、“**”、“/”)。因此,它可能会变得更加复杂。
我实际上在这里使用 PEG.js
而不是普通的 PEG,因此使用了非常规的语法。
编译器向我抱怨 statement
访问了 operation
,而后者又访问了 statement
等等,这会导致可能的无限循环。这通常称为左递归。
对于这种特殊情况,我无法理解如何解决此问题。我不太明白这个场景的头尾模式。
注意:我想尽可能方便地在其他规则中重复使用 statement
规则。因此,将其分成十几个单独的规则作为解决方法可能是一个解决方案,但作为答案并不能真正帮助我。
解决方法
在一些朋友的帮助下,顺便在10分钟内了解了整个PEG解析架构,我能够解决这个场景的问题。
让我们问这个:
在 left+right
形式的操作中,我们是否会在 {{1} 上进行赋值(形式为 a=b
)或其他操作(形式为 a+b
) }}一面?
答案很可能是否定的。
因此,此语法有效:
left
如您所见,我只是将 statement "Statement" =
assignment / operation / primitive / reference
operation "Operation" =
(primitive / reference) operator statement
operator "Operator" =
"+"
规则替换为 statement
规则中的 primitive / reference
部分,省略了 statement
和 { {1}} 部分,因为我们不需要它们在左侧。
这就是解决方案。一切正常。
然而,如果您想知道为什么解析像 assignment
这样的输入有效,尽管我们显然不允许 operation
左侧的递归 1+2+3+4+5
s,请注意我们仍然允许他们在右侧。并且右递归在 PEG 中是完全有效的。