實現:
輸入:一組任意的文法規則和任意符號串
輸出:相應的chomsky(文法型別和推導)
要求:1.文法的輸入應簡便(不代表產生式少)
2.指明是那一類chomsky文法,給出相應的四元祖形式,不考慮0型文法
實驗原理
1,文法定義:
文法g定義為四元組(vn,vt,p,s)。
其中vn為非終結符集,vt為終結符集,p為規則(a->b)的集合,a∈(vn∪vt)且至少包含乙個非終結符,b∈(vn∪vt),vn,vt,p是非空有窮集。s為起始符,至少在一條規則中左部出現。
vn和vt不含公共元素。
2,chomsky文法型別判斷:
如果乙個文法是0型文法:
若每個產生式均為|右|>=|左|,空產生式除外,則該文法為1型文法。
若文法是1型文法,並且,每個產生式的左部只有乙個非終結符,則該文法是2型文法。
若文法是2型文法,且所有產生式均為左線性或者均為右線性,則該文法為3型文法。空產生式除外。
其中,左線性為形如s->aa ,s->a
右線性形如 s->aa,s->a
實驗思路
程式中用結構體gram陣列儲存輸入的產生式,並有兩個int引數ll和rl,記錄每個產生式左邊和右邊的字串的長度,以「->」為分界線,用5個flag符號分別標記文法。由於四種文法的關係是下一級包含上一級的關係,所以從第一級開始往下推導。如果標誌符號flag在下一級沒有變為0,則輸出推導結果及相關資料。一級文法只需要比較所有產生式的ll與rl,只要滿足左右的ll<=rl,則繼續向第二級推導。根據第二級文法的定義,其條件可以理解為在一級文法的基礎上每個產生式的ll=1且左邊字串為終結符即可。當滿足此條件後可以向第**文法推導。對於第**文法的確認,程式分為兩種情況判斷。(1)當rl=1時,則只有右邊字串(即gram[i].str[3])為非終結符時成立(2)當rl=2時,只有形如「aa」或者」aa」的字串才能成立。對於其餘的情況,皆視為第二種文法。在第二種情況的基礎下,又可以分為左線性和右線性。這個只需要對非終結符的位置進行判斷即可。
輸入時,要求大寫字母表示非終結符,小寫字母表示終結符,每條產生式換行,預設第一條產生式的第乙個字母為起始符,輸入』$』結束輸入。
判斷完畢之後,需要對終結符集和非終結符集進行輸出,由於在輸入時已經將終結符和非終結符存入相關陣列,此時需要進行輸出查重操作,避免重複輸出。本程式採用雙重迴圈輸出。
#include
#include
using
namespace
std;
struct gram;
int main()
for(j=0;jif(gram[i].str[j]=='-')
break;
}gram[i].ll=j;
gram[i].rl=len-j-2;
}int num=i;
cout
/1型文法判斷
for(i=0;iif(gram[i].ll<=gram[i].rl)
flag=0;
else
}if(flag==0)}}
if(flag1==0)
else
} if(flag2==0)
cout
<
else
} if(flagr==0)
cout
<
else
} if(flagl==0)
cout
<
cout
<
<
<0];
for(i=1;ifor(j=0;jif(vn[j]==vn[i])
else flag=1;
}if(flag)
cout
<
<
<0];
for(i=1;ifor(j=0;jif(vt[j]==vt[i])
else flag=1;
}if(flag)
cout
<
<
<
<0].str[0]
0;}
下面給出一些示例:
希望有高見的大牛多提提意見哈!
文法的判斷,遞迴下降分析程式
1.文法g s 1 s ab 2 a da 3 b cc 4 c aadc 5 d b 驗證文法g s 是不是ll 1 文法?select a da first da select a follow a select c aadc first aadc select c follow c selec...
如何判斷文法是否是LL 1 文法
判斷該文法是不是ll 1 文法,說明理由 s abc a a b b first集合求法就是 能由非終結符號推出的所有的開頭符號或可能的 但要求這個開頭符號是終結符號。如此題a可以推導出a和 所以first a a,同理first b s可以推導出abc,還可以推導出bc,還可以推導出c,所以fir...
如何判斷文法是否為LL 1 文法
判斷該文法是不是ll 1 文法,說明理由 s abc a a b b first集合求法就是 能由非終結符號推出的所有的開頭符號或可能的 但要求這個開頭符號是終結符號。如此題a可以推導出a和 所以first a a,同理first b s可以推導出abc,還可以推導出bc,還可以推導出c,所以fir...