在解析 LiveScript 对象定义时避免左递归

Avoiding left recursion in parsing LiveScript object definitions

我正在为 LiveScript 语言开发解析器,但在同时解析对象 属性 定义形式 — key: value(+|-)key 时遇到了问题。例如:

prop: "val"
+boolProp
-boolProp
prop2: val2

我有 key: value 表格来处理这个:

Expression ::= TestExpression
    | ParenExpression
    | OpExpression
    | ObjDefExpression
    | PropDefExpression
    | LiteralExpression
    | ReferenceExpression

PropDefExpression ::= Expression COLON Expression

ObjDefExpression ::= PropDefExpression (NEWLINE PropDefExpression)*

// ... other expressions

但是我尝试将 ("+"|"-") IDENTIFIER 添加到 PropDefExpressionObjDefExpression,但我得到有关使用左递归的错误。执行此操作的(正确)方法是什么?

您发布的语法片段已经是左递归的,即甚至没有添加 (+|-)boolprop,非终结符 'Expression' 派生出一种形式,其中 'Expression' 重新出现在最左边符号:

Expression -> PropDefExpression -> Expression COLON Expression

而且它不仅是左递归的,而且是模棱两可的。例如

Expression COLON Expression COLON Expression

可以用两种不同的方式推导出来(大致上,左结合与右结合)。

您可以通过在冒号左侧使用更受限制的内容来消除这两个问题,例如:

PropDefExpression ::= Identifier COLON Expression

此外,还有另一个歧义:Expression 以两种不同的方式派生 PropDefExpression,直接派生和通过 ObjDefExpression 派生。我的猜测是,您可以放弃直接推导。

一旦你处理了这些事情,在我看来你应该能够添加 (+|-)boolprop 而不会出错(除非它与你没有的其他类型的表达式之一冲突显示).

请注意,查看 http://livescript.net 中的示例,我怀疑您能否用常规语法捕捉其中的多少。但如果你只是想要一个子集,你可能没问题。

我不知道这会有多大帮助,因为我对 GrammarKit 一无所知,对您尝试解析的语言也不了解。

不过,在我看来

PropDefExpression ::= Expression COLON Expression

不是很准确,当您添加布尔 属性 产生式时它会产生歧义,因为表达式可能以一元 - 运算符开头。但是,在实际语法中,属性 不能以任意表达式开头。有两种key-属性定义:

name : expression
parenthesized_expression : expression

(也就是说,表达式需要以()开头。

这意味着布尔值 属性 定义,以 +- 开头的第一个标记是可识别的,它正是成功进行递归下降解析所需的条件。还有其他几种 属性 定义语法,包括名称和 parenthesized_expressions 后面没有 :

这很容易用 LR(1) 解析器解析,就像 Jison 生成的解析器一样,但是要用递归下降解析器解析它,你需要左因子。 (顺便说一下,GrammarKit 可能会为你做这件事。)基本上,你需要类似的东西(这还不完整):

PropertyDefinition ::= PropertyPrefix PropertySuffix? | BooleanProperty
PropertyPrefix ::= NAME | ParenthesizedExpression
PropertySuffix ::= COLON Expression | DOT NAME