Parsing 通过检查句子形式的长度并丢弃无限多义性语法,有可能处理LL中的左递归吗?

Parsing 通过检查句子形式的长度并丢弃无限多义性语法,有可能处理LL中的左递归吗?,parsing,context-free-grammar,formal-languages,ll,Parsing,Context Free Grammar,Formal Languages,Ll,我知道LL解析器(无前瞻性)无法处理左递归规则,因为它会反复预测左递归非终结符,并且永远无法匹配 但是,如果我们采用两种策略的组合会怎么样: 我们构建了一个表,在该表中,我们为每个非终端分配其子语言生成的字符串的最小长度 因此,假设我们有一个左递归规则,如下所示: A->As|A 其中,s是由终端和非终端组成的字符串 如果s中的任何一个生成最小长度大于0的字符串,那么即使在预测中面对非终端“A”,我们也会反复预测“As”,但预测字符串的最小长度只会增加,最终超过输入字符串的长度,因此被丢弃 当然

我知道LL解析器(无前瞻性)无法处理左递归规则,因为它会反复预测左递归非终结符,并且永远无法匹配

但是,如果我们采用两种策略的组合会怎么样:

  • 我们构建了一个表,在该表中,我们为每个非终端分配其子语言生成的字符串的最小长度
  • 因此,假设我们有一个左递归规则,如下所示:

    A->As|A

    其中,s是由终端和非终端组成的字符串

    如果s中的任何一个生成最小长度大于0的字符串,那么即使在预测中面对非终端“A”,我们也会反复预测“As”,但预测字符串的最小长度只会增加,最终超过输入字符串的长度,因此被丢弃

    当然,这对无限模糊的语法(比如有循环的语法)不起作用,导致我们采用第二种策略:

  • 每次我们做一个预测,或者整个句子形式的最小长度增加,或者保持不变,在它保持不变的情况下,我们保留一堆最左边的预测非终结符,并且每当我们预测同一个非终结符两次,我们丢弃预测
  • 这实际上丢弃了无限多的派生,尽管它保留了解析器所接受的语言


    作为一个具体示例,假设以下语法:

    S->Sa | a

    非终端S生成的字符串的最小长度为1

    现在假设我们正在解析以下输入字符串:aa

  • 我们首先预测开始符号“S”
  • 使用广度优先搜索,我们有两个预测:“Sa”和“a”
  • “a”预测被丢弃,因为即使它与输入字符串中的第一个“a”匹配,它仍达到下线,而输入字符串中仍有一个“a”
  • “Sa”预测不能匹配任何东西,因为我们在句子形式中有“S”作为“匹配标记”,因此我们做出另外两个预测:“Saa”和“aa”
  • “aa”预测匹配整个输入字符串,因此我们找到了一个解析
  • “Saa”预测的最小长度为3,因此无法与输入字符串匹配,因此被丢弃


  • 这样行吗?我遗漏了什么吗?

    在第3步,您似乎在使用任意的前瞻。当你看到
    a
    时,你必须预测
    Sa
    a
    ,此时你不知道输入的结尾是否接近。不管它值多少,我的想法与你的想法类似,事实上我有一个概念证明,我使用基于左递归语法的自上而下的递归下降解析器解析任意插入的表达式。我的解析器系统(甚至在此之前)在解析开始之前标记整个输入流,因此解析器知道输入中词素的总数,并使用这一事实限制推测递归的数量。不用说,我的解析器是一个回溯式解析器,它允许它从太多的递归调用中恢复。现在,我不知道这对实际输入的效果如何。,我一直想把它扩展到可能的终止终端,这样每个自递归生产都会提前扫描必须存在的令牌列表,以便正确终止它,并将其设置为生产可以使用多少(或很少)令牌的限制,但是我还没有时间进一步探讨这个想法。@500 InternalServerError:为了避免使用LALR解析器,似乎需要做大量的工作。LALR解析器可以在线性时间内完美地处理左递归,而无需任何额外的前瞻。或者,您知道,如果1982年的算法对您来说过于新颖,您可以使用表达式的运算符优先解析器来扩充LL解析器,从而生成1970年最先进的左角解析器。:-)这大概是我写的第一个解析器(APL)。@rici::)-我知道存在自底向上的解析技术,它们不会受到这里讨论的问题的影响-我相信OP也知道它们。然而,就我个人而言,我发现自顶向下的解析器更容易理解和推理,尤其是在语法/解析器开发阶段,因此我仍然认为这是一个值得研究的领域,即使世界上很多人已经转向LALR或类似的技术。