編譯原理實(shí)驗(yàn)報(bào)告(詞法分析+語法分析)_第1頁
編譯原理實(shí)驗(yàn)報(bào)告(詞法分析+語法分析)_第2頁
編譯原理實(shí)驗(yàn)報(bào)告(詞法分析+語法分析)_第3頁
編譯原理實(shí)驗(yàn)報(bào)告(詞法分析+語法分析)_第4頁
編譯原理實(shí)驗(yàn)報(bào)告(詞法分析+語法分析)_第5頁
已閱讀5頁,還剩31頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、計(jì)算機(jī)專業(yè)類課程實(shí)驗(yàn)報(bào)告課程名稱:編譯原理學(xué)院:計(jì)算機(jī)科學(xué)與工程專業(yè):計(jì)算機(jī)科學(xué)與技術(shù)學(xué)生姓名:林怡學(xué)號:2012060020023指導(dǎo)教師:陳昆日期:2015年6月5日電 子 科 技 大 學(xué)實(shí) 驗(yàn) 報(bào) 告實(shí)驗(yàn)一1、 實(shí)驗(yàn)名稱:詞法分析器的設(shè)計(jì)與實(shí)現(xiàn)2、 實(shí)驗(yàn)學(xué)時(shí):43、 實(shí)驗(yàn)內(nèi)容和目的:實(shí)驗(yàn)內(nèi)容:求n!的極小語言的源程序作為詞法分析的輸入程序,根據(jù)給定的文法對其進(jìn)行詞法分析并將單詞符號與種別組成的二元式按指定格式輸出到out.dyd文件中,同時(shí)將詞法錯(cuò)誤輸出到error.err文件中。其中二元式文件out.dyd 有如下要求: (1)二元式形式: 單詞符號È種別 (2)每行后加上

2、“ÈÈÈ.ÈEOLNÈ24” (3)文件結(jié)尾加上 “ÈÈÈ.ÈEOFÈ25”出錯(cuò)文件error.err中錯(cuò)誤信息格式如下: *LINE:行號ÈÈ錯(cuò)誤性質(zhì)實(shí)驗(yàn)?zāi)康模?通過設(shè)計(jì)并實(shí)現(xiàn)一個(gè)詞法分析器,了解和掌握詞法分析程序設(shè)計(jì)的原理及相應(yīng)的程序設(shè)計(jì)方法,同時(shí)提高編程能力。4、 實(shí)驗(yàn)原理:1、編譯程序要求對高級語言編寫的源程序進(jìn)行分析和合成,生成目標(biāo)程序。詞法分析是對源程序進(jìn)行的首次分析,實(shí)現(xiàn)詞法分析的程序?yàn)樵~法分析程序。像用自然語言書寫的文章一樣,源程序是由一系列的句子組成的,句子

3、是由單詞符號按一定的規(guī)則構(gòu)成的,而單詞符號又是由字符按一定規(guī)則構(gòu)成,因此,源程序?qū)嶋H上是由滿足程序語言規(guī)范的字符按照一定的規(guī)則組合起來構(gòu)成的一個(gè)字符串。2、詞法分析的功能是從左到右逐個(gè)地掃描源程序字符串,按照詞法規(guī)則識別出單詞符號作為輸出,對識別過程中發(fā)現(xiàn)的詞法錯(cuò)誤,輸出相關(guān)信息。3、單詞符號是程序語言最基本的語法符號,為便于語法分析,通常將單詞符號分為五類(標(biāo)識符,基本字,常數(shù),運(yùn)算符,界符),而本次實(shí)驗(yàn)中單詞符號與其對應(yīng)的種別如下圖所示:4、狀態(tài)轉(zhuǎn)換圖是有限有向圖,是設(shè)計(jì)詞法分析器的有效工具。圖中的節(jié)點(diǎn)代表狀態(tài),節(jié)點(diǎn)間的有向邊代表狀態(tài)之間的轉(zhuǎn)換關(guān)系,有向邊上標(biāo)記的字符表示狀態(tài)轉(zhuǎn)換的條件。本

