📜  删除语法中的直接和间接左递归

📅  最后修改于: 2021-09-27 15:15:08             🧑  作者: Mango

先决条件 – 上下文无关语法、歧义和解析器的分类
左递归:
形式的语法,

S --> S / a / b 

它被称为左递归,其中 S 是任何非终结符,a 和 b 是任何终结符集。

左递归问题:
如果任何语法中存在左递归,那么在编译的语法分析部分的解析过程中,语法有可能会创建无限循环。这是因为每次产生语法 S 都会产生另一个 S 而不检查任何条件。

以示例删除左递归的算法:
假设我们有一个包含左递归的文法:

S-->S a / S b / c / d 
  1. 检查给定的语法是否包含左递归,如果存在则分离产生式并开始处理它。
    在我们的例子中,

    S-->S a/ S b /c / d   
  2. 引入一个新的非终结符并将其写在每个终结符的最后。我们产生一个新的非终结符 S’ 并将新产生写为,
    S-->cS' / dS' 
  3. 在 LHS 中写入新产生的非终结符,在 RHS 中它可以产生或可以产生新的产生,其中跟在前一个 LHS 之后的终结符或非终结符最终将被新的非终结符替换。
    S'-->? / aS' / bS' 

    所以转换后新的等效产量是

    S-->cS' / dS'
    S'-->? / aS' / bS'   

间接左递归:
如果从文法的任何符号开始,可以导出以该符号为头的字符串,则称该文法具有间接左递归。

例如,

A --> Br 
B --> Cd
C --> At 

其中 A、B、C 是非终结符,r、d、t 是终结符。
在这里,从 A 开始,我们可以通过将 C 替换为 B 和 B 替换为 A 再次推导出 A。

借助示例删除间接递归的算法:

A1 --> A2  A3
A2 --> A3  A1 / b
A3 --> A1  A1 / a 

其中 A1、A2、A3 为非终端,a、b 为终端。

  1. 识别可能导致间接左递归的产生式。在我们的例子中,
    A3--> A1 A1 / a 
  2. 在终端所在的位置替代其生产在任何其他生产替代 A1-> A2 A3 的生产 A3 中。 A3 –> A2 A3 A1。
    现在在这个生产中替换 A2–> A3 A1 / b 然后将其替换为,
    A3 --> A3  A1 A3 A1 / b A3 A1 
  3. 现在新产生式转化为直接左递归的形式,用直接左递归的方法解决这个问题。
    消除上面的直接左递归,
    A3 --> a | b A3 A1 | aA' | b A3 A1A' 
    A' --> A1 A3 A1 | A1 A3 A1A' 

    产生的语法是:

    A1 -->  A2 A3
    A2 --> A3 A1 | b
    A3 --> a | b A3 A1 | aA' | b A3 A1A' 
    A' --> A1 A3 A1 | A1 A3 A1A'