廣藥編譯原理實(shí)驗_第1頁
廣藥編譯原理實(shí)驗_第2頁
廣藥編譯原理實(shí)驗_第3頁
廣藥編譯原理實(shí)驗_第4頁
廣藥編譯原理實(shí)驗_第5頁
已閱讀5頁,還剩25頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、實(shí)驗一:消去C、C+程序中的注釋實(shí)驗類型:驗證一、實(shí)驗?zāi)康恼莆誄語言文件的基本操作,消除源C語言程序中的注釋,為以后的編譯提供方便。二、實(shí)驗內(nèi)容注釋對于高級語言程序設(shè)計可以提高程序的可閱讀性,但是對于編譯系統(tǒng)而言,注釋是沒有實(shí)際意義的,所以編譯系統(tǒng)在預(yù)編譯階段首先就要去掉注釋。在VC中有兩種注釋,即單行注釋,由/引入到行未,由/*.*/所包圍的注釋。要求去掉VC中這兩種注釋而不改變程序的其它部分。三、實(shí)驗原理或算法算法原理:逐字符讀入源程序,并判斷相鄰2個字符是否為/或/*或*/,如果不是,則直接將讀入的字符寫入新文件中;如果是,則跳過注釋部分。四、程序清單在VC6.0下程序清單:/削除單行注

2、釋與多行注釋即/與/*.*/#includestdio.h#includestdlib.hmain()FILE*fp1,*fp2;char ch1,ch2,ch3,ch4,flag=0; if(fp1=fopen(D:Hxjb.c,r)=NULL)/ input.cpp為任意帶注釋的C程序 printf(file cannot be openedn);exit(1);if(fp2=fopen(D:Hxjb1.c,w)=NULL)printf(file cannot be writedn);exit(1);/fgetc是用來從文件中讀取內(nèi)容的ch1=fgetc(fp1);ch2=fgetc(fp

