編譯原理課程設計 LL(1)文法的判定_第1頁
編譯原理課程設計 LL(1)文法的判定_第2頁
編譯原理課程設計 LL(1)文法的判定_第3頁
編譯原理課程設計 LL(1)文法的判定_第4頁
編譯原理課程設計 LL(1)文法的判定_第5頁
已閱讀5頁,還剩30頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

課程設計報告編譯原理課程設計課程學號姓名班級教師時間編譯原理課程設計計算機科學與技術系設計名稱:LL(1)文法的判定(假設文法符合的First和Follow集未知)設計內容、目的與要求:1、 設計內容LL(1)文法的判定(假設文法符合的First和Follow集未知)根據LL(1)分析法編寫一個語法分析程序,可根據自己實際情況,選擇以下一項作為分析算法的輸入:直接輸入根據已知文法構造的分析表M;輸入文法的FIRST(a)和FOLLOW(U)集合,由程序自動生成文法的分析表M;輸入已知文法,由程序自動構造文法的分析表M。所開發的程序可適用于不同的文法和任意輸入串,且能判斷該文法是否為LL(1)文法。如完成前兩項,可增加運行實例,對于輸入的文法和符號串,所編制的語法分析程序應能正確判斷此串是否為文法的句子,并要求輸出分析過程。2、 要求:輸入文法,輸出判定該文法是否是LL(1)的。計劃與進度安排:5月20日一5月23日:查閱資料,進一步掌握LL(1)文法的定義,掌握LL(1)分析法及其原理;5月24日一5月26日:分析題目,畫出系統的流程圖;5月27日一5月29日:根據流程圖,將系統功能劃分成各個不同的模塊;5月30日—5月31日:根據不同的模塊,設計與其相對應的函數,并依據分析函數的功能設置函數的參數和返回值;6月1日一6月2日:根據上一步的各個函數,編寫對應的代碼;6月3日一6月4日:對各個函數進行編譯和檢查;6月5日一6月6日:編寫程序執行的入口函數main()函數,通過調用各個函數,實現整個程序的基本功能;6月7日一6月8日:編寫程序執行的入口函數main()函數,通過調用各個函數,實現整個程序的基本功能;6月9日一6月10日:編譯整個程序,并根據調試信息進行相應的修改,同時

