編譯原理 三 消除文法的左遞迴

2021-07-08 10:15:49 字數 2646 閱讀 5475

對於任意上下文無關的文法消除左遞迴形如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 借助如下公式,消除直接左遞...