4、實(shí)驗(yàn)中的狀態(tài)轉(zhuǎn)換圖如下圖所示:5、本程序所設(shè)計(jì)主要方法及作用如下: int isletter(char c) 判別字符c是否為字母 int isdigital(char c) 判別字符c是否為數(shù)字 int match_reserve(char *p) 匹配字符串p是否為保留字 void match_symbol(const char *p) 匹配字符串p是否為標(biāo)識符 void match_double_operator(char *p) 匹配字符串p是否為雙運(yùn)算符 void match_single_operator(char *p) 匹配字符串p是否為單運(yùn)算符 void outfile()

5、將詞法分析所得的二元式按固定格式寫入文件out.dyd5、 實(shí)驗(yàn)器材(設(shè)備、元器件) C語言+windows7+CodeBlocks+gcc6、 實(shí)驗(yàn)步驟:1、將源程序保存到in.pas文件中;2、從in.pas文件中讀取字符串保存到buf數(shù)組,若整個(gè)輸入文件已讀取完畢,程序結(jié)束;3、每次從buf數(shù)組中讀入一個(gè)字符,若已讀到buf最后一個(gè)字符,返回第2步繼續(xù)執(zhí)行;3-a 如果該字符是字母或數(shù)字將其連接到temp字符串尾部,buf索引index加1,判斷bufindex是否為0,若為0說明temp字符串為一完整單詞,跳到第4步執(zhí)行;若不為0,繼續(xù)執(zhí)行第3步;3-b 如果讀入的不是字母/數(shù)字,首先

6、判斷并匹配temp中是否已出現(xiàn)保留字/標(biāo)識符,如果沒有,通過預(yù)讀buf中的下一個(gè)字符來進(jìn)一步判斷temp中存放的是單運(yùn)算符還是雙運(yùn)算符或換行符,最終寫入相應(yīng)二元式,返回第3步繼續(xù)執(zhí)行;4、判斷temp字符串是否為保留字,若不是保留字,進(jìn)一步判斷它是標(biāo)識符還是常量,最終生成相應(yīng)二元式,返回第3步繼續(xù)執(zhí)行;【注】 這里省略了對于非法字符的出錯(cuò)處理7、 實(shí)驗(yàn)數(shù)據(jù)及結(jié)果分析:1、 測試程序如圖,在測試程序中故意添加了一些詞法錯(cuò)誤如:將保留字寫成beg in,常數(shù)1kkk,符號 !=,用于檢測本實(shí)驗(yàn)程序的查錯(cuò)能力;2、 程序運(yùn)行完畢,得到out.dyd文件,內(nèi)容如圖所示:3、 報(bào)錯(cuò)文件error.err

7、內(nèi)容如圖:由上圖可以看出,本詞法分析程序,可以識別部分非法的常數(shù)以及字母表以外的非法字符,但對于將begin寫成beg in這一類的詞法錯(cuò)誤,并未做處理,而是將其放到語法分析的部分來處理。 8、 實(shí)驗(yàn)結(jié)論、心得體會和改進(jìn)建議:1、本詞法分析程序可以正確的按照給定的文法識別出源程序中的單詞符號及其對應(yīng)的種別并生成相應(yīng)的二元式文件,并具有一定的處理錯(cuò)誤信息的能力;2、由實(shí)驗(yàn)結(jié)果截圖可以看到,本實(shí)驗(yàn)僅能對一部分的詞法錯(cuò)誤作出響應(yīng),而一個(gè)完整的詞法分析程序還應(yīng)該能夠識別出如標(biāo)識符前綴為保留字等錯(cuò)誤,并且錯(cuò)誤信息文件.err中還應(yīng)該包括行號,所以還可以對本實(shí)驗(yàn)進(jìn)行改進(jìn);3、通過本次實(shí)驗(yàn),我設(shè)計(jì)并實(shí)現(xiàn)了一