設計相關的文法進行測試,檢查程序是否滿足設計要求;6月11日一6月12日:使用不同的實例進行測試,同時修改并完善設計;6月13日一6月17日:完成設計并答辯。設計過程、步驟(可加頁):1、數據結構設計數據結構設計的合理性直接關系著系統功能的實現方便與否。本系統的數據結構包含全局變量的定義和一位數組以及二維數組的定義。intcount=0;/*分解的產生式的個數*/intnumber;/*所有終結符和非終結符的總數*/charstart;/*開始符號*/chartermin[50];/*終結符號*/charnon_ter[50];/*非終結符號*/charv[50];/*所有付號*/charleft[50];/*左部*/charright[50][50];/*右部*/charfirst[50][50],follow[50][50]; /*各產生式右部的FIRST和左部的FOLLOW集合*/charfirst1[50][50]; /*所有單個符號的FIRST集合*/charselect[50][50]; /*各單個產生式的SELECT集合*/charf[50],F[50];/*記錄各符號的FIRST和FOLLOW是否已求過*/charempty[20];/*記錄可直接推出的付號*/charTEMP[50];/*求FOLLOW時存放某符號串的FIRST集合*/intvalidity=1;/*表示輸入文法是否有效*/intll=1;/*表示輸入文法是否為LL(1)文法*/intM[20][20];/*分析表*/charchoose;/*用戶輸入時使用*/charempt[20];/*求_emp()時使用*/charfo[20];/*求FOLLOW集合時使用*/intdg=0;/*標志輸入文法是否是由有遞歸的文法哈成的LL()*/2、函數設計及其說明intin(charc,char*p)功能:判斷一個字符是否在指定字符串中說明:若該字符在指定字符串中,函數返回1;否則返回0。voidMM()功能:構造預測分析表M。說明:在該函數中,把預測分析表設計成二維數組,構造預測分析表時,文法用其序號代替。voidmenu()功能:設置用戶界面。說明:該函數將設計一個人機交互界面,從而選擇實現各種功能。voidCh()功能:得到一個不是非終結符的符號。說明:該函數通過調用in(charc,char*p)函數,返回一個不是非終結符的符號。voidmerge(char*d,char*s,inttype)功能:將單個符號或符號串并入另一符號串說明:d指向目標符號串,s指向源串,type=l,源串中的‘£‘一并并入目串;type=2,源串中的'「不并入目串。voidrecur(char*point)功能:分解含有左遞歸的產生式。說明:完整的產生式在point[]中。voidnon_re(char*point)功能:分解不含有左遞歸的產生式,即將形如P-*Qa|F的產生式分解為Pf*Qa和P—F。說明:完整的產生式在point[]中。intjudge()功能:判斷讀入的文法是否正確說明:若讀入的文法不正確則返回0,否則返回1。voidsyntax()功能:檢查輸入串是否滿足,通過分析表判斷。說明:通過分析表判斷,檢查輸入的字符串是否滿足。chargrammer(char*t,char*n,char*left,charright[50][50])功能:讀入一個文法。說明:char*七指向終結符號的集合;char*n指向非終結符號的集合;char*left指向文法產生式的左部;charright[50][50]傳遞的參數是文法產生式的右部。voidFOLLOW(inti)功能:求各產生式左部的FOLLOW集。說明:i為分解后的產生式的序號。voidfirst2(inti)功能:求單個符號的FIRST集。說明:i為符號在所有輸入符號中的序號。voidFIRST(inti,char*p)功能:求各產生式右部的FIRST集。說明:i為分解后的產生式的序號;char*p指向產生式的右部。intlll()功能:判斷讀入文法是否為一個LL(1)文法。說明:若輸入的文法是LL(1)文法,返回1,否則報錯,返回0。voidemp(charc)功能:求所有能直接推出£的符號,這里利用Y弋替£。說明:charc是需要判斷的符號。int_emp(charc)功能:求某一符號能否推出說明:charc是需要判斷的符號,若能推出,則返回1,否則返回0。3、總控算法及流程推導出非終結符首先進行第一次掃描,把能夠直接推出$的非終結符號記錄到空串表,把不能直接推出$的符號依次記錄下來,然后單個掃描每一個不能直接推出$的符號。掃描這個符號能夠直接推出的第一個非終結符記錄到一個隊列,接下來依次檢查隊列中每一個元素,把二次能夠推出$的符號記錄到空串表,把二次也推不出空串的繼續送入到隊列,然后再從隊列取元素掃描,直到隊列為空沒能找到能夠星推導出$的終結符,那么可以確定這個非終結符推導不出$,接下去掃描下一個非終結符。確定FIRST集FIRST集使用以下四個步驟判定:、若XeVTT,則FIRST(X)二{X}、若XGVN,且有產生式X-a…,aeVT則把a加入到FIRST(X)中,即aeFIRST(X)、若XeVN,且有產生式X-$,則把$也加到FIRST(X)中,^P$GFIRST(X)、若XeVN,Y1,Y2,…,Yi都eVN,且有產生式X—Y1Y2-Yno當Y1,..Yi-1二>$(1WiWn),貝UFIRST(Y1)-{$},…,FIRST(Yi-1)-{$},FIRST(Yi)都包含在FIRST(X)中,即:FIRST(Yi-1)-{$}eFIRST(X)所有Y1,???Yn*=>$,則把$加到FIRST(X)中,即:FIRST(Yi)eFIRST(X)其中第1-3個方法都很好處理,關鍵是第四個方法判斷時首先判斷第一個字符為非終結符,設定一個布爾型掃描標志FLAG,賦初值TRUE,接下去依次掃描產生式右部每一個字符Yi,假如第i個字符可以推出空,那么就把這個字符的FIRST集去除$加入到產生式左部字符的FIRST集中,即FIRST(Yi)-{$}iFIRST(X),假如Yi是終結符或者不可以推出$,那么就把這個字符的FIRST集直接加入到FIRST(X)中,即FIRST(Yi)IFIRST(X)同時置FLAG為FALSE不再向下掃描,假如Yi恰好是最后一個字符,那么不管它能不能星推導出空都直接把它的FIRST集加入到FIRST(X)中。同時要設置一個隊列和一組布爾型變量記錄FIRST集是否完成,隊列用來記錄FIRST(X)用到了哪些其它非終結符的FIRST集。第一遍掃描完成后就掃描隊列,把FIRST集完成的非終結符的FIRST集加入到那些沒有完成的非終結符的FIRST集中去,沒有完成的非終結符再送回到隊列,這時候可能出現死循環,比如FIRST(S)用到了FIRST(A),而FIRST(A)用到了FIRST(B),FIRST(B)又用到了FIRST(S),這時候S,A,B的FIRST標志均為FALSE,無限循環下去。這時候可以記錄一下,比如循環了100次,強行設置FIRST(S)的標志為TRUE,那么FIRST(A),FIRST(B)也就依次可以求出了。我們在實際計算時也是這樣處理的,只是沒有把標志寫出來而是記錄在心里的。確定FOLLOW集FOLLOW集使用以下三個步驟判定:、如果X是開始符那么把#加入到FOLLOW(X)、若A=>aBB是一個產生式,則把FIRST(B)—{$}加至FOLLOW(B)中、若A=>aB是一個產生式,或A二〉aBB是一個產生式而B*二>$(即$$FIRST(B)),則把FOLLOW(A)加至FOLLOW(B)中。FOLLOW集的求法與FIRST集類似,但有不同的地方。FOLLOW集需要掃描每一個產生式。而FIRST集掃描的是產生式左部不同的產生式,然后掃描左部相同的產生式的每一個右部。FOLLOW集第一次掃描可以確定哪些FIRST集或FOLLOW集屬于所求的FOLLOW集,由于FIRST集已經求出,所以第一次掃描就可以把相應的FIRST集加入到FOLLOW集中,設置FOLLOW集完成標記位,設置隊列,把未完成的非終結符送入隊列,依次取出隊列元素,把求出FOLLOW集的非終結符的FOLLOW集加入到相應的FOLLOW集中,把未求出的送回隊列。如果碰到死循環使用FIRST集一樣的方法處理就可以。確定SELLECT集FIRST集&FOLLOW集都已經求出來后SELLECT集就很好求了,掃描每一個產生式,使用以下三個步驟確定:A—aAeVN,aEV*,、若a是終結符,那么SELLECT(A—a)={a};、若a是$,則SELECT(A—a)二FOLLOW(A);、若a是非終結符,那么若a*=>$,則SELECT(A—a)=(FIRST(a)-$)UFOLLOW(A);若a「*=>$則SELECT(A—a)=FIRST(a)。LL(1)文法的判定當SELLECT集求出來后就可以判斷是不是一個文法是不是LL(1)文法了,掃描產生式左部相同的SELLCET集是否含有相同元素,一旦發現相同元素立刻返回0,掃描結束沒有發現相同元素則返回1。句子的判定當一個文法確定是LL(1)文法時就可以對輸入的語句進行判定了。首先要安裝SELLECT集生成LL(1)預測分析表,最簡單的方法是使用哈希表來表示,把每一個產生式左部依次和這個產生式SELLECT集中的每一個終結符組成關鍵字,其值即為這個產生式,送入哈希表。這樣在進行句子的分析時就可以很容易判斷是否使用某一個產生式來進行規約。在實際分析時設置兩個棧,把"#〃壓入分析棧和剩余棧,把開始符壓入分析棧,把輸入串從右向左送入剩余棧,然后只要兩個棧元素個數同時大于1,那么依次從兩個棧中取出兩個元素進行比較,假如一樣就匹配,假如可以規約就規約,否則就不是該文法的句子。圖1整個系統控制流程圖

