编译原理 消除左递归,直接左递归、间接左递归

消除左递归

左递归的定义

如果存在非终结符PP经过一步或一步以上推导出PαP\alpha,即
P+PαP\stackrel{+}{\Longrightarrow}P\alpha则称PP含有左递归。

  • 含有左递归的文法将使自上而下的分析过程1陷入无限循环。

左递归的消除

消除直接左递归

假定关于非终结符PP的规则为PPαβP\to P\alpha|\beta其中,β\beta不以PP开头。即,PP所能确定的是以β\beta开头、以若干个α\alpha结尾的语言。
那么,可以把PP的规则改写为下面的非直接左递归形式:
PβPP\to \beta P' PαPεP'\to \alpha P'|\varepsilon

  • 举个例子:文法

EE+TTE\to E+T|T TTFFT\to T*F|F F(E)iF\to (E)|i 经过消去直接左递归后变成 ETEE\to TE' E+TEεE'\to +TE'|\varepsilon TFTT\to FT' TFTεT'\to *FT'|\varepsilon F(E)i F\to (E)|i

消除间接左递归

先将间接左递归变为直接左递归,再按消除直接左递归的方法进行。

  • 举个例子,文法G[A]

ABcdA\to Bc|d BaAAbB\to aA|Ab 转换为直接左递归(代入) AaAcAbcdA\to aAc|Abc|d 消除直接左递归 AaAcAdAA\to aAcA'|dA' AbcAεA'\to bcA'|\varepsilon 简化为 A(aAcd)AA\to (aAc|d)A' AbcAεA'\to bcA'|\varepsilon

消除全部左递归

前提:该文法不含回路2

  1. 把文法中所有非终结符按任意一种顺序排列成P1,P2,P3,PnP_{1},P_{2},P_{3}\cdots,P_{n}

  2. 对每个非终结符号,用排在它前面的其他非终结符号的产生式表示出来(代入),并消除产生式中的直接左递归。

  3. 化简上一步所得文法,即去掉重复、多余的产生式。

  • 举个例子,文法G[S]

SQccS\to Qc|c QRbbQ\to Rb|b RSaaR\to Sa|a 1. 对非终结符排序:R,Q,S
2. 逐个消除直接左递归:R:RSaaR:R\to Sa|a 无直接左递归,将RR代入QQQSababbQ\to Sab|ab|b 无直接左递归,将RRQQ代入SSSSabcabcbccS\to Sabc|abc|bc|c 消除SS的直接左递归:S(abcbcc)SS\to(abc|bc|c)S' SabcSεS'\to abcS'|\varepsilon 现文法为:S(abcbcc)SS\to (abc|bc|c)S' SabcSεS'\to abcS'|\varepsilon QSababbQ\to Sab|ab|b RSaaR\to Sa|a 3. 去掉多余产生式 S(abcbcc)SS\to (abc|bc|c)S' SabcSεS'\to abcS'|\varepsilon

注意:对非终结符的排序是任意的(但要保证其识别的符号不变),不同的排序最后所得文法的形式可能不同,但他们是等价的。


  1. 自上而下就是从文法的开始符号出发,向下推导,推出句子。 ↩︎

  2. 形如PPP\to P的推导,也不含有以ε\varepsilon为右部的产生式。 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章