左递归语法识别

时间:2013-10-22 22:31:44

标签: algorithm parsing recursion grammar

通常我们想重构一个无上下文语法来删除左递归。有许多算法来实现这种转换;例如herehere

无论是否存在左递归,此类算法都将重构语法。这具有负面的副作用,例如从原始语法产生不同的解析树,可能具有不同的关联性。理想情况下,如果绝对必要,语法只会被转换。

是否有算法或工具来识别语法中是否存在左递归?理想情况下,这也可能会对包含左递归的生产规则的子集进行分类。

1 个答案:

答案 0 :(得分:2)

有一种用于识别可空的非终端的标准算法,该算法在语法大小上按时间线性运行(见下文)。完成后,您可以在所有非终端A potentially-starts-with BA上构建关系B。 (事实上​​,在所有语法符号上构建这种关系更为正常,因为它也用于构造FIRST集,但在这种情况下,我们只需要投影到非终端上。)

完成此操作后,左递归非终端全部为AA potentially-starts-with+ Apotentially-starts-with+,其中potentially-starts-with ∘ potentially-starts-with*为:

{{1}}

您可以使用任何传递闭包算法来计算该关系。


供参考,检测可以为空的非终端。

  1. 删除所有无用的符号。
  2. 将指针附加到每个作品,最初位于第一个位置。
  3. 将所有作品放入工作队列。
  4. 尽可能找到符合下列条件之一的作品:
    • 如果生产的左侧标记为ε-非终端,则丢弃生产。
    • 如果指针右侧的令牌是终端,则丢弃生产。
    • 如果指针右侧没有任何标记(即指针位于末尾),请将生产的左侧标记为ε-非终端并丢弃生产。
    • 如果指针右侧的令牌是一个已被标记为ε-非终端的非终端,则将指针向前推进一个令牌并将生产返回到工作队列。
  5. 一旦无法再从工作队列中选择生产,就会识别出所有ε-非终端。

    只是为了好玩,可以使用上述算法的微小修改来执行步骤1.我将把它作为练习(它也是龙书中的练习)。同样留下练习是确保上述算法在线性时间内执行的方法。