E2壬遼航集合計算的程序控制流程團

結果與分析(可以加頁):1、輸入一個LL⑴進行測試,測試文法,測試結果如下圖所示G(Z):Z->dAZ|bAcA->aA|e圖4輸入LL⑴文法并測試2、輸入上述文法的一個句型進行測試,測試結果如下圖所示待測試的句型1:bac圖5測試滿足指定文法的句型待測試句型2:abc圖6測試不滿足指定文法的句型3、測試一個非LL(1)文法I.pft 口口Right:-TRternixn: ■nontersETFftEw=ETFftD-"3E->E+T:E-r:IT->T*FSr/TIFF-XE>il/TB'FB<E>IFFTfi*FBBEHstart'E_enr:0001 1 0BH00M0HJI.pft 口口Right:-TRternixn: ■nontersETFftEw=ETFftD-"3E->E+T:E-r:IT->T*FSr/TIFF-XE>il/TB'FB<E>IFFTfi*FBBEHstart'E_enr:0001 1 0BH00M0HJQ^Windo^vs\5ystern32\cmdl.exeuI口 I-E->123-—..——..量#3F(ET*/rr號號雜??;■式?耳口土主+亠嚴亠嚴產丈:■開生養蟲的的?嚴的的的進法法法法迭法各〈哀rIH.IH,lidt=稈往5LB請請Tt'If'If:11存存lcoBtill】First:*-Ci*/<i<iFollow:#><#>+-*/ <#><#)+-*/select:- <1?Z化#”<i<i消除遞歸后:1H=國該文法不是一tixs文法!請按任意犍繼續…-圖7測試非LL⑴文法設計體會與建議:近一個月的設計過程,雖然題目早已經布下,但當時正在學習中,看到題目僅是一頭霧水,沒有一點頭緒。剛拿到題目的時候,乍看很簡單,但當真正入手做的時候,覺得設計一個合理的數據結構不是一件很容易的事。因為一個好的軟件設計,應該考慮到它的健壯性和可擴充性,而且能夠做的比較完善,對于系統運行中可能遇到的問題能夠給出人性化的提示。這需要在問題分析和題目設計的過程中逐漸改進。就本次設計而言,要構造預測分析表,就要考慮輸入的文法是否是LL(1)文法,對檢測的結果應該給予適當的處理。經過查找資料和他人的耐心答疑,我終于設計處理較為合理的程序,達到了預期的課程設計目的。隨著課程的深入,逐漸了解到一點解題的方法,但對于上機實踐還是沒有什么想法,后來到圖書館和網上找了很多資料,才了解到大致的實現方法,有根據以前的一點編程經驗,于是開始一個模塊一個模塊的去實現,然后在進行整合,合并成一個完整的程序。通過本次課程設計,使學到的理論知識得到了實踐,清晰地看到了LL(1)分析的全過程,掌握了first,follow,select的機上實現方法,掌握了分析表的構造過程和方法,但遺憾的是,對于一些實現方法,例如句型分析的跟蹤過程,仍是參考的網上的源程序,感到了自己的不足,還需更加努力!