8、個(gè)簡單的詞法分析器,在這個(gè)過程中加深了我對于詞法分析的原理及其過程的理解,而對于詞法錯(cuò)誤的處理也在一定程度上提高了我的編程能力。實(shí)驗(yàn)代碼如下:#include <stdio.h>#include <string.h>#include<stdlib.h>#define BEGIN 1#define END 2#define INTEGER 3#define IF 4#define THEN 5#define ELSE 6#define FUNCTION 7#define READ 8#define WRITE 9#define SYMBOL 10 /標(biāo)識符#d

9、efine CONSTANT 11 /常數(shù)#define EQ 12 /=#define NE 13 /<>#define LE 14 /<=#define LT 15 /<#define BE 16 />=#define BT 17 />#define SUB 18 /-#define MUL 19 /*#define ASSIGN 20 /:=#define LBRAC 21 /(#define RBRAC 22 /)#define SEM 23 /;#define BUFLEN 50#define TEMPLEN 2*BUFLENint type=0;

10、char valTEMPLEN;FILE *infile; /.pasFILE *outfile; /.dydFILE *errfile; /.errchar bufBUFLEN; /讀入緩沖區(qū)char tempTEMPLEN;char reserve2;/*判別是否字母*/int isletter(char c) if(c>='a')&&(c<='z')|(c>='A')&&(c<='Z') return 1; else return 0;/*判別是否數(shù)字*/int isd