3、1);/feof為輸入輸出函數(shù),檢查文件是否結(jié)束,如結(jié)束,則返回非零值,否則返回0。while(!feof(fp1)/文件未結(jié)束時feof(fp1)=0;反之為1 if(ch1=/)if(ch2=*|ch2=/)if(ch2=*)ch3=fgetc(fp1);ch4=fgetc(fp1);while(!(ch3=*& ch4=/)&!feof(fp1)ch3=ch4;ch4=fgetc(fp1);ch2=fgetc(fp1);if(ch2=/)while(ch2=fgetc(fp1)!=10);elsefputc(ch1,fp2);/ fputc函數(shù)的功能是把一個字符寫入指定的文件中elsef

4、putc(ch1,fp2);ch1=ch2;ch2=fgetc(fp1);fputc(ch1,fp2);fclose(fp1);fclose(fp2);return 1;五、實(shí)驗結(jié)果分析比對源文件和產(chǎn)生的新文件,對照驗證程序所產(chǎn)生的結(jié)果。答:程序byyl1.c運(yùn)行結(jié)果截圖如下:測試程序b.c如下:生成程序b1.c如下:顯然,通過文件b.c和b1.c的截圖對比,可見b1.c中少了b.c中的單行注釋/與多行注釋/*.*/,而其他部分不變。故程序的作用是讀入源程序中的字符,削除其中的單行注釋與多行注釋,產(chǎn)生一個新文件。六、思考題(1)將輸入輸出文件改成可由鍵盤輸入的文件名。答:改寫程序byyl12.

5、c如下:#includestdio.h#includestdlib.hmain()FILE*fp1,*fp2;char ch1,ch2,ch3,ch4,flag=0; char fname20;printf(請輸入文件名:n);scanf(%s,fname);/輸入文件名if(fp1=fopen(fname,r)=NULL)/打開輸入的文件名的文件printf(file cannot be openedn);exit(1);if(fp2=fopen(D:Hxjb1.c,w)=NULL)/新建文件b1printf(file cannot be writedn);exit(1);/fgetc是用來

6、從文件中讀取內(nèi)容的ch1=fgetc(fp1);ch2=fgetc(fp1);/feof輸入輸出函數(shù),檢查文件是否結(jié)束,如結(jié)束,則返回非零值,否則返回0 while(!feof(fp1)/文件未結(jié)束時feof(fp1)=0;反之為1 if(ch1=/)if(ch2=*|ch2=/)if(ch2=*)ch3=fgetc(fp1);ch4=fgetc(fp1);while(!(ch3=*& ch4=/)&!feof(fp1)ch3=ch4;ch4=fgetc(fp1);ch2=fgetc(fp1);if(ch2=/)while(ch2=fgetc(fp1)!=10);elsefputc(ch1,f

7、p2);/ fputc函數(shù)的功能是把一個字符寫入指定的文件中elsefputc(ch1,fp2);ch1=ch2;ch2=fgetc(fp1);fputc(ch1,fp2);fclose(fp1);fclose(fp2);return 1;程序運(yùn)行結(jié)果如下:輸入要打開的文件名:源文件b.c:生成文件b1.c:(2)如果在字符串中出現(xiàn)連續(xù)的/或/*或*/則不應(yīng)做處理,請修改上面的程序。答:程序byyl13.cpp如下:#include stdio.h#include stringchar fsm8128;void initfsm() const int line_len=sizeof(char)

8、*128;memset(fsm0,0,line_len); memset(fsm1,0,line_len);memset(fsm2,2,line_len); memset(fsm3,3,line_len); memset(fsm4,3,line_len); memset(fsm5,5,line_len); memset(fsm6,5,line_len); memset(fsm7,0,line_len); fsm0/=1; fsm0=5; fsm1/=2; fsm1*=3; fsm1=5; fsm2n=7; fsm3*=4; fsm4/=7; fsm4*=4; fsm5=0; fsm5=6; f

9、sm7/=1; fsm7=5;int main() int state=0; char c; std:string s; FILE *fin=fopen(D:Hxja.c,r); FILE *fout=fopen(D:Hxja1.c,w); initfsm(); while(fscanf(fin,%c,&c)!=EOF) state=fsmstatec; s+=c; switch(state) case 0: fprintf(fout,%s,s.c_str(); s=; break; case 7: s=; if(c=n) fputc(c,fout); break; fclose(fin);

10、fclose(fout); return 0; 源文件a.c如下:生成文件a1.c如下:兩張截圖對比可見程序?qū)υ谳敵龅姆柎谐霈F(xiàn)連續(xù)的/或/*或*/不做處理,而刪除了注釋內(nèi)容。實(shí)驗二:詞法分析實(shí)驗類型:綜合一、實(shí)驗?zāi)康耐ㄟ^設(shè)計編制調(diào)試一個具體的詞法分析程序,加深對詞法分析原理的理解。并掌握在對程序設(shè)計語言源程序進(jìn)行掃描過程中將其分解為各類單詞的詞法分析方法。二、實(shí)驗內(nèi)容編制一個讀單詞過程,從輸入的源程序中,識別出各個具有獨(dú)立意義的單詞,即基本保留字、標(biāo)識符、常數(shù)、運(yùn)算符、分隔符五大類。并依次輸出各個單詞的內(nèi)部編碼及單詞符號自身值。(遇到錯誤時可顯示“Error”,然后跳過錯誤部分繼續(xù)顯示)。

11、三、實(shí)驗原理或算法1、詞法分析器的功能和輸出格式詞法分析器的功能是輸入源程序,輸出單詞符號。詞法分析器的單詞符號常常表示成以下的二元式(單詞種別碼,單詞符號的屬性值)。本實(shí)驗中,采用的是一類符號一種別碼的方式。2、單詞的BNF表示- -| - - |- +- - - =3、“超前搜索”方法詞法分析時,常常會用到超前搜索方法。如當(dāng)前待分析字符串為“a=”或“ab”,當(dāng)前字符為“”,此時,分析器倒底是將其分析為大于關(guān)系運(yùn)算符還是大于等于關(guān)系運(yùn)算符呢?顯然,只有知道下一個字符是什么才能下結(jié)論。于是分析器讀入下一個字符“”或“b”,這時可知應(yīng)將“”解釋為大于或大于等于運(yùn)算符。但此時,超前讀了一個字符“

12、b”,所以要回退一個字符,詞法分析器才能正常運(yùn)行。在分析標(biāo)識符,無符號整數(shù)等時也有類似情況。4、編程思路這里以開始定義的C語言子集的源程序作為詞法分析程序的輸入數(shù)據(jù)。在詞法分析中,自文件頭開始掃描源程序字符,一旦發(fā)現(xiàn)符合“單詞”定義的源程序字符串時,將它翻譯成固定長度的單詞內(nèi)部表示,并查填適當(dāng)?shù)男畔⒈怼=?jīng)過詞法分析后,源程序字符串(源程序的外部表示)被翻譯成具有等長信息的單詞串(源程序的內(nèi)部表示),并產(chǎn)生兩個表格:常數(shù)表和標(biāo)識符表,它們分別包含了源程序中的所有常數(shù)和所有標(biāo)識符。5、單詞種別碼要求:識別保留字:if、int、for、while、do、return、break、continue;單

13、詞種別碼為1。 分隔符包括:,、;、(、); 單詞種別碼為2。運(yùn)算符包括:+、-、*、/、=、;單詞種別碼為3。關(guān)系運(yùn)算符:、=、=、!= ;單詞種別碼為4。標(biāo)識符;單詞種別碼為5。常數(shù)為無符號整形數(shù);單詞種別碼為6。四、程序清單#include #include #include #include #define NULL 0FILE *fp;char cbuffer;char *key8=if,else,for,while,int,return,break,continue;char *border6=,;,(,);char *arithmetic5=+,-,*,/,=;char *rel

14、ation6=,=,!=;char *consts20;char *label20;int constnum=0,labelnum=0;int search(char searchchar,int wordtype)int i=0;switch (wordtype)case 1:for (i=0;i=7;i+)if (strcmp(keyi,searchchar)=0) return(i+1);return 0;case 2:for (i=0;i=5;i+)if (strcmp(borderi,searchchar)=0) return(i+1);return(0);case 3:for (i

15、=0;i=4;i+)if (strcmp(arithmetici,searchchar)=0) return(i+1); return(0);case 4:for (i=0;i=5;i+)if(strcmp(relationi,searchchar)=0) return(i+1); return(0);case 5:for (i=0;iconstnum;i+)if(strcmp(constsi,searchchar)=0) return(i+1); constsi=(char *)malloc(sizeof(searchchar);strcpy(constsi,searchchar);cons

16、tnum+;return(i+1);case 6:for (i=0;ilabelnum;i+)if (strcmp(labeli,searchchar)=0) return(i+1); labeli=(char *)malloc(sizeof(searchchar);strcpy(labeli,searchchar);labelnum+;return(i+1);char alphaprocess(char buffer)/字母開頭串的處理(可能是保留字或標(biāo)識符)int atype;int i=-1;char alphatp20;while (isalpha(buffer)|(isdigit(b

17、uffer) alphatp+i=buffer;buffer=fgetc(fp);alphatpi+1=0;/printf(%s,search=%d,alphatp,search(alphatp,1); if (atype=search(alphatp,1)printf(%s,1,%d)n,alphatp,atype); elseatype=search(alphatp,6);printf(%s,6,%d)n,alphatp,atype); return(buffer);char digitprocess(char buffer) /常量串的處理int i=-1;char digittp20;

18、int dtype;while (isdigit(buffer)digittp+i=buffer;buffer=fgetc(fp);digittpi+1=0;dtype=search(digittp,5);printf(%s,5,%d)n,digittp,dtype);return(buffer);char otherprocess(char buffer) /進(jìn)行其它符號的處理 int i=-1;char othertp20;int otype,otypetp;othertp0=buffer;othertp1=0;if (otype=search(othertp,3)printf(%s,3,

19、%d)n,othertp,otype);buffer=fgetc(fp);goto out;if (otype=search(othertp,4)buffer=fgetc(fp);othertp1=buffer;othertp2=0;if (otypetp=search(othertp,4) printf(%s,4,%d)n,othertp,otypetp); goto out;elseothertp1=0;printf(%s,4,%d)n,othertp,otype); goto out;if (buffer=:)buffer=fgetc(fp);if (buffer=)printf(:=

20、(2,2)n);buffer=fgetc(fp);goto out;elseif (otype=search(othertp,2)printf(%s,2,%d)n,othertp,otype); buffer=fgetc(fp);goto out;if (buffer!=n)&(buffer!= )printf(%c error,not a wordn,buffer);buffer=fgetc(fp);out: return(buffer);void main()int i;for (i=0;iE+T|T T-T*F|F F-(E)| 所生成的句子進(jìn)行LL(1)分析,構(gòu)造其分析程序。三、實(shí)驗原

21、理或算法1、改造文法:消除左遞歸、提取左因子 將文法改造為: ETE E+TE| TFT T*FT|F (E)|i2、 求出firstt和follow FIRST()的 構(gòu)造:設(shè)(VNVT)*,=X1X2Xn,F(xiàn)IRST():(1)若=,則FIRST()=;(2)若,則FIRST() FIRST(X); (3)若X1X2Xi1* , 則:FIRST(Xi) FIRST(); (4)若X1X2Xn * , 則 FIRST()對于X(VNVT),F(xiàn)IRST(X) 的構(gòu)造: (1)若X VT,則FIRST(X)=X;(2)若X VN,且有產(chǎn)生式Xa,a VT ,則:aFIRST(X),如果X ,那么

22、FIRST(X);(3)若有產(chǎn)生式XY,Y VN ,則:FIRST(Y) FIRST(X);(4)如果有產(chǎn)生式XY1Y2YK,其中Y1,Y2,Yi1 VN 且Y1Y2Yi1* , 則FIRST(Yi) FIRST(X);(5)若Y1Y2YK * ,則 FIRST(X)。FOLLOW(U) 的 構(gòu)造:(1)# FOLLOW(S)(2)如果有產(chǎn)生式AxUy,那么FIRST(y) FOLLOW(U)。(3)如果有產(chǎn)生式AxU 或則 AxUy 且y*,那么FOLLOW(A) FOLLOW(U) 3、LL(1)文法的判定:對于文法G 的每一個非終結(jié)符U 的產(chǎn)生式:U1|2|n 。如果文法G 是一個LL(

23、1) 文法,則有SELECT(Ui)SELECT(Uj)= (ij,i,j=1,2,n)。4、SELECT 集的構(gòu)造:SELECT(U)= FIRST(), 當(dāng) 不空 FIRST()FOLLOW(U), 當(dāng) 為空對于上面的方法可以得到:first(E)= (,ifirst( E)=+, first(T)=*, follow(E)=follow(E)= ),# follow(T)=follow(T)=+, ),# follow(F)=*,+,),# (3) 構(gòu)造預(yù)測分析表 5、LL(1)分析表構(gòu)造算法:對于每個產(chǎn)生式U,執(zhí)行下一步驟:1、對于每個終結(jié)符號:aFIRST(),MU,a=U.2、如果

24、eFIRST( ),對于每個終結(jié)符號:bFOLLOW(U),MU,b=U。3、將其它未定義的分析元素置為ERROR。預(yù)測分析表i+*()#ETETEE+TETFTFTT*FTFi(E)6、自下而上分析技術(shù):從輸入符號串出發(fā),試圖把它規(guī)約為識別符號。自下而上分析技術(shù)是一種“移進(jìn)歸約”法。從輸入符號串開始,從左到右進(jìn)行掃描,將輸入符號逐個移入一個棧中,邊移入邊分析,一旦棧頂符號串形成某個產(chǎn)生式的右部時,就用該產(chǎn)生式的左部非終結(jié)符代替,稱為歸約。重復(fù)這一過程,直到歸約到棧中只剩下文法的開始符號時,則分析成功, 稱為“移進(jìn)歸約”方法。四、程序清單/文法:E-E+T|T T-T*F|F F-(E)|i/

25、根據(jù)預(yù)測分析表MA,a對輸入串進(jìn)行自上而下的語法分析程序 /已知預(yù)測分析表MA,a和輸入串/判別輸入串是否為文法的句子,并生成預(yù)測分析步驟#include #include #include #includeusing namespace std;char Vn=E,e,T,t,F; /定義文法的非終結(jié)符,由小寫字母e表示E char Vt=i,+,*,(,),#; /定義文法的終結(jié)符 int LENVt=sizeof(Vt);void showstack(stack st) /從棧底開始顯示棧中的內(nèi)容 int i,j;char ch100; j=st.size();for(i=0;i=0;i

26、-) coutchi; st.push(chi); int find(char c,char array,int n)/查找函數(shù),返回布爾值 int i;int flag=0;for(i=0;in;i+) if(c=arrayi)flag=1; return flag; int location(char c,char array) /定位函數(shù),指出字符所在位置,即將字母轉(zhuǎn)換為數(shù)組下標(biāo)值 int i;for(i=0;c!=arrayi;i+); return i; void error() cout 出錯!endl; void analyse(char Vn,char Vt,string M5

27、6,string str) int i,j,p,q,h,flag=1; char a,X;stack st; /定義堆棧st.push(#); st.push(Vn0); /#與識別符號入棧j=0; /j指向輸入串的指針 h=1; a=strj;cout步驟 分析棧 剩余輸入串 所用產(chǎn)生式endl; while(flag=1) couth ; /顯示步驟 h+;showstack(st); /顯示分析棧中內(nèi)容 cout ;for(i=j;istr.size();i+) coutstri; /顯示剩余字符串X=st.top(); /取棧頂符號放入X if(find(X,Vt,LENVt)=1)

28、/X是終結(jié)符if(X=a) /分析棧的棧頂元素和剩余輸入串的第一個元素相比較 if (X!=#) cout X匹配endl;st.pop(); a=str+j; /讀入輸入串的下一字符 else cout 接受!endlendl; flag=0; else error();break; else p=location(X,Vn); /實(shí)現(xiàn)下標(biāo)的轉(zhuǎn)換(非終結(jié)符轉(zhuǎn)換為行下標(biāo)) q=location(a,Vt); /實(shí)現(xiàn)下標(biāo)的轉(zhuǎn)換(終結(jié)符轉(zhuǎn)換為列下標(biāo))string S1(NULL),S2(null); if(Mpq=S1 | Mpq=S2) /查找二維數(shù)組中的產(chǎn)生式 error();break; /

29、對應(yīng)項為空,則出錯 else string str0=Mpq; cout Xstr0=0;i-)st.push(str0i);/產(chǎn)生式右端逆序進(jìn)棧 main()string M56=Te ,NULL,NULL,Te, NULL,NULL,NULL,+Te ,NULL,NULL,$, $,Ft,NULL,NULL,Ft, NULL,NULL,NULL,$, *Ft, NULL,$, $,i,NULL,NULL,(E), NULL,NULL; /預(yù)測分析表j string str;int errflag,i;coutE+T|T T-T*F|F F-(E)|iendl;cout請輸入分析串(以#結(jié)束

30、):str;for(i=0;istr.size();i+)if(!find(stri,Vt,LENVt) cout輸入串中包含有非終結(jié)符stri(輸入錯誤)!endl; errflag=1;while(errflag=1); /判斷輸入串的合法性analyse(Vn, Vt, M,str);return 0;5、 實(shí)驗結(jié)果分析輸入i+i*(i+i)#,請給出結(jié)果截圖與分析答:程序byyl3.cpp運(yùn)行結(jié)果如下:輸入i+i*(i+i)#,結(jié)果如下:由上圖中的分析棧和剩余輸入串可見棧的變化,把“#”和文法開始符壓入進(jìn)棧,產(chǎn)生式右部為反序進(jìn)棧。 思考:如何改寫程序,實(shí)現(xiàn)first集和follow集的

31、自動生成算法、預(yù)測分析表的構(gòu)造算法?答:程序byyl32.cpp實(shí)現(xiàn)first集和follow集如下:#include #include #include #include#includeusing namespace std;char Vn=E,e,T,t,F; /定義文法的非終結(jié)符,由小寫字母e表示E char Vt=i,+,*,(,),#; /定義文法的終結(jié)符 int LENVt=sizeof(Vt);struct define /產(chǎn)生式 char left;string right; ; int N,K1=0,K2=0; char B; struct define *p=new def

32、ine10; bool find(char b) /查找是否有產(chǎn)生空的產(chǎn)生式 int i;for(i=0;iN;i+) if(b=pi.left & pi.right0=) return true; return false; bool findfo(char b) /查找是否有產(chǎn)生空的產(chǎn)生式 int i; for(i=0;iN;i+) if(b=pi.left & pi.right0=) return true; return false; string first(char b) /求解Frist集 int i,index; queue pos; string s,rights; for(i=0;iN;i+) if(b=pi.left) pos.push(i); while(!pos.empty() if(!(ppos.front

溫馨提示

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

最新文檔

評論

0/150

提交評論