附錄:程序代碼#include<stdlib.h>#include<stdio.h>#include<string.h>intcount=0;intnumber;charstart;chartermin[50];charnon_ter[50];charv[50];charleft[50];charright[50][50];/*分解的產生式的個數*//*所有終結符和非終結符的總數*//*開始符號*//*終結符號*//*非終結符號*//*所有符號*//*左部*//*右部*/charfirst[50][50],follow[50][50]; /*各產生式右部的FIRST和左部的FOLLOW集合*/charfirst1[50][50];charselect[50][50];charf[50],F[50];charempty[20];charTEMP[50];intvalidity=1;intll=1;intM[20][20];charchoose;charempt[20];charfo[20];/*所有單個符號的FIRST集合*//*各單個產生式的SELECT集合*//*記錄各符號的FIRST和FOLLOW是否已求過*//*記錄可直接推出人的符號*//*求FOLLOW時存放某一符號串的FIRST集合*//*表示輸入文法是否有效*//*表示輸入文法是否為LL(1)文法*//*分析表*//*用戶輸入時使用*//*求_emp()時使用*//*求FOLLOW集合時使用*/判斷一個字符是否在指定字符串中intin(charc,char*p){inti;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)/*若在,返回/*若在,返回1*//*若不在,返回0*/if(i==strlen(p))return(0);}}得到一個不是非終結符的符號charc(){charc='A';while(in(c,non_ter)==1)c++;return(c);}分解含有左遞歸的產生式voidrecur(char*point){ /*完整的產生式在point[]中*/intj,m=0,n=3,k;chartemp[20],ch;ch=c(); /*得到一個非終結符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘后|'的首符號和左部相同*/for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else/*如果‘后|'的首符號和左部不同*/left[count]=ch;right[count][0]='A';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf("count=%d",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}分解不含有左遞歸的產生式voidnon_re(char*point){intm=0,j;chartemp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];elseleft[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}讀入一個文法chargrammer(char*t,char*n,char*left,charright[50][50]){charvn[50],vt[50];chars;charp[50][50];inti,j,k;printf(”請輸入文法的非終結符號串:”);scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf(”請輸入文法的終結符號串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf(”請輸入文法的開始符號:");scanf("%c",&s);getchar();printf("請輸入文法產生式的條數:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("請輸入文法的第%小條(共%d條)產生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){printf("\ninputerror!");validity=0;return('\0');} /*檢測輸入錯誤*/for(k=0;k<=i-1;k++){ /*分解輸入的各產生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}將單個符號或符號串并入另一符號串voidmerge(char*d,char*s,inttype){ /*d是目標符號串,s是源串,type=l,源串中的‘人'—并并入目串;type=2,源串中的‘人’不并入目串*/inti,j;for(i=0;i<=strlen(s)-l;i++){if(type==2&&s[i]=='A')else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+l]='\0';break;