11、igital(char c) if(c>='0'&&c<='9') return 1; return 0;/*匹配保留字*/int match_reserve(char *p) memset(val,0,TEMPLEN);if(!(strcmp(p,"begin") type=BEGIN; strcpy(val,"begin");to_outfile();return 1; else if(!(strcmp(p,"end") type=END;strcpy(val,"

12、;end");to_outfile();return 1; else if(!(strcmp(p,"integer") type=INTEGER;strcpy(val,"integer");to_outfile();return 1; else if(!(strcmp(p,"if") type=IF;strcpy(val,"if");to_outfile();return 1; else if(!(strcmp(p,"then") type=THEN;strcpy(val,"

13、then");to_outfile();return 1; else if(!(strcmp(p,"else") type=ELSE;strcpy(val,"else");to_outfile();return 1; else if(!(strcmp(p,"function") type=FUNCTION;strcpy(val,"function");to_outfile();return 1; else if(!(strcmp(p,"read") type=READ;strcpy(v

14、al,"read");to_outfile();return 1; else if(!(strcmp(p,"write") type=WRITE;strcpy(val,"write");to_outfile();return 1; elsereturn 0;/*匹配標(biāo)識符*/void match_symbol(const char *p,int len) /以字母開頭,是標(biāo)識符 if(isletter(p0) type=SYMBOL; strcpy(val,p);to_outfile(); / 不是以字母開頭的是常數(shù)else if(i

15、sdigital(p0) type=CONSTANT; strcpy(val,p); to_outfile(); int i; for (i=1;i<strlen(val);i+) if(isletter(vali) fprintf(errfile,"標(biāo)識符%s不正確n",val); break; / 不是以字母開頭也不是以數(shù)字開頭的報(bào)錯(cuò) elsestrcpy(val,p);to_outfile(); fprintf(errfile,"標(biāo)識符%s不正確n",val);/*匹配雙運(yùn)算符*/void match_double_operator(char

16、 *p)if(!(strcmp(p,":=") type=ASSIGN;strcpy(val,":=");to_outfile(); else if(!(strcmp(p,"<>") type=NE;strcpy(val,"<>");to_outfile(); else if(!(strcmp(p,"<=") type=LE;strcpy(val,"<=");to_outfile(); else if (!(strcmp(p,"&

17、gt;=") type=BE;strcpy(val,">=");to_outfile(); elsestrcpy(val,p);to_outfile(); fprintf(errfile,"運(yùn)算符%s不正確n",val);/*匹配單個(gè)運(yùn)算符*/void match_single_operator(char *p)if(!(strcmp(p,"<") type=LT;strcpy(val,"<");to_outfile(); else if(!(strcmp(p,">&qu

18、ot;) type=BT;strcpy(val,">");to_outfile(); else if(!(strcmp(p,"-") type=SUB;strcpy(val,"-");to_outfile(); else if(!(strcmp(p,"*") type=MUL;strcpy(val,"*");to_outfile(); else if(!(strcmp(p,"=") type=EQ;strcpy(val,"=");to_outfile

19、(); else if(!(strcmp(p,"(") type=LBRAC;strcpy(val,"(");to_outfile(); else if(!(strcmp(p,")") type=RBRAC;strcpy(val,")");to_outfile(); else if(!(strcmp(p,"") type=SEM;strcpy(val,"");to_outfile(); else if (!(strcmp(p," ") /如果是空格空操作

20、elsestrcpy(val,p);to_outfile(); fprintf(errfile,"運(yùn)算符%s不正確n",val);void to_outfile() fprintf(outfile,"%16s %02dn",val,type);int main(int argc,char *argv) int index=0; /指針指向緩存數(shù)組 int length=0; /非運(yùn)算符(標(biāo)識符)數(shù)組長度 memset(temp,0,TEMPLEN); if(infile=fopen("in.pas","r+")=N

21、ULL) /*打開in.pas*/ printf("Source file cannot be openedn"); exit(1); if(!(outfile=fopen("out.dyd","w+") /*打開out.dyd*/ printf("Destination file cannot be openedn"); exit(1); if(!(errfile=fopen("error.err","w+") /*打開error.err*/ printf("De

22、stination file cannot be openedn"); exit(1); /*讀字符串并判斷*/ while (!feof(infile) memset(buf,0,BUFLEN); index = 0; fgets(buf,BUFLEN,infile); printf("%s",buf); if(buf0=0)break; /*遍歷buf數(shù)組對讀入的字符逐個(gè)判斷*/while(index<BUFLEN)&&(bufindex!=0) memset(reserve,0,2); /*若讀入的是字母或數(shù)字*/if(isletter

23、(bufindex) = 1)|(isdigital(bufindex) = 1)length+;reserve0=bufindex;strcat(temp,reserve); /注意這里tail1=0 保證temp是完整字符串index+;if(bufindex=0) /*匹配保留字*/if(temp0!=0)int fm=match_reserve(temp); /*若不是保留字(fm=0),判斷是標(biāo)識符還是常量*/if(fm=0) match_symbol(temp,length); memset(temp,0,TEMPLEN); memset(reserve,0,2); length=

24、0; /*讀入的是運(yùn)算符or界符*/else /*首先判斷temp中是否已出現(xiàn)一個(gè)單詞*/if(temp0!=0)int fm=match_reserve(temp); /先判斷是否為保留字 if(fm=0) match_symbol(temp,length); memset(temp,0,TEMPLEN); /將temp,length和tail清零 length=0; /*是否為雙操作符 ':=' | '<=' | '>=' | '<>' */if(bufindex=':')&&a

25、mp;(bufindex+1='=')|(bufindex='<')&&(bufindex+1='=')|(bufindex='>')&&(bufindex+1='=')|(bufindex='<')&&(bufindex+1='>')reserve0=bufindex;reserve1=bufindex+1;match_double_operator(reserve);index += 2;/*如果是換行符寫入

26、EOLN 24*/else if (bufindex='n') fprintf(outfile," EOLN 24n"); index += 1; /*不是雙操作符,判斷是否為單操作符*/ elsereserve0=bufindex;match_single_operator(reserve);index+; memset(reserve,0,2); memset(buf,0,BUFLEN); /buffer清零 fprintf(outfile," EOF 25");return 0;電 子 科 技 大 學(xué)實(shí) 驗(yàn) 報(bào) 告實(shí)驗(yàn)二1、 實(shí)驗(yàn)名

27、稱:遞歸下降詞法分析器的設(shè)計(jì)與實(shí)現(xiàn)2、 實(shí)驗(yàn)學(xué)時(shí):43、 實(shí)驗(yàn)內(nèi)容和目的:實(shí)驗(yàn)內(nèi)容:根據(jù)給定的方法,編寫相應(yīng)的遞歸下降的語法分析程序,實(shí)現(xiàn)對詞法分析后的單詞序列的語法檢查和程序結(jié)構(gòu)的分析,生成相應(yīng)的變量名表和過程名表,并將編譯中語法檢查出來的錯(cuò)誤寫入相應(yīng)的文件。語法錯(cuò)分類: (1) 缺少符號錯(cuò); (2) 符號匹配錯(cuò) (3) 符號無定義或重復(fù)定義。 變量名表內(nèi)容:變量名vname: char(16)所屬過程vproc:char(16)分類vkind: 0.1(0變量、1形參)變量類型vtype: types變量層次vlev: int 變量在變量表中的位置vadr: int(相對第一個(gè)變量而言)過

28、程名表內(nèi)容:過程名pname: char(16)過程類型ptype: types過程層次plev: int 第一個(gè)變量在變量表中的位置fadr: int 最后一個(gè)變量在變量表中的位置ladr: int 實(shí)驗(yàn)?zāi)康模?通過設(shè)計(jì)并實(shí)現(xiàn)一個(gè)遞歸下降語法分析器,了解和掌握語法分析程序設(shè)計(jì)的原理及相應(yīng)的程序設(shè)計(jì)方法,同時(shí)提高編程能力。4、 實(shí)驗(yàn)原理:1、語法分析是對源程序經(jīng)過詞法分析后轉(zhuǎn)換成的單詞流按方法規(guī)則進(jìn)行判斷,對能構(gòu)成正確句子的單詞流,給出相應(yīng)的語法樹;對不能構(gòu)成正確句子的單詞流判斷其語法錯(cuò)誤并做出相應(yīng)處理。2、語法分析方法有自上而下和自下而上的分析方法。在不含左遞歸的文法G中,如果對每一個(gè)非終結(jié)

29、符的所有候選式的第一個(gè)終結(jié)符都是兩兩不相交的(即無公共左因子),則可能構(gòu)造出一個(gè)不帶回溯的自上而下的分析程序,這個(gè)分析程序由一組遞歸過程組成,每個(gè)過程對應(yīng)文法的一個(gè)非終結(jié)符。這樣的分析程序稱為遞歸下降分析程序。要使用遞歸下降分析法,我們必須先消除文法的左遞歸和提取公共左因子,消除左遞歸的方法如圖:4、 本實(shí)驗(yàn)中程序語言的文法如下: <程序><分程序><分程序>begin <說明語句表>;<執(zhí)行語句表> end<說明語句表><說明語句><說明語句表> ;<說明語句><說明語句>

30、<變量說明><函數(shù)說明><變量說明>integer <變量><變量><標(biāo)識符><標(biāo)識符><字母><標(biāo)識符><字母> <標(biāo)識符><數(shù)字><字母>abcdefghijklmnopqrstuvwxyz <數(shù)字>0123456789<函數(shù)說明>integer function <標(biāo)識符>(<參數(shù)>);<函數(shù)體><參數(shù)><變量><函數(shù)體>begin <

31、;說明語句表>;<執(zhí)行語句表> end<執(zhí)行語句表><執(zhí)行語句><執(zhí)行語句表>;<執(zhí)行語句><執(zhí)行語句><讀語句><寫語句><賦值語句><條件語句><讀語句>read(<變量>)<寫語句>write(<變量>)<賦值語句><變量>:=<算術(shù)表達(dá)式><算術(shù)表達(dá)式><算術(shù)表達(dá)式>-<項(xiàng)><項(xiàng)><項(xiàng)><項(xiàng)>*<因子&

32、gt;<因子><因子><變量><常數(shù)><函數(shù)調(diào)用><常數(shù)><無符號整數(shù)><無符號整數(shù)><數(shù)字><無符號整數(shù)><數(shù)字><條件語句>if<條件表達(dá)式>then<執(zhí)行語句>else <執(zhí)行語句><條件表達(dá)式><算術(shù)表達(dá)式><關(guān)系運(yùn)算符><算術(shù)表達(dá)式><關(guān)系運(yùn)算符> <<=>>=<>5、 本程序所設(shè)計(jì)的主要數(shù)據(jù)結(jié)構(gòu)及方法如下:方法

33、: void addVar(char var_name) 添加變量到變量名表,若變量重復(fù)定義則報(bào)錯(cuò); void addProc(char proc_name) 添加過程到過程名表; int findVar(char var_name) 查找變量名表中變量是否已存在,主要用于查重; int findProc(char proc_name) 查找過程名表中過程是否已存在; void advance() 從out.dyd中讀取一行獲取一個(gè)單詞符號及其種別; void error(int type) 向error.err文件中寫入對應(yīng)的報(bào)錯(cuò)信息; void S() 代表 <程序>begin

34、 <說明語句表>;<執(zhí)行語句表> end 中的<程序> void A() <說明語句表> void A_STAR() <說明語句表><說明語句><說明語句表> ;<說明語句>消除左遞歸后出現(xiàn)的A*,即<說明語句表*>; int C() <說明語句>;void H() <標(biāo)識符>void E() <函數(shù)體>void B() <執(zhí)行語句表>void Z() <執(zhí)行語句>void J() <算術(shù)表達(dá)式>void X() &

35、lt;項(xiàng)>void Y() <因子>void K() <條件表達(dá)式>void P() <關(guān)系運(yùn)算符>int main() 主函數(shù)還有X_STAR()、B_STAR()與J_STAR()都是對應(yīng)的文法消除左遞歸以后新出現(xiàn)的非終極符數(shù)據(jù)結(jié)構(gòu):struct variable var_table10; /變量名表struct procedure proc_table10; /過程名表struct variable /變量結(jié)構(gòu)體 char vname16; char vtype10; int vadr; char vproc16; int vlev; ;stru

36、ct procedure /過程結(jié)構(gòu)體 char pname16; char ptype10; int plev,fadr,ladr; ;5、 實(shí)驗(yàn)器材(設(shè)備、元器件)C語言+windows7+CodeBlocks+gcc6、 實(shí)驗(yàn)步驟:1、 化簡、提取公共左因子和消除左遞歸后的文法如下:<程序>begin <說明語句表>;<執(zhí)行語句表> end<說明語句表><說明語句><說明語句表*> /消除左遞歸<說明語句表*>;<說明語句><說明語句表*>|<說明語句>integer&

37、lt;標(biāo)識符或函數(shù)體> /提取公共左因子<標(biāo)識符或函數(shù)體><標(biāo)識符>function <標(biāo)識符>(<標(biāo)識符>);<函數(shù)體><函數(shù)體>begin <說明語句表>;<執(zhí)行語句表> end<執(zhí)行語句表><執(zhí)行語句><執(zhí)行語句表*> /消除左遞歸<執(zhí)行語句表*>;<執(zhí)行語句><執(zhí)行語句表*>|<執(zhí)行語句>read(<標(biāo)識符>)write(<標(biāo)識符>)<標(biāo)識符>:=<算術(shù)表達(dá)式&

38、gt;if<條件表達(dá)式>then<執(zhí)行語句>else <執(zhí)行語句><算術(shù)表達(dá)式><算術(shù)表達(dá)式>-<項(xiàng)><項(xiàng)><項(xiàng)><因子><項(xiàng)*> /消除左遞歸<項(xiàng)*>*<因子><項(xiàng)*>|<因子><標(biāo)識符><常數(shù)><函數(shù)調(diào)用><常數(shù)><數(shù)字><無符號整數(shù)><數(shù)字><條件表達(dá)式><算術(shù)表達(dá)式><關(guān)系運(yùn)算符><算術(shù)表達(dá)式&g

39、t;<關(guān)系運(yùn)算符> <<=>>=<>【注】 由于標(biāo)識符可由詞法分析階段得到的二元式判斷,所以在文法中將其推導(dǎo)省略2、 用簡單的英文字符替換中文后得文法如下:<S>begin <A>;<B> end<A><C><A*> <A*>;<C><A*>|<C>integer <H><H><I>integer function <I>(<I>);<E><I>

40、<L><I*> <I*><G><I*>|<G><E>begin <A>;<B> end<B><Z><B*> <B*>;<Z><B*>|<Z><Z>read(<I>)write(<I>)<I>:=<J>if<K>then<Z>else <Z><J><X><J*> <J*&

41、gt; -<X><J*>|<X><Y><X*> <X*>|*<Y><X*><Y><I><O><G><K><J><P><J><P><<=>>=<>3、 程序主要流程:從out.dyd中讀取待匹配的單詞符號保存到sym中,用構(gòu)造的遞歸下降分析器匹配該單詞符號,若匹配成功,繼續(xù)讀取下一單詞符號;若匹配失敗,向錯(cuò)誤文件error.err中寫入相應(yīng)的出錯(cuò)信息,繼續(xù)讀取

42、下一單詞符號,直到所有未匹配符號皆處理完畢。7、 實(shí)驗(yàn)數(shù)據(jù)及結(jié)果分析:1、 測試程序如圖所示,所包含的語法錯(cuò)誤有:錯(cuò)誤的保留字integr和beginnnnn,重復(fù)定義的標(biāo)識符k,不匹配的括號read(m;,以及最后一行缺少了end關(guān)鍵字;2、 錯(cuò)誤信息文件error.err的內(nèi)容如圖:由上圖可以看到測試程序中的5處錯(cuò)誤都正確的識別出來,并且雖然源測試程序的第3行和第6行的都是integer k;但語法分析程序并沒有報(bào)重復(fù)定義的錯(cuò),說明本實(shí)驗(yàn)程序還可以識別不同層次的重復(fù)定義。本實(shí)驗(yàn)程序把F和m也當(dāng)做未定義的變量,這里我個(gè)人認(rèn)為按照慣例F和m還是應(yīng)該定義一下,直接拿來使用不符合我們一般的編程習(xí)慣

43、,但是error.err的8、9、11、12行對于已經(jīng)報(bào)過錯(cuò)的變量F 和m又報(bào)了一次未定義錯(cuò)誤,感覺有一些啰嗦,可以改進(jìn)一下本程序讓它不要重復(fù)報(bào)錯(cuò)。8、 實(shí)驗(yàn)結(jié)論、心得體會和改進(jìn)建議:1、 一開始本實(shí)驗(yàn)程序?qū)τ谌鄙俜痔柕腻e(cuò)誤不能正確處理,這個(gè)問題一直困擾著我,后來我發(fā)現(xiàn)這是由于文法<程序>begin <說明語句表>;<執(zhí)行語句表> end 中當(dāng)說明語句表只有一條說明語句時(shí),遞歸下降分析器并不能判定這條說明語句的接下來的一條語句到底是一條執(zhí)行語句還是仍然是一條說明語句,所以在函數(shù)體A_STAR中需要增加一段程序判斷一下下一條語句是不是執(zhí)行語句,若是執(zhí)行語句,由

44、于當(dāng)只有一個(gè)說明語句時(shí),執(zhí)行語句之前的那個(gè)分號已經(jīng)被說明語句表匹配,所以這是需要回退一步(back),sym重新取一次分號,讓執(zhí)行語句表之前的分號得以匹配; 2、本實(shí)驗(yàn)中的過程表不是很完整,我只處理了過程名以及其對應(yīng)的層次和類型,對于實(shí)驗(yàn)中要求的fadr,ladr并未做相應(yīng)處理,這點(diǎn)值得改進(jìn);3、如果把第2行或第7行的integer改為integr,將會使得程序由于無法判斷這條語句到底是說明語句還是執(zhí)行語句而無法正確執(zhí)行,其實(shí)這個(gè)問題還是出在說明語句表和執(zhí)行語句表之間的界限不清楚,我現(xiàn)在還沒有想出一個(gè)很好的方法來解決這個(gè)問題;4、 實(shí)驗(yàn)一開始的時(shí)候我根本不知道語法分析應(yīng)該報(bào)哪些錯(cuò),對于詞法分析

45、應(yīng)不應(yīng)該報(bào)錯(cuò)也不了解,但是通過第13周的實(shí)驗(yàn)程序的檢查和自己慢慢的調(diào)試,我逐漸加深了對于詞法分析、語法分析的過程的理解,雖然這個(gè)程序的功能也不是很完善,但是自己動(dòng)手編寫遞歸下降分析器的這個(gè)過程確實(shí)使我對于編譯的原理有了更深入的掌握;實(shí)驗(yàn)代碼如下:#include <stdio.h>#include <stdlib.h>#include <string.h>#define MISSINGSEM 1 /缺少分號錯(cuò)誤#define MISSINGEND 2 /缺少end#define MISSINGBEGIN 3 /缺少begin#define MISSINGTY

46、PE 4 /缺少類型定義#define MISSINGRBRAC 5 /缺少右括號#define MISSINGLBRAC 6 /缺少左括號#define MISSINGPARA 7 /缺少參數(shù)#define MISSINGFUCNAME 8/缺少函數(shù)名稱#define MISSINGFUC 9 /缺少function關(guān)鍵字#define MISSINGOP 10 /缺少操作符#define MISSINGELSE 11 /缺少else#define MISSINGTHEN 12 /缺少then#define MISSINGVAR 13 /缺少變量名#define UndefinedVar 1

47、4 /變量未定義#define RepeatDefine 15 /變量重復(fù)定義FILE *infile;FILE *errfile;char *t;char sym16;int id;int lineNum = 1;int var_len= 0;int proc_len = 0;int level = 0;/*變量名表*/struct variable char vname16; char vtype10; /ints int vadr; /char vproc16; int vlev; ;/*過程名表*/struct procedure char pname16; char ptype10;

48、 / int plev,fadr,ladr; ;struct variable var_table10;struct procedure proc_table10;/*添加變量到變量名表*/void addVar(char var_name16) if (findVar(var_name) error(RepeatDefine); else printf(" 添加到變量名表%sn",var_name); strcpy(var_tablevar_len.vname,var_name); strcpy(var_tablevar_len.vtype,"integer&q

49、uot;); var_tablevar_len.vlev = level; var_tablevar_len.vadr = 4*var_len; var_len+; /*添加過程到過程名表*/void addProc(char proc_name16) printf(" 添加到過程名表%sn",proc_name); strcpy(proc_tableproc_len.pname,proc_name); strcpy(proc_tableproc_len.ptype,"integer"); proc_len+;/*在變量名表中查找變量是否存在*/int

50、findVar(char var_name16) printf("查找變量%s n",var_name); int finded = 0,i = 0; for (i = 0;i < var_len+1;i+) if (!strcmp(var_tablei.vname,var_name)&&(var_tablei.vlev=level) finded = 1; printf("var_tablei.vname %sn",var_tablei.vname); break; if (!finded) printf("沒找到!n&

51、quot;); return finded;/*在過程名表中查找過程是否存在*/int findProc(char proc_name16) int finded = 0,i = 0; for (i = 0;i < proc_len+1;i+) if (!strcmp(proc_tablei.pname,proc_name) finded = 1; break; return finded;/*if id = 25 文件讀取完畢!*/void advance() char line21; if(!feof(infile) fgets(line,21,infile); line 19 =

52、'0' /去掉換行符n char *buf = line; t = strtok(buf," "); /使用strtok進(jìn)行字符串分割 buf = NULL; id = atoi(strtok(buf," "); strcpy(sym,t); printf("line%d: sym=%s,id=%dn",lineNum,sym,id); if (id = 24) /如遇到EOLN,行號+1繼續(xù)讀取下一個(gè)字符串 lineNum+; advance(); void back() printf("back!n&qu

53、ot;); fseek(infile,-60,1); lineNum -; advance();void error(int type) switch(type) case 1: fprintf(errfile,"LINE %02d: missing '' here. n",lineNum);break; case 2: fprintf(errfile,"LINE %02d: missing 'end' here. n",lineNum);break; case 3: fprintf(errfile,"LINE %02d: missing 'begin' here. n",lineNum);break; case 4: fprintf(errfile,"LINE %02d: 缺少類型定義關(guān)鍵字,%s不是保留字n",lineNum,sym);break; case 5: fprintf(errfile,"LINE %02d: missing ')'

溫馨提示

  • 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)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論