2023年語法分析器實(shí)驗(yàn)報(bào)告_第1頁
2023年語法分析器實(shí)驗(yàn)報(bào)告_第2頁
2023年語法分析器實(shí)驗(yàn)報(bào)告_第3頁
2023年語法分析器實(shí)驗(yàn)報(bào)告_第4頁
2023年語法分析器實(shí)驗(yàn)報(bào)告_第5頁
已閱讀5頁,還剩34頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

語法分析器的設(shè)計(jì)實(shí)驗(yàn)報(bào)告一、實(shí)驗(yàn)內(nèi)容語法分析程序用LL(1)語法分析方法。一方面輸入定義好的文法書寫文獻(xiàn)(所用的文法可以用LL(1)分析),先求出所輸入的文法的每個(gè)非終結(jié)符是否能推出空,再分別計(jì)算非終結(jié)符號(hào)的FIRST集合,每個(gè)非終結(jié)符號(hào)的FOLLOW集合,以及每個(gè)規(guī)則的SELECT集合,并判斷任意一個(gè)非終結(jié)符號(hào)的任意兩個(gè)規(guī)則的SELECT集的交集是不是都為空,假如是,則輸入文法符合LL(1)文法,可以進(jìn)行分析。對于文法:G[E]:E->E+T|TT->T*F|FF->i|(E)分析句子i+i*i是否符合文法。二、基本思想1、語法分析器實(shí)現(xiàn)語法分析是編譯過程的核心部分,它的重要任務(wù)是按照程序的語法規(guī)則,從由詞法分析輸出的源程序符號(hào)串中辨認(rèn)出各類語法成分,同時(shí)進(jìn)行詞法檢查,為語義分析和代碼生成作準(zhǔn)備。這里采用自頂向下的LL(1)分析方法。語法分析程序的流程圖如圖5-4所示。開始開始讀入文法有效?判斷句型報(bào)錯(cuò)結(jié)束語法分析程序流程圖是LL(1)文法?該程序可分為如下幾步:(1)讀入文法(2)判斷正誤(3)若無誤,判斷是否為LL(1)文法(4)若是,構(gòu)造分析表;(5)由句型判別算法判斷輸入符號(hào)串是為該文法的句型。三、核心思想該分析程序有15部分組成:(1)一方面定義各種需要用到的常量和變量;(2)判斷一個(gè)字符是否在指定字符串中;(3)讀入一個(gè)文法;(4)將單個(gè)符號(hào)或符號(hào)串并入另一符號(hào)串;(5)求所有能直接推出&的符號(hào);(6)求某一符號(hào)能否推出‘&’;(7)判斷讀入的文法是否對的;(8)求單個(gè)符號(hào)的FIRST;(9)求各產(chǎn)生式右部的FIRST;(10)求各產(chǎn)生式左部的FOLLOW;(11)判斷讀入文法是否為一個(gè)LL(1)文法;(12)構(gòu)造分析表M;(13)句型判別算法;(14)一個(gè)用戶調(diào)用函數(shù);(15)主函數(shù);下面是其中幾部分程序段的算法思想:1、求能推出空的非終結(jié)符集Ⅰ、實(shí)例中求直接推出空的empty集的算法描述如下:voidemp(charc){參數(shù)c為空符號(hào) chartemp[10];定義臨時(shí)數(shù)組?inti;?for(i=0;i<=count-1;i++)從文法的第一個(gè)產(chǎn)生式開始查找?{ ?if產(chǎn)生式右部第一個(gè)符號(hào)是空符號(hào)并且右部長度為1,then將該條產(chǎn)生式左部符號(hào)保存在臨時(shí)數(shù)組temp中將臨時(shí)數(shù)組中的元素合并到記錄可推出&符號(hào)的數(shù)組empty中。?}Ⅱ、求某一符號(hào)能否推出'&'int_emp(charc){//若能推出&,返回1;否則,返回0 inti,j,k,result=1,mark=0; chartemp[20];?temp[0]=c; temp[1]='\0';?存放到一個(gè)臨時(shí)數(shù)組empt里,標(biāo)記此字符已查找其是否可推出空字假如c在可直接推出空字的empty[]中,返回1 for(i=0;;i++) { ?if(i==count)return(0);??找一個(gè)左部為c的產(chǎn)生式?j=strlen(right[i]);//j為c所在產(chǎn)生式右部的長度? ?if右部長度為1且右部第一個(gè)字符在empty[]中.then返回1(A->B,B可推出空)???if右部長度為1但第一個(gè)字符為終結(jié)符,then返回0(A->a,a為終結(jié)符)???else ??{??? for(k=0;k<=j-1;k++)? ??{ ???查找臨時(shí)數(shù)組empt[].并標(biāo)記mark-=1(A->AB)?? if找到的字符與當(dāng)前字符相同(A->AB)?? ? 結(jié)束本次循環(huán) ??else(mark等于0)查找右部符號(hào)是否可推出空字,把返回值賦給result ?? 把當(dāng)前符號(hào)加入到臨時(shí)數(shù)組empt[]里.} ? if當(dāng)前字符不能推出空字且還沒搜索完所有的產(chǎn)生式then跳出本次循環(huán)繼續(xù)搜索下一條產(chǎn)生式? elseif//當(dāng)前字符可推出空字,返回1}}}??2、計(jì)算每個(gè)符號(hào)的first集:實(shí)例中求單個(gè)符號(hào)的FIRST集的算法描述如下:voidfirst2(inti){ 參數(shù)i為符號(hào)在所有輸入符號(hào)中的序號(hào)?c等于指示器i所指向的符號(hào)?在保存終結(jié)符元素的termin[]數(shù)組查找cifc為終結(jié)符(c∈VT),thenFIRST(c)={c}在保存終結(jié)符元素的non_ter[]數(shù)組查找cifc是非終結(jié)符(c∈VN)在所有產(chǎn)生式中查找c所在的產(chǎn)生式if產(chǎn)生式右部第一個(gè)字符為終結(jié)符或空(即c→a(a∈VT)或c→&)then把a(bǔ)或&加進(jìn)FIRST(c)if產(chǎn)生式右部第一個(gè)字符為非終結(jié)符thenif產(chǎn)生式右部的第一個(gè)符號(hào)等于當(dāng)前字符then跳到下一條產(chǎn)生式進(jìn)行查找求當(dāng)前非終結(jié)符在所有字符集中的位置if當(dāng)前非終結(jié)符還沒求其FIRST集then查找它的FIRST集并標(biāo)記此符號(hào)已求其FIRST集?求得結(jié)果并入到c的FIRST集.if當(dāng)前產(chǎn)生式右部符號(hào)可推出空字且當(dāng)前字符不是右部的最后一個(gè)字符then獲取右部符號(hào)下一個(gè)字符在所有字符集中的位置if此字符的FIRST集尚未查找then找其FIRST集,并標(biāo)其查找狀態(tài)為1把求得的FIRST集并入到c的FIRST集.if當(dāng)前右部符號(hào)串可推出空且是右部符號(hào)串的最后一個(gè)字符(即產(chǎn)生式為c→Y1Y2…Yk,若對一切1<=i<=k,均有&∈FIRST(Yi),則將&∈符號(hào)加進(jìn)FIRST(c))then把空字加入到當(dāng)前字符c的FIRST集. else不能推出空字則結(jié)束循環(huán)標(biāo)記當(dāng)前字符c已查找其FIRST集.}3.計(jì)算FOLLOW集FOLLOW集的構(gòu)造可用如下方法來求:對于文法中的符號(hào)XVN,其FOLLOW(A)集合可反復(fù)應(yīng)用下列規(guī)則計(jì)算,直到FOLLOW(A)集合不再增大為止。(1)對于文法開始符號(hào)S,由于SS,故#FOLLOW(S);(2)若A→B,其中BVN,(VTVN)*、(VTVN)+,則FIRST()-{e}FOLLOW(B);(3)若A→B或A→B(e),則FOLLOW(A)FOLLOW(B)。 FOLLOW集的算法描述如下: voidFOLLOW(inti)??X為待求的非終結(jié)符把當(dāng)前字符放到一臨時(shí)數(shù)組foll[]中,標(biāo)記求已求其FOLLOW集.避免循環(huán)遞歸ifX為開始符號(hào)then#∈FOLLOW(X) 對所有的產(chǎn)生式找一個(gè)右部具有當(dāng)前字符X的產(chǎn)生式注:比如求FOLLOW(B)則找A→αX或A→X(ε)的產(chǎn)生式ifX在產(chǎn)生式右部的最后(形如產(chǎn)生式A→X)then查找非終結(jié)符A是否已經(jīng)求過其FOLLOW集.避免循環(huán)遞歸if非終結(jié)符A已求過其FOLLOW集thenFOLLOW(A)∈FOLLOW(X)繼續(xù)查下一條產(chǎn)生式是否具有Xelse求A之FOLLOW集,并標(biāo)記為A已求其FOLLOW集elseifX不在產(chǎn)生式右部的最后(形如A→B)thenif右部X后面的符號(hào)串能推出空字then查找是否已經(jīng)求過其FOLLOW集.避免循環(huán)遞歸if已求過的FOLLOW集thenFOLLOW(A)∈FOLLOW(B)結(jié)束本次循環(huán)elseif不能推出空字then求FIRST()把FIRST()中所有非空元素加入到FOLLOW(B)中標(biāo)記當(dāng)前規(guī)定的非終結(jié)符X的FOLLOW集已求過4.計(jì)算SELECT集SELECT集的構(gòu)造算法如下:對所有的規(guī)則產(chǎn)生式A→x:(1)若x不能推出空字e,則SELECT(A→x)=FIRST(x);(2)若x可推出空字e,則SELECT(A→x)=FIRST(x)–{}FOLLOW(A)。算法描述如下:?for(i=0;i<=產(chǎn)生式總數(shù)-1;i++)先把當(dāng)前產(chǎn)生式右部的FIRST集(一切非空元素,不涉及ε)放入到當(dāng)前產(chǎn)生式的SELECT(i); if產(chǎn)生式右部符號(hào)串可推出空字ethen把i指向的當(dāng)前產(chǎn)生式左部的非終結(jié)符號(hào)的FOLLOW集并入到SELECT(i)中5.判斷是否LL(1)文法要判斷是否為LL(1)文法,需要輸入的文法G有如下規(guī)定:具有相同左部的規(guī)則的SELECT集兩兩不相交,即:SELECT(A→)∩SELECT(A→)=?假如輸入的文法都符合以上的規(guī)定,則該文法可以用LL(1)方法分析。算法描述如下:?把第一條產(chǎn)生式的SELECT(0)集放到一個(gè)臨時(shí)數(shù)組temp[]中?for(i=1;i<=產(chǎn)生式總數(shù)-1;i++)求temp的長度length??ifi指向的當(dāng)前產(chǎn)生式的左部等于上一條產(chǎn)生式的左部then? 把SELECT(i)并入到temp數(shù)組中???Iftemp的長度小于length加上SELECT(i)的長度 返回0 else把temp清空把SELECT(i)存放到temp中結(jié)果返回1;四、算法#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/intcount=0;//產(chǎn)生式的個(gè)數(shù)intnumber;//所有終結(jié)符和非終結(jié)符的總數(shù)charstart;//開始符號(hào)chartermin[50];//終結(jié)符號(hào)charnon_ter[50];//非終結(jié)符號(hào)charv[50];//所有符號(hào)charleft[50];//左部charright[50][50];//右部charfirst[50][50],follow[50][50];//各產(chǎn)生式右部的FIRST和左部的FOLLOW集合charfirst1[50][50];//所有單個(gè)符號(hào)的FIRST集合charselect[50][50];//各個(gè)產(chǎn)生式的SELECT集合charfirstflag[50],followflag[50];//記錄各符號(hào)的FIRST和FOLLOW是否已求過charempty[20];//記錄可推出&的符號(hào)charnonempty[20];?//記錄不可推出&的符號(hào)charempt[20];//求_emp()時(shí)使用charTEMP[50];//求FOLLOW時(shí)存放某一符號(hào)串的FIRST集合intvalidity=1;//表達(dá)輸入文法是否有效intll=1;//表達(dá)輸入文法是否為LL(1)文法intM[20][20];//分析表charchoose;//用戶輸入時(shí)使用charfoll[20];//求FOLLOW集合時(shí)使用/*******************************************判斷一個(gè)字符c是否在指定字符串p中********************************************/intin(charc,char*p){?inti; if(strlen(p)==0) return(0); for(i=0;;i++)?{ ?if(p[i]==c)? ?return(1);//若在,返回1? if(i==(int)strlen(p))?? return(0);//若不在,返回0 }}/*******************************************將單個(gè)符號(hào)或符號(hào)串并入另一符號(hào)串********************************************/voidmerge(char*d,char*s,inttype){//是目的符號(hào)串,s是源串,type=1,源串中的'&'一并并入目串;//type=2,源串中的'&'不并入目串inti,j; for(i=0;i<=(int)strlen(s)-1;i++)?{? if(type==2&&s[i]=='&');??else? {???for(j=0;;j++)???{?? ?if(j<(int)strlen(d)&&s[i]==d[j]) ???break;//若已存在,則退出,繼續(xù)看下一個(gè)源串字符 ???if(j==(int)strlen(d))//若不存在,則并入 ???{??? ?d[j]=s[i]; ????d[j+1]='\0'; ?? ?break; ? }?? } ?}?}}/*******************************************讀入一個(gè)文法********************************************/chargrammer(char*t,char*n,char*left,charright[50][50]){?charvn[50],vt[50];?chars; charp[50][50];?inti,j; printf("請輸入文法的非終結(jié)符號(hào)串:");scanf("%s",vn); getchar();i=strlen(vn);memcpy(n,vn,i);?n[i]='\0';?printf("請輸入文法的終結(jié)符號(hào)串:");scanf("%s",vt); getchar();i=strlen(vt);memcpy(t,vt,i); t[i]='\0';printf("請輸入文法的開始符號(hào):");?scanf("%c",&s); getchar();?printf("請輸入文法產(chǎn)生式的條數(shù):");scanf("%d",&i); getchar();?count=i;for(j=1;j<=i;j++)?{? printf("請輸入文法的第%d條(共%d條)產(chǎn)生式:",j,i); scanf("%s",p[j-1]);getchar(); }for(j=0;j<=i-1;j++)?{??if(p[j][1]!='-'||p[j][2]!='>')//檢測輸入錯(cuò)誤? {? ?printf("\n輸入錯(cuò)誤!"); ??validity=0; ??return('\0');} } ?return(s);}/*******************************************判斷讀入的文法是否對的********************************************/intjudge(){inti,j; for(i=0;i<=count-1;i++) {? if(in(left[i],non_ter)==0) {//若左部不在非終結(jié)符中,報(bào)錯(cuò)?? printf("\n文法左部犯錯(cuò)!"); validity=0;? ?return(0);??} for(j=0;j<=(int)strlen(right[i])-1;j++)? {? if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='&') ? {//若右部某一符號(hào)不在非終結(jié)符、終結(jié)符中且不為'&',報(bào)錯(cuò)? ? printf("\n文法右部犯錯(cuò)!"); ??validity=0;?? return(0);?? }??}?} return(1);}/*******************************************求所有能直接推出&的符號(hào)********************************************/voidemp(charc){ chartemp[10];?inti; for(i=0;i<=count-1;i++)?{??if(right[i][0]==c&&strlen(right[i])==1)? { ??temp[0]=left[i]; temp[1]='\0';? ?merge(empty,temp,1);//求所有能直接推出'&"的符號(hào),結(jié)果保存到empty[]中 ? emp(left[i]);? }?}}/*******************************************求某一符號(hào)能否推出'&'********************************************/int_emp(charc){//若能推出&,返回1;否則,返回0 inti,j,k,result=1,mark=0;?chartemp[20];?temp[0]=c;?temp[1]='\0';?merge(empt,temp,1);//存放到一個(gè)臨時(shí)數(shù)組empt里,標(biāo)記此字符已查找其是否可推出空字?if(in(c,empty)==1)//假如c在可直接推出空字的empty[]中,返回1? return(1); for(i=0;;i++)?{ ?if(i==count)return(0);??if(left[i]==c)//找一個(gè)左部為c的產(chǎn)生式? {j=strlen(right[i]);//j為c所在產(chǎn)生式右部的長度 ?if(j==1&&in(right[i][0],empty)==1)//右部長度為1且右部第一個(gè)字符在empty[]中.返回1(A->B,B可推出空)? ??return(1);?? elseif(j==1&&in(right[i][0],termin)==1)//右部長度為1但第一個(gè)字符為終結(jié)符,返回0(A->a,a為終結(jié)符)? ? continue; ? else?? {????for(k=0;k<=j-1;k++) ? { ? ??if(in(right[i][k],empt)==1)//查找臨時(shí)數(shù)組empt[].(A->AB)???? mark=1; ? } ? if(mark==1)//找到的字符與當(dāng)前字符相同(A->AB)?? ? continue;//結(jié)束本次循環(huán)? ?else//(mark等于0)????{ ?? ?? ? for(k=0;k<=j-1;k++) ? {? ????result*=_emp(right[i][k]);//遞歸調(diào)用,查找右部符號(hào)是否可推出空字,把返回值賦給result ? ?? temp[0]=right[i][k];???? temp[1]='\0';? ? ?merge(empt,temp,1);//把當(dāng)前符號(hào)加入到臨時(shí)數(shù)組empt[]里,標(biāo)記已查找? ? ?} ? }? } ? if(result==0&&i<count)//假如當(dāng)前字符不能推出空字且還沒搜索完所有的產(chǎn)生式,則跳出本次循環(huán)繼續(xù)搜索下一條產(chǎn)生式 continue; ?elseif(result==1&&i<count)//當(dāng)前字符可推出空字,返回1 ??return(1);? } }}/*******************************************求單個(gè)符號(hào)的FIRST********************************************/voidfirst2(inti){//i為符號(hào)在所有輸入符號(hào)中的序號(hào)charc,temp[20];?intj,k,m;?charch='&'; c=v[i];??emp(ch);//求所有能直接推出空字的符號(hào),結(jié)果保存到empty[]中 if(in(c,termin)==1)//若為終結(jié)符--c∈VT,則FIRST(c)={c}{first1[i][0]=c; ?first1[i][1]='\0'; } elseif(in(c,non_ter)==1)//若為非終結(jié)符?{ for(j=0;j<=count-1;j++)//j為所有產(chǎn)生式中的序列??{if(left[j]==c)//找一個(gè)左部為c的產(chǎn)生式 ??{??? if(in(right[j][0],termin)==1||right[j][0]=='&')? {//若產(chǎn)生式右部第一個(gè)字符為終結(jié)符或空.---產(chǎn)生式X→a(a∈VT)或X→&,則把a(bǔ)或&加進(jìn)FIRST(X)temp[0]=right[j][0];??? ?temp[1]='\0';? ? merge(first1[i],temp,1); ???}//------X→Y1Y2…Yk的產(chǎn)生式,若Y1∈VN,則把FIRST(Y1)中的一切非空符號(hào)加進(jìn)FIRST(X)?? elseif(in(right[j][0],non_ter)==1)//產(chǎn)生式右部第一個(gè)字符為非終結(jié)符 { ? if(right[j][0]==c)//產(chǎn)生式右部的第一個(gè)符號(hào)等于當(dāng)前字符,則跳到下一條產(chǎn)生式進(jìn)行查找 ? ? ?continue;??? for(k=0;;k++)? ?{ ??? if(v[k]==right[j][0])//求右部第一個(gè)字符在所有字符集中的位置k? ??? ?break; ??? }??? if(firstflag[k]=='0') ? {? ? ?first2(k);//求其FIRST集?? ??firstflag[k]='1';//標(biāo)記其為查找狀態(tài)?? ? } ??? merge(first1[i],first1[k],2);//求得結(jié)果并入到X的FIRST集. ?? for(k=0;k<(int)strlen(right[j]);k++)?? ? { ????empt[0]='\0';//存放到一個(gè)臨時(shí)數(shù)組里,標(biāo)記此字符已查找其是否可推出空字? ? if(_emp(right[j][k])==1&&k<(int)strlen(right[j])-1)? ? {//當(dāng)前產(chǎn)生式右部符號(hào)可推出空字,且當(dāng)前字符不是右部的最后一個(gè)字符??? for(m=0;;m++)??? ? ?{ ?? ????if(v[m]==right[j][k+1])//獲取右部符號(hào)下一個(gè)字符在所有字符集中的位置 ?? ? break; ?? ?}? ??? ?if(firstflag[m]=='0')//假如此字符的FIRST集尚未查找,則找其FIRST集,并標(biāo)其查找狀態(tài)為1????? {?? ? ???first2(m); ? ? firstflag[m]='1';? ? ??}? ? merge(first1[i],first1[m],2);//把求得結(jié)果并入到X的FIRST集. ?? ? }//----產(chǎn)生式為X→Y1Y2…Yk,若對一切1<=i<=k,均有&∈FIRST(Yi),則將&∈符號(hào)加進(jìn)FIRST(X) ???elseif(_emp(right[j][k])==1&&k==(int)strlen(right[j])-1) ???{//當(dāng)前右部符號(hào)串可推出空且是右部符號(hào)串的最后一個(gè)字符 ?? ?temp[0]='&';? ?temp[1]='\0'; ?? ? merge(first1[i],temp,1);//把空字加入到當(dāng)前字符X的FIRST集. ? ? ?} else ? ??break;//不能推出空字則結(jié)束循環(huán) ???} ? ?} } } }?firstflag[i]='1';//標(biāo)記當(dāng)前字符c已查找其FIRST集}/*******************************************求各產(chǎn)生式右部的FIRST********************************************/voidFIRST(inti,char*p) ? {//指針p指向右部符號(hào)串 intlength;//標(biāo)記右部符號(hào)串的長度?intj,k,m; chartemp[20];?length=strlen(p);?if(length==1)//假如右部為單個(gè)符號(hào)?{? if(p[0]=='&')//右部符號(hào)串字符為"&"空字{? ?if(i>=0)//i不為-1時(shí)是產(chǎn)生式的序號(hào){? ? first[i][0]='&'; //把"&"加入到當(dāng)前符號(hào)串的FIRST集??? first[i][1]='\0'; } ? else//i為-1時(shí),表達(dá)求FOLLOW時(shí)用到的產(chǎn)生式右部的FIRST集,保存在TEMP[]中?? {????TEMP[0]='&';? TEMP[1]='\0';?? }??}? else//右部符號(hào)串字符不為"&"空字 {?? for(j=0;;j++)???{?? if(v[j]==p[0])//求右部符號(hào)的第一個(gè)字符p[0]在所有字符集中的位置j? ??break; ?}???if(i>=0)?? {?? memcpy(first[i],first1[j],strlen(first1[j]));//把j所指向的單個(gè)符號(hào)的FIRST集拷貝到該右部符號(hào)串的FIRST集 ???first[i][strlen(first1[j])]='\0'; }? ?else ?{?? memcpy(TEMP,first1[j],strlen(first1[j]));? TEMP[strlen(first1[j])]='\0'; ??}} }?else//假如右部為符號(hào)串?{? for(j=0;;j++) ?{?? if(v[j]==p[0])//求右部符號(hào)的第一個(gè)字符p[0]在所有字符集中的位置j? ??break; ?} if(i>=0)? merge(first[i],first1[j],2);? else???merge(TEMP,first1[j],2); for(k=0;k<=length-1;k++) ?{ ??empt[0]='\0';???if(_emp(p[k])==1&&k<length-1)? {//當(dāng)前產(chǎn)生式右部符號(hào)可推出空字,且當(dāng)前字符不是右部的最后一個(gè)字符 ? ?for(m=0;;m++) ? { ??if(v[m]==right[i][k+1]) ?break;? } ? if(i>=0) ????merge(first[i],first1[m],2);? ? else? ? merge(TEMP,first1[m],2);?? } ??elseif(_emp(p[k])==1&&k==length-1) ?{//當(dāng)前右部符號(hào)串可推出空且是右部符號(hào)串的最后一個(gè)字符????temp[0]='&';? ??temp[1]='\0';? if(i>=0) ?? ?merge(first[i],temp,1); ???else ????merge(TEMP,temp,1); } ? elseif(_emp(p[k])==0)????break;??}?}}/*******************************************求各產(chǎn)生式左部的FOLLOW********************************************/voidFOLLOW(inti){//參數(shù)i為該符號(hào)在非終結(jié)符中的位置 intj,k,m,n,result=1;?charc,temp[20]; c=non_ter[i];//c為待求的非終結(jié)符?temp[0]=c;?temp[1]='\0';?merge(foll,temp,1);//把當(dāng)前字符放到一臨時(shí)數(shù)組foll[]中,標(biāo)記求已求其FOLLOW集.避免循環(huán)遞歸 if(c==start) {//若為開始符號(hào)-----開始符號(hào)S,則#∈FOLLOW(S)??temp[0]='#'; temp[1]='\0'; ?merge(follow[i],temp,1);?}for(j=0;j<=count-1;j++)?{??if(in(c,right[j])==1)//找一個(gè)右部具有當(dāng)前字符c的產(chǎn)生式 {//比如求FOLLOW(B)則找A→αB或A→αBβ(β=>*&)的產(chǎn)生式 ??for(k=0;;k++) ?{? ? if(right[j][k]==c) ? ? break;//k為c在該產(chǎn)生式右部的序號(hào),如B在產(chǎn)生式A→αB中的位置???}for(m=0;;m++)???{ ? if(v[m]==left[j]) ? ?break;//m為產(chǎn)生式左部非終結(jié)符在所有符號(hào)中的序號(hào)? ?}//假如c在產(chǎn)生式右部的最后,形如產(chǎn)生式A→αB,則FOLLOW(A)∈FOLLOW(B) ? if(k==(int)strlen(right[j])-1)? {??? if(in(v[m],foll)==1)//查找該非終結(jié)符是否已經(jīng)求過其FOLLOW集.避免循環(huán)遞歸 ?? {//是則FOLLOW(A)∈FOLLOW(B) ? ?merge(follow[i],follow[m],1);//把c所在產(chǎn)生式的左部非終結(jié)符的FOLLOW集加入到FOLLOW(c)中?? ?continue;//結(jié)束本次循環(huán),進(jìn)入j++循環(huán)} ? ?if(followflag[m]=='0') ? {//假如該非終結(jié)符的FOLLOW未求過??? FOLLOW(m);//求之FOLLOW集? ? ?followflag[m]='1';//標(biāo)記為1 ???}?? ?merge(follow[i],follow[m],1);//FOLLOW(A)∈FOLLOW(B)? ?} else ?{//假如c不在產(chǎn)生式右部的最后,形如A→αBβ ??for(n=k+1;n<=(int)strlen(right[j])-1;n++)? ?{? ???empt[0]='\0';//把empt[]置空,由于求此字符是否可推出空字_emp(c)時(shí)用到? ?result*=_emp(right[j][n]);????} if(result==1) {//假如右部c后面的符號(hào)串能推出空,A→αBβ(β=>*&)則FOLLOW(A)∈FOLLOW(B)if(in(v[m],foll)==1)??? {//查找該非終結(jié)符是否已經(jīng)求過其FOLLOW集.避免循環(huán)遞歸?? ?merge(follow[i],follow[m],1);//FOLLOW(A)∈FOLLOW(B) ?????continue;?? ??} ?if(followflag[m]=='0') ?? {? ?FOLLOW(m); ??? followflag[m]='1'; ? } ?? merge(follow[i],follow[m],1);? ??}//若A→αBβ,其中B∈VN,α∈(VTUVN)*、β∈(VTUVN)+,則FIRST(β)-{ε}∈FOLLOW(B);??? for(n=k+1;n<=(int)strlen(right[j])-1;n++) ? {temp[n-k-1]=right[j][n];??? }?? ?temp[strlen(right[j])-k-1]='\0'; FIRST(-1,temp);//求FIRST(β)? ??merge(follow[i],TEMP,2);//把FIRST(β)中所有非空元素加入到FOLLOW(B)中???}??} } followflag[i]='1';//標(biāo)記當(dāng)前規(guī)定的非終結(jié)符的FOLLOW集已求過}/*******************************************判斷讀入文法是否為一個(gè)LL(1)文法********************************************/intLL1(){inti,j,length,result=1; chartemp[50]; for(j=0;j<=49;j++)?{//初始化??first[j][0]='\0';follow[j][0]='\0';??first1[j][0]='\0'; ?select[j][0]='\0'; TEMP[j]='\0';? temp[j]='\0'; firstflag[j]='0';//用來記錄該字符的FIRST集是否已求過.1表達(dá)已求,0表達(dá)未求 ?followflag[j]='0';//用來記錄該字符的FOLLOW集是否已求過.1表達(dá)已求,0表達(dá)未求 } for(j=0;j<=(int)strlen(v)-1;j++) { ?first2(j);//求單個(gè)符號(hào)的FIRST集合,結(jié)果保存在first1[]里?}?printf("\n各非終結(jié)符推出的first集:\n");?for(j=0;j<=(int)strlen(v)-1;j++) { printf("%c:%s",v[j],first1[j]);?}printf("\n能導(dǎo)空的非終結(jié)符集合:%s",empty); printf("\n_emp:");?for(j=0;j<=(int)strlen(v)-1;j++) printf("%d",_emp(v[j])); for(i=0;i<=count-1;i++) ?FIRST(i,right[i]);//求FIRST for(j=0;j<=(int)strlen(non_ter)-1;j++){//求FOLLOW??if(foll[j]==0) ?{ ??foll[0]='\0'; ?FOLLOW(j); }} printf("\nfirst集:");?for(i=0;i<=count-1;i++) printf("%s",first[i]); printf("\nfollow集合:");for(i=0;i<=(int)strlen(non_ter)-1;i++)? printf("%s",follow[i]);?for(i=0;i<=count-1;i++)?{//求每一產(chǎn)生式的SELECT集合memcpy(select[i],first[i],strlen(first[i]));//first[]存放的是各產(chǎn)生式右部的FIRST集select[i][strlen(first[i])]='\0'; for(j=0;j<=(int)strlen(right[i])-1;j++)? result*=_emp(right[i][j]);? if(strlen(right[i])==1&&right[i][0]=='&')//形如產(chǎn)生式A->& ? result=1;? if(result==1)? {? ?for(j=0;;j++) ?if(v[j]==left[i])//j為左部符號(hào)在所有字符集中的位置???? break;? ? merge(select[i],follow[j],1);? }?} printf("\nselect集合順序是:"); for(i=0;i<=count-1;i++) ?printf("%s",select[i]);?memcpy(temp,select[0],strlen(select[0])); temp[strlen(select[0])]='\0';?for(i=1;i<=count-1;i++) {/*判斷輸入文法是否為LL(1)文法*/length=strlen(temp); ?if(left[i]==left[i-1]) {? ?merge(temp,select[i],1);???if(strlen(temp)<length+strlen(select[i]))//比較兩個(gè)產(chǎn)生式的SELECT長度 ???return(0); } else ?{?? temp[0]='\0'; ? memcpy(temp,select[i],strlen(select[i]));???temp[strlen(select[i])]='\0'; ?} }?return(1);}/*******************************************構(gòu)造分析表M********************************************/voidMM(){inti,j,k,m; for(i=0;i<=19;i++)?{ ?for(j=0;j<=19;j++)//初始化分析表,所有置為空(-1)? { ??M[i][j]=-1; } } i=strlen(termin); termin[i]='#';//將#加入終結(jié)符數(shù)組 termin[i+1]='\0'; for(i=0;i<=count-1;i++)//查看每個(gè)產(chǎn)生式的SELECT集?{for(m=0;;m++)?{ if(non_ter[m]==left[i]) ?break;//m為產(chǎn)生式左部非終結(jié)符的序號(hào)?} for(j=0;j<=(int)strlen(select[i])-1;j++)//對每個(gè)SELECT集中的所有元素進(jìn)行操作?{??if(in(select[i][j],termin)==1) ?{???for(k=0;;k++) ?{ ? ?if(termin[k]==select[i][j])? ? break;//k為產(chǎn)生式右部終結(jié)符的序號(hào)?? }?? M[m][k]=i; }?} }}/*******************************************判斷符號(hào)串是否是該文法的句型********************************************/voidsyntax(){ inti,j,k,m,n,p,q;charch; charS[50],str[50];printf("請輸入該文法的句型:"); scanf("%s",str); getchar();?i=strlen(str);?str[i]='#';?str[i+1]='\0'; S[0]='#';?S[1]=start;?S[2]='\0'; j=0;?ch=str[j];while(1) {? if(in(S[strlen(S)-1],termin)==1)??{if(S[strlen(S)-1]!=ch) ??{??? printf("該符號(hào)串不是文法的句型!");return; ??} ??elseif(S[strlen(S)-1]=='#') ?{printf("該符號(hào)串是文法的句型.");return;?? } else???{S[strlen(S)-1]='\0';????j++;? ch=str[j]; ? }? } else ?{for(i=0;;i++) ???if(non_ter[i]==S[strlen(S)-1])? ? break;??? for(k=0;;k++) ? {?? ? if(termin[k]==ch)? ????break;? ? if(k==(int)strlen(termin)) ? ??{?? ?printf("詞法錯(cuò)誤!");??? ? return;? ???}? ?}

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論