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

📅  最后修改于: 2021-06-28 07:04: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. 将其生产替换为A3生产中其他任何生产替代产品A1-> A2 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'