【问题标题】:Avoiding left recursion in parsing LiveScript object definitions在解析 LiveScript 对象定义时避免左递归
【发布时间】:2015-03-01 19:57:11
【问题描述】:

我正在开发 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,我得到关于使用左递归的错误。这样做的(正确)方法是什么?

【问题讨论】:

  • 您使用的是什么解析器生成器(如果您想发表评论,为什么选择那个而不是生成自底向上解析器的解析器)?
  • 我正在为 IntelliJ IDEA IDE 开发 LiveScript 插件,根据他们的tutorial,我正在使用JFlex lexer + GrammarKit parser plugin。而且我对解析器和 IntelliJ 插件开发的了解太少,无法寻找替代方案。
  • 很公平。显然 GrammarKit 构建了一个递归下降语法,尽管它的文档有点杂乱无章,所以我可能会遗漏一些东西。我对 livescript 也不太了解,但它似乎不适用于 LL(1) 解析,它的解析器是用 Jison 构建的,它构建自下而上的 LALR(1) 解析器。 (github.com/gkz/LiveScript/blob/master/src/grammar.ls)。简而言之,我想我帮不了你太多。对不起。

标签: recursion context-free-grammar ebnf livescript grammar-kit


【解决方案1】:

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

Expression -> PropDefExpression -> Expression COLON Expression

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

Expression COLON Expression COLON Expression

可以通过两种不同的方式派生(大致而言,左关联与右关联)。

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

PropDefExpression ::= Identifier COLON Expression

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

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

请注意,看看http://livescript.net 上的示例,我怀疑你能在传统语法中捕捉到多少。但是,如果您只是选择一个子集,您可能还可以。

【讨论】:

  • Grammar-Kit 允许通过一种类似 OO 的扩展机制进行一些(伪?)递归,所以这并不是问题所在。但我确实通过用更有限/特定的表达式重写文件来解决它,所以我接受这个作为答案。
【解决方案2】:

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

但是,在我看来

PropDefExpression ::= Expression COLON Expression

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

name : expression
parenthesized_expression : expression

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

这意味着以 +- 开头的布尔属性定义可以从第一个标记中识别出来,这正是成功递归下降解析所需的条件。还有其他几种属性定义语法,包括名称和括号表达式不跟随

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-15
    • 2016-10-17
    • 1970-01-01
    相关资源
    最近更新 更多