【问题标题】:Removing indirect left recursion from this grammar从此语法中删除间接左递归
【发布时间】:2020-09-01 18:03:08
【问题描述】:

我试图弄清楚如何从我的 Ruby 解析器 (https://github.com/kenaniah/ruby-parser/blob/master/ruby-parser/src/parsers/expression/logical.rs) 的 Rust 端口中的逻辑关键字表达式中删除间接左递归。语法如下:

E --> N | A | O | t
N --> n E
A --> E a E
O --> E o E
E = expression
A = keyword_and_expression
O = keyword_or_expression
N = keyword_not_expression

我将如何进行转换以删除 AO 中的递归?

【问题讨论】:

  • 正如源代码所示,我已经从那些中删除了左递归(那些是直接左递归的情况,我知道如何处理)。这是 间接 递归让我感到困惑,因为我不确定如何将其转换为等效的语法。

标签: grammar left-recursion


【解决方案1】:

根据这个factorization tool,生成的语法将是:

E  -> N
    | A
    | O
    | t
N  -> n E
A  -> n E a E A'
    | O a E A'
    | t a E A'
O  -> n E o E O'
    | n E a E A' o E O'
    | t a E A' o E O'
    | t o E O'
A' -> a E A'
    | ϵ
O' -> a E A' o E O'
    | o E O'
    | ϵ

由于E 的多次产生,AO 的因式分解最终变得相当复杂。

【讨论】:

    【解决方案2】:

    我认为这里的问题不是间接递归,而是歧义。

    如果只是间接递归,你可以简单地替换NAO的右侧,消除间接递归:

    E → n E
      | E a E
      | E o E
      | t
    

    为了摆脱直接左递归,你可以left-factor:

    E → n E
      | E A'
      | t
    A'→ a E
      | o E
    

    然后移除剩余的左递归:

    E → n E E'
      | t E'
    E'→ ε
      | A' E'
    A'→ a E
      | o E
    

    没有直接或间接的左递归,并且每条规则都以唯一的终端开始。但是,它不是 LL(1),因为存在先/后冲突。

    这并不奇怪,因为原来的语法是高度歧义的,左递归消除并不能消除歧义。原始语法只有在带有operator precedence table 时才真正有意义。

    该表表明ANDOR 是具有相同优先级的左结合运算符(一个有点不寻常的决定),而NOT 是具有更高优先级的一元运算符。反过来,这意味着 BNF 应该写成这样:

    N → n N
      | t
    E → A
      | O
      | N
    A → E a N
    O → E o N
    N → n N
      | t
    

    与 OP 中语法的唯一区别是消除了歧义,如优先表所示。

    同样,第一步是替换非终结符 AO 以使左递归直接:

    E → E a N
      | E o N
      | N
    N → n N
      | t
    

    这与算术表达式的语法本质上是相同的语法(忽略乘法,因为只有一个优先级),并且可以直接消除左递归:

    E  → N E'
    E' → a E
       | o E
       | ε
    N  → n N
       | t
    

    【讨论】:

    • 我对语法很陌生,如果我可能会监督某些事情,请原谅,但我认为您的第三版语法(以及以下所有内容)不正确。 E → n E E' | t 只能产生一个t 或以n 开头的东西。而前两个语法可能会产生类似t o t.
    • @Filou:没错,左递归消除有错误。谢谢。但这并不影响其余的答案,因为没有什么是基于第三种语法的,这是一条死胡同。
    • @Filou:现在我实际上修正了语法。显然我的第一个编辑消失在 bitbucket 中了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    相关资源
    最近更新 更多