【问题标题】:Why do right recursive parsers not loop infinitely?为什么右递归解析器不会无限循环?
【发布时间】:2016-05-27 07:27:27
【问题描述】:

左递归将使解析器进入无限循环。那么为什么右递归不会发生同样的情况呢?

【问题讨论】:

  • 您能否提供您的代码以便我们为您提供帮助?谢谢。
  • @EdvinTenovim 这听起来不像有任何代码要显示。据推测,Shraddha 目前正在通过编译器构造教科书/课程/教程/其他工作,并且在阅读了语法中的左递归导致递归下降解析器中的无限循环之后,想知道为什么这只适用于左递归。这不是一个荒谬的问题。
  • @EdvinTenovim 这是一个关于解析器类型的理论问题。它与实际代码无关。
  • @EJP 好吧,我的错。大概吧。
  • "Packrat Parsers Can Support Left Recursion" “本文提出了对 Packrat 解析器实现使用的记忆机制的修改,使它们能够直接支持直接和间接左递归(即,无需首先转换规则)。”

标签: parsing compiler-construction left-recursion


【解决方案1】:

在递归下降解析器中,像A -> B C | D 这样的语法规则是通过尝试在当前位置解析 B 来实现的,然后,如果成功,则尝试在 B 结束的位置解析 C。如果其中一个失败,我们会尝试在当前位置解析 D¹。

如果 C 等于 A(右递归),那没关系。这只是意味着如果 B 成功,我们尝试在 B 之后的位置解析 A,这意味着我们首先尝试在那里解析 B,然后在新位置再次尝试 A 或尝试 D。这将一直持续到最终 B 失败我们试试 D。

但是,如果 B 等于 A(左递归),那将是一个很大的问题。因为现在要解析A,我们首先尝试在当前位置解析A,它尝试在当前位置解析A……无限。我们从不提升我们的位置,从不尝试任何东西,除了 A(它只是不断地尝试自己),所以我们永远不会到达我们可能终止的地步。

¹ 假设完全回溯。否则,如果 B 和/或 C 消耗了任何令牌(或比我们预知更多的令牌),A 可能会在不尝试 D 的情况下失败,但这些对于本次讨论都无关紧要。

【讨论】:

    【解决方案2】:

    如果您对缺乏对称性感到困惑,另一种看法是左递归会导致递归下降解析器出现问题,因为我们通常从左到右解析语言。这意味着如果解析器是左递归的,那么递归符号是第一个尝试的,它在与父规则相同的状态下尝试,保证递归将无限继续。

    如果您认真考虑的话,我们从左到右解析语言并没有根本原因;这只是一个约定! (有一些原因,例如以这种方式从磁盘读取文件更快;但这是约定的结果。)如果您编写了一个从右到左的递归下降解析器,该解析器从文件末尾开始并使用首先从末尾开始的字符,向后工作到文件的开头,然后右递归会导致问题,并且您需要将右递归语法重写为左递归,然后才能解析它们。那是因为如果您首先处理正确的符号,那么它就会被解析为与父级相同的状态。

    所以你来了;对称性得以保留。就像从左到右的递归下降解析器与左递归一样,从右到左的递归下降解析器与右递归也很相似。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-12
      • 2010-10-23
      • 2014-03-18
      • 2016-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多