對於任意上下文無關的文法消除左遞迴形如p
→pα|
β 可以通過直接消除轉化為: p→
βp′p
′→αp
′|ϵ
有時候雖然形式上產生式沒有遞迴,但是因為形成了環,所以導致進行閉包運算後出現左遞迴,如下:s→
qc|c
q→rb
|br→
sa|a
雖不具有左遞迴,但s、q、r都是左遞迴的,因為經過若干次推導有
消除左遞迴演算法:
for (i=1;i
<=n;i++)
for (j=1;j
<=i-1;j++)
利用此演算法可以將上述文法進行改寫,來消除左遞迴。
首先,令非終結符的排序為r、q、s。對於r,不存在直接左遞迴。把r代入到q中的相關規則中,則q的規則變為q→sab/ ab/ b。
代換後的q不含有直接左遞迴,將其代入s,s的規則變為s→sabc/ abc/ bc/ c。
此時,s存在直接左遞迴。在消除了s的直接左遞迴後,得到整個文法為: s→
abcs
′|bc
s′|c
s′s′
→abc
s′|ε
q→sa
b|ab
|br→
sa|a
可以看到從文法開始符號s出發,永遠無法達到q和r,所以關於q和r的規則是多餘的,將其刪除並化簡,最後得到文法g[s]為: s→
abcs
′|bc
s′|c
s′s′
→abc
s′|ε
當然如果對文法非終結符排序的不同,最後得到的文法在形式上可能不一樣,但它們都是等價的。例如,如果對上述非終結符排序選為s、q、r,那麼最後得到的文法g[r]為: r→
bcar
′|ca
r′|a
r′r′
→bca
r′|ε
容易證明上述兩個文法是等價的。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define max 507
using
namespace
std;
class wf
void print ( )
void insert ( const
string& temp )
};map
vn_dic;
vector
vn_set;
string start;
bool used[max];
//消除間接左遞迴
void remove1 ( )
}for ( int i = 0 ; i < cont.size() ; i++ )
right1.insert ( cont[i] );
}#define debug
#ifdef debug
for ( int i = 0 ; i < vn_set.size() ; i++ )
vn_set[i].print();
#endif
}//消除直接左遞迴
void remove2 ( )
int x = vn_dic[tt]-1;
if ( flag ) continue;
vector
cont;
set& ss = vn_set[x].right;
ss.insert ( "~" );
while (!temp.empty())
temp.erase(temp.begin());
}puts ("");
for ( int i = 0 ; i < cont.size() ; i++ )
}#define debug
#ifdef debug
for ( int i = 0 ; i < vn_set.size() ; i++ )
vn_set[i].print();
#endif
}void dfs ( int x )
}//化簡
void simplify ( )
void print ()
int main ( )
string temp = buf;
if ( !vn_dic[temp] )
int x = vn_dic[temp]-1;
temp = buf+i+3;
//cout <
vn_set[x].insert(temp);
}remove1();
remove2();
simplify();
print();
//puts ("請輸入文法g[s]的產生式數量");
}
}
測試樣例:
測試結果:
編譯原理 消除左遞迴
乙個文法含有下列形式的產生式之一時 1 a a a vn,v 2 a b b a a b vn,v 則稱該文法是左遞迴的。乙個文法g 若存在 p經過一次或多次推導得到 pa 即能推導出以 p開頭的式子 則稱 g是左遞迴的。然而,乙個文法是左遞迴時,不能採取自頂向下分析法。左遞迴分為直接左遞迴和間接左...
編譯原理 消除左遞迴
乙個文法含有下列形式的產生式之一時 1 a a a vn,v 2 a b b a a b vn,v 則稱該文法是左遞迴的。然而,乙個文法是左遞迴時,不能採取自頂向下分析法。消除左遞迴方法有 a 把直接左遞迴改寫為右遞迴 設有文法產生式 a a 其中 非空,不以a打頭。可寫為 a a a a 一般情況...
消除文法左遞迴的演算法
1 typedef struct pp 6 typedef struct gg 文法g由多條產生式組成,出現在產生式左部的非終結符,會指向乙個p文法陣列,每乙個陣列元素對應乙個程式的右部,這樣的結構顯然是對文法進行了壓縮的 1 掃瞄文法,先將間接做遞迴轉換成直接左遞迴 2 借助如下公式,消除直接左遞...