求所有能直接推出人的符號/*即求所有由/*即求所有由‘人'推出的符號*/{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);emp(left[i]);}}}求某一符號能否推出‘人'int_emp(charc){ /*若能推出,返回1;否則,返回0*/inti,j,k,result=1,mark=0;chartemp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一個左部為c的產生式*/{j=strlen(right[i]); /*j為右部的長度*/if(j==1&&in(right[i][0],empty)==1)return(1);elseif(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;elseif(result==1&&i<count)return(1);}}}判斷讀入的文法是否正確intjudge(){inti,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非終結符中,報錯*/printf("\nerror1!");validity=0;

return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='A'){ /*若右部某一符號不在非終結符、終結符中且不為‘;'報錯*/printf("\nerror2!");validity=0;return(0);}}}return(1);}求單個符號的FIRST/*i為符號在所有輸入符號中的序號/*i為符號在所有輸入符號中的序號*/{charc,temp[20];intj,k,m;charch='A';c=v[i];emp(ch);if(in(c,termin)==1) /*若為終結符*/{first1[i][0]=c;first1[i][1]='\0';}elseif(in(c,non_ter)==1) /*若為非終結符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='A'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);elseif(in(right[j][0],non_ter)==1){}}f[i]='1';}if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}elseif(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[O]='N;temp[1]='\0';merge(first1[i],temp,1);}elsebreak;求各產生式右部的FIRSTvoidFIRST(inti,char*p){intlength;intj,k,m;chartemp[20];length=strlen(p);if(length==1) /*如果右部為單個符號*/{if(p[O]=='T{if(i>=0){first[i][0]='A';first[i][1]='\0';}else{TEMP[0]='A';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部為符號串*/{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}elseif(_emp(p[k])==1&&k==length-1){temp[O]='N;temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}elseif(_emp(p[k])==0)break;}}}求各產生式左部的FOLLOWvoidFOLLOW(inti){/*c為待求的非終結符/*c為待求的非終結符*/c=non_ter[i];temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若為開始符號*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一個右部含有c的產生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k為c在該產生式右部的序號*/for(m=0;;m++)if(v[m]==left[j])break; /*m為產生式左部非終結符在所有符號中的序號*/if(k==strlen(right[j])-1){ /*如果c在產生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在產生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符號串能推出心/if(in(v[m],fo)==1){ /*避免循環遞歸*/merge(follow[i],follow[m],1);

continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}判斷讀入文法是否為一個LL(1)文法intll1()/*初始化*//*初始化*//*求單個符號的FIRST集合*/{first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j);printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n_emp:");for(j=0;j<=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<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s",follow[i]);for(i=0;i<=count-1;i++){ /*求每一產生式的SELECT集合*/memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==l&&right[i][0]=='A')result=1;if(result==l){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],l);}}printf("\nselect:");for(i=0;i<=count-l;i++)printf("%s",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=l;i<=count-l;i++){ /*判斷輸入文法是否為LL(1)文法*/length=strlen(temp);if(left[i]==left[i-1])merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}構造分析表MvoidMM(){inti,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*將#加入終結符數組*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m為產生式左部非終結符的序號*/f

溫馨提示

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

評論

0/150

提交評論