詞法分析程序+語(yǔ)法語(yǔ)義分析四元式生成+實(shí)驗(yàn)報(bào)告記錄_第1頁(yè)
詞法分析程序+語(yǔ)法語(yǔ)義分析四元式生成+實(shí)驗(yàn)報(bào)告記錄_第2頁(yè)
詞法分析程序+語(yǔ)法語(yǔ)義分析四元式生成+實(shí)驗(yàn)報(bào)告記錄_第3頁(yè)
詞法分析程序+語(yǔ)法語(yǔ)義分析四元式生成+實(shí)驗(yàn)報(bào)告記錄_第4頁(yè)
詞法分析程序+語(yǔ)法語(yǔ)義分析四元式生成+實(shí)驗(yàn)報(bào)告記錄_第5頁(yè)
已閱讀5頁(yè),還剩51頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、詞法分析程序+語(yǔ)法語(yǔ)義分析四元式生成+實(shí)驗(yàn)報(bào)告記錄作者:日期:#編譯原理實(shí)驗(yàn)報(bào)告本文檔集合了編譯原理大作業(yè)的實(shí)驗(yàn)報(bào)告加代碼實(shí)驗(yàn)主要內(nèi)容為用C+實(shí)現(xiàn)了詞法分析程序;語(yǔ)法語(yǔ)義以及四元式生成程序代碼見(jiàn)附錄,復(fù)制進(jìn)VS后程序絕對(duì)可編譯執(zhí)行。文檔代碼為原創(chuàng),謹(jǐn)慎使用(姚礪的大作業(yè))3實(shí)驗(yàn)設(shè)計(jì)一、實(shí)驗(yàn)名稱(chēng)詞法分析程序二、實(shí)驗(yàn)?zāi)康?1) 設(shè)計(jì)一個(gè)詞法分析程序,每調(diào)用一次就從源程序文件中順序識(shí)別出一個(gè)單詞符號(hào),并返回 該單詞符號(hào)的內(nèi)部編碼、單詞符號(hào)自身、行列位置信息。(2) 要能處理單行注釋。三、實(shí)驗(yàn)內(nèi)容及要求單詞種類(lèi)與識(shí)別規(guī)則(1) 標(biāo)識(shí)符:首字符為字母或下劃線,其后由字母、數(shù)字或下劃線組成、長(zhǎng)度不超過(guò)25

2、5個(gè)字符;(2) 整數(shù):由1到8個(gè)數(shù)字組成。(3) 小數(shù):數(shù)字串1 .數(shù)字串2,其中:數(shù)字串1由1-8個(gè)數(shù)字符組成;數(shù)字串2由0-8個(gè)數(shù)字符組成,即:數(shù)字串2可以為空。(4) 字符串:由一對(duì)“”括起來(lái)的符號(hào)串,長(zhǎng)度不超過(guò)255個(gè)字符;(5) 保留字:if、else while、do、in teger、float、stri ng、in put、output、and、or、function、end、def、as、beg in(6) 數(shù)學(xué)運(yùn)算符: +、*、/、=(7) 比較運(yùn)算符: 、=、=、=(8) 邏輯運(yùn)算符:and、or(9) 分隔符:、(、)、;、,四、實(shí)驗(yàn)環(huán)境操作系統(tǒng):Win7/其他編譯工

3、具:VC+6.0/ CFree /VS2012五、設(shè)計(jì)1設(shè)計(jì)大體思路將讀取的文件采用一遍掃描的方法,即從左到右只掃描一次源程序,將讀取的數(shù)據(jù)存放在一個(gè)二維 數(shù)組里。然后通過(guò)掃描函數(shù) sea n,再?gòu)臄?shù)組中一行一行的讀取數(shù)據(jù),每調(diào)用其依次返回一個(gè)單詞的 類(lèi)型,同時(shí)單詞本身以及行列號(hào)存放在全局變量中。而說(shuō)詞法分析作為語(yǔ)法分析的一個(gè)子程序,故 在編寫(xiě)詞法分析程序時(shí),將會(huì)反復(fù)調(diào)用scan函數(shù)來(lái)獲取一個(gè)個(gè)單詞信息。53設(shè)計(jì)流程圖1 1-3 r -和忙訂 j Jj ij !-j%' j- r. Jr4函數(shù)設(shè)計(jì)/*詞法分析函數(shù)*/int sea n( stri ng s ,int line )框架:

4、初始化工作是空格直接跳過(guò),知直到讀取到一個(gè)字符if(是字母)查表判斷是否為關(guān)鍵字判斷是否為邏輯運(yùn)算符and或orElse則為標(biāo)識(shí)符else if( 是否為數(shù)字 )判斷是整數(shù)Else是小數(shù)Else其余情況判斷是否為運(yùn)算符,字符串等else if( getehar= ' / 'if( contentlinei+1='/')向前看一個(gè),確定是否為行注釋;如果是,則游標(biāo)指向行末,跳過(guò)行注釋if( co nte ntli nei+1='/*')如果向前看一個(gè)發(fā)現(xiàn)時(shí)塊注釋則一直向前掃描直到出現(xiàn)“*/”停止,略過(guò)塊注釋如果都不是則Else判斷為除號(hào),返回運(yùn)算符

5、類(lèi)型2對(duì)其中部分實(shí)現(xiàn)的說(shuō)明(1)數(shù)字識(shí)別while (contentlinei>='O' && contentlinei<=9 )/ 判斷是否為數(shù)字text += conten tli nei;i+;flag=1;if ( flag=1 )if ( contentlinei='.')text += conten tli nei;i+;/判斷是否while ( contentlinei>='0' && contentlinei<=9 )11#為數(shù)字#return 3;/ 小數(shù)每讀入一個(gè)字符,判

6、斷是否數(shù)字,然后找小數(shù)點(diǎn),找到即為小數(shù)(2)標(biāo)識(shí)符處理/判斷是否while ( (contentlinei>=65 && contentlinei<=90) | (contentlinei>=91 && contentlinei<=122) | contentlinei>='O' && contentlinei<=9 )為數(shù)字或者字母或者下劃線text += conten tli nei;i+;for ( j=0; j<=13 ; j+ )if ( text=keyj)/查表判斷是否為保留

7、字return 5;檢查到讀取的字符為字母時(shí),進(jìn)行查表判斷,找到即說(shuō)明為關(guān)鍵字空格,注釋?zhuān)刑?hào)的處理if( mode=0 )if( i<co nte ntke ngth() ) i+;/如果為行注釋直接跳到下一行elseif( mode=-1 )/如果為塊注釋找回行號(hào)k=templi ne;六、程序源代碼見(jiàn)源代碼文件。七、實(shí)驗(yàn)數(shù)據(jù)、結(jié)果測(cè)試數(shù)據(jù)見(jiàn)文件湄試數(shù)據(jù)如下;functionIregfintenp3 til;此處變量春定義就使用def temple tunp2 as float此處少分號(hào)input tempi,temp2:def tenpl as float; /*此處變量重復(fù)定義*

8、/tenpl = 123;empl = tempi + tenp2; if tempi >= tenp2begintempi 123;+ 4*2;end else begin tempi endcnidend function數(shù)數(shù)數(shù)數(shù)感IW皺IWIB眾 列-1 4<2 果 11112 3 3 3 3 4 A 士口 - 8 I 婁戮蓼婁謝費(fèi)婁 丁-T!- r-T-r - TJ- _J-T1-T' 為mtts列JMll119 9 3 9 1 s s 1 6 50 3 4013 3 11114 2 8 119-1 funct ion g: aaa單詞為:<單乎|應(yīng):hejg

9、in 單詞為;tempS勺:def八、總結(jié)之前的每周作業(yè)曾經(jīng)寫(xiě)過(guò)一個(gè)詞法分析程序,所以這次寫(xiě)詞法分析程序沒(méi)什么太多困難。在讀取源文件時(shí),最初的想法是一行一行的讀取,讀一次就存一行,這樣可以節(jié)省空間資源,提高效 率。但是仔細(xì)一想考慮到塊注釋分布在不同的行中,而且這樣對(duì)行列的操作十分麻煩,而且許多地方 涉及到要向前看,(比如判斷注釋與/除號(hào)運(yùn)算符時(shí)),最后只好一次全部讀完,存在一個(gè)二維數(shù)組中。 再用scan函數(shù)來(lái)處理。這樣一來(lái)行列的處理就自由多了。第二點(diǎn),在寫(xiě)scan函數(shù)的時(shí)候,最初的想法是每調(diào)用一次,返回一個(gè)單詞,然后在語(yǔ)法分析時(shí) 不斷調(diào)用它。但是僅僅返回單詞是不夠的,于是打算返回一個(gè)結(jié)構(gòu)體,把

10、單詞信息行列號(hào)什么的全部 存進(jìn)去,這個(gè)在后來(lái)的語(yǔ)法語(yǔ)義分析中可以看到,這里任然采用的是返回一個(gè)單詞類(lèi)型。單詞本身, 和行列號(hào)作為全局變量保存。然后只要按照流程圖一步一步判斷,慢慢寫(xiě)就行了,沒(méi)有太多難度,唯一要注意的是單詞位置行列的計(jì)算一定要細(xì)心。這個(gè)是要穿插在整個(gè)詞法分析的全部地方的。 所有涉及到讀入一個(gè)字符的地 方都需要考慮到如何修改行列變量。尤其是本程序拓展了塊注釋?zhuān)⒁庑辛凶兓?3實(shí)驗(yàn)設(shè)計(jì)二注:由于語(yǔ)義分析和四元式生成都是在語(yǔ)法分析的基礎(chǔ)上拓展得到的,這一章實(shí)驗(yàn)報(bào) 告囊括了語(yǔ)法,語(yǔ)義和四元式。一、實(shí)驗(yàn)名稱(chēng)語(yǔ)法語(yǔ)義以及四元式分析程序二、實(shí)驗(yàn)?zāi)康脑O(shè)計(jì)一個(gè)語(yǔ)法語(yǔ)義以及生成四元式的分析程序三

11、、實(shí)驗(yàn)內(nèi)容及要求設(shè)計(jì)要求:構(gòu)造相應(yīng)文法的語(yǔ)法分析程序,應(yīng)能指出源程序中出現(xiàn)的錯(cuò)誤。為語(yǔ)法分析程序中添加類(lèi)型檢查功能,包括:變量重復(fù)定義;15 變量未定義就使用; 變量未賦值就引用;將語(yǔ)法正確的源程序翻譯成四元式。文法見(jiàn)附錄四、實(shí)驗(yàn)環(huán)境操作系統(tǒng):Win7/其他編譯工具:VC+6.0/ CFree /VS2012五、設(shè)計(jì)1語(yǔ)法分析設(shè)計(jì)(1) 相關(guān)數(shù)據(jù)機(jī)構(gòu)struct Toke n Istri ng value; /值intmode;/類(lèi)型introw;/行intcol;/列toke n;說(shuō)明:這本應(yīng)是詞法分析時(shí)的結(jié)構(gòu),但是scan函數(shù)返回的是但單一值,于是又設(shè)計(jì)了Token函數(shù),對(duì)scan函數(shù)進(jìn)行

12、擴(kuò)充,每個(gè)單詞的信息均保存一次在結(jié)構(gòu)體中,方便錯(cuò)誤報(bào)告函數(shù)進(jìn)行處理。(2) 各個(gè)非終結(jié)符函數(shù)形式/*/*語(yǔ)法語(yǔ)義 各產(chǎn)生式 函數(shù)*/void chengxu();void hanshukuai();void bianliangdingyiyuju();void shujuleixing();void shuruyuju();void shuchuyuju();void fuzhiyuju();void fenzhiyuju();void xunhuanyuju();void biaodashi();void xiang();void yinzi();void buerbiaodashi();v

13、oid guanxibiaodashi();void guanxi();其他函數(shù):void error();void warning();每個(gè)函數(shù)具體作用在代碼中都有注釋說(shuō)明(3) 語(yǔ)法分析整體設(shè)計(jì)思路采用遞歸下降的方法,為每個(gè)非終結(jié)符設(shè)計(jì)一個(gè)函數(shù),在函數(shù)中對(duì)此處可能出現(xiàn)的語(yǔ) 法錯(cuò)誤進(jìn)行處理。處理也語(yǔ)法錯(cuò)誤的思路主要分兩種:1. 查找關(guān)鍵字由于進(jìn)行語(yǔ)法分析時(shí)檢查到錯(cuò)誤不可能就此停下,要一次性盡量找到所有的錯(cuò)誤,而且測(cè)試數(shù)據(jù)的語(yǔ)法錯(cuò)誤形式千奇百怪,這就要求發(fā)現(xiàn)錯(cuò)誤之后如何找到繼續(xù)進(jìn)行 分析的位置。這里對(duì)于一些不常見(jiàn)的錯(cuò)誤采取查找關(guān)鍵字的方法,一旦出現(xiàn)錯(cuò)誤在 相應(yīng)函數(shù)中查找下一個(gè)出現(xiàn)的關(guān)鍵字的位置

14、,然后繼續(xù)分析。2. 跳過(guò)錯(cuò)誤單詞,直接分析下一個(gè)單詞由于查找關(guān)鍵字方法會(huì)跳過(guò)許多代碼,從而有可能造成一些信息不必要的遺漏。尤 其是對(duì)于漏分號(hào)這種錯(cuò)誤,與是這里采取,直接當(dāng)前錯(cuò)誤,默認(rèn)后續(xù)單詞可能就是 正確單詞,繼續(xù)分析。但是這個(gè)方法在一些地方并不適用,可能會(huì)導(dǎo)致一連串的錯(cuò)誤出現(xiàn),于是在使用時(shí)要考慮好取舍編譯錯(cuò)誤處理函數(shù):void error( Token token , char * msg/ 編譯錯(cuò)誤處理函數(shù) |cout << "編譯錯(cuò)誤:”;printf( "%s", msg; cout << endl <<"錯(cuò)

15、誤位置:第"<< token .row<< "行,第"<< token .col <<"列-> "<< token.value;cout << en dl;cout << en dl;error nu m+;每出現(xiàn)錯(cuò)誤時(shí),通過(guò)傳遞錯(cuò)誤信息參數(shù)以及單詞信息,調(diào)用編譯錯(cuò)誤處理函數(shù)進(jìn)行實(shí) 時(shí)報(bào)錯(cuò)。(3) 測(cè)試數(shù)據(jù)和結(jié)果見(jiàn)后文語(yǔ)義分析部分(4) 語(yǔ)法分析部分的小總結(jié)原本打算試試自底向上歸約方法設(shè)計(jì)的,結(jié)果想了想發(fā)現(xiàn)實(shí)在麻煩,老師給的文法又 挺龐雜的,創(chuàng)建分析表什么

16、的就要好久。后來(lái)一想用遞歸下降方法好處很多,做到之 后的語(yǔ)義分析和四元式生成的時(shí)候在語(yǔ)法分析的基礎(chǔ)上拓展很方便,整體框架非常清 晰。在錯(cuò)誤處理方面考慮的還是挺合理的,對(duì)于一些常見(jiàn)錯(cuò)誤都能有效指出。并且程 序只有一個(gè)出口,任何代碼輸入都會(huì)從那一個(gè)出口結(jié)束,不會(huì)引起程序崩潰。2、語(yǔ)義分析設(shè)計(jì)語(yǔ)義分析主要實(shí)現(xiàn)3個(gè)功能 變量重復(fù)定義; 變量未定義就使用; 變量未賦值就引用;(1) 相關(guān)數(shù)據(jù)結(jié)構(gòu)struct Symtable / 符號(hào)表結(jié)構(gòu)stri ng n ame;int type;bool value;S;structcompare: binary_function vSymtable, strin

17、g , bool > /仿函數(shù)和綁定器bool operator()( Symtable s, stringstr ) constif ( = str )return true ;elsereturn false ;相關(guān)函數(shù)void push_in_token(Token token )/ 進(jìn)表操作S.name = token .value;S.type = -1;S.value = false ;ST.push_back( S );vector <Symtable> : iterator find_token( Token token )/查表操作it = fi

18、nd_if( ST.begin(), ST.end(), bind2nd(compare(), token .value );return it;(2) 測(cè)試數(shù)據(jù)和結(jié)果(4)設(shè)計(jì)思路語(yǔ)義部分主要采用符號(hào)表結(jié)構(gòu),符號(hào)表中記錄了每個(gè)非終結(jié)符的信息。(名稱(chēng),類(lèi)型,是否賦值)。然后再程序中每次調(diào)用 Token函數(shù)發(fā)現(xiàn)讀取到標(biāo)識(shí)符時(shí)都進(jìn)行查表操作。 根據(jù)查表結(jié)果進(jìn)行相關(guān)分析。在賦值函數(shù)中,如果查表找到其信息就說(shuō)明重復(fù)定義。再其余函數(shù)中1沒(méi)有找到說(shuō)明為聲明就使用。2找到發(fā)現(xiàn)未賦值說(shuō)明未賦值就引用。(5)語(yǔ)義部分小總結(jié)假如只實(shí)現(xiàn)以上3個(gè)功能語(yǔ)義部分并不難,關(guān)鍵是符號(hào)表的構(gòu)建以及進(jìn)表查表等操作。 在這一部分我

19、使用了仿函數(shù)和綁定器進(jìn)行查表。由于我把相應(yīng)表結(jié)構(gòu)都存在 vector內(nèi),導(dǎo)致查找結(jié)構(gòu)內(nèi)成員信息的不便,但是自己寫(xiě)一套查找操作代碼估計(jì)效率不高,索性 使用仿函數(shù)進(jìn)行查找,泛型操作一般效率較高而且代碼較少也很清晰。假如時(shí)間更充 足一點(diǎn)其實(shí)還可以把數(shù)據(jù)類(lèi)型匹配這一部分拓展一下,畢竟也是查表比較,但是時(shí)間 有限只好先完成要求的3個(gè)任務(wù)。3、四元式分析設(shè)計(jì)(1)相關(guān)數(shù)據(jù)結(jié)構(gòu)struct Quaternary / 四元式結(jié)構(gòu)int serial;string op;stri ng v1;string v2;stri ng result;Q;stack <string > operator_st

20、ack;/操作數(shù)堆棧stack <string > operand_stack;/ 操作符堆棧(2)相關(guān)函數(shù)result )Quaternary Quaternary_generater(int serial , string op, string v1, string v2, string/四元式生成函數(shù)Q.serial = serialQ.op = op;Q.v1 = v1;Q.v2 = v2;Q.result = result return Q;while ( !operand_stack.empty() && !operator_stack.empty()

21、25op = operator_stack.top();operator_stack.pop();v1 = opera nd_stack.top();opera nd_stack.pop();v2 = opera nd_stack.top();opera nd_stack.pop();res = resultr;r+;Q = Quater nary_ge nerater( serial, op, v1, v2, res );serial+;QV.push_back( Q );/for ( it2=QV.begin(); it2!=QV.end(); it2+ )/ 找回真出口if ( (*it

22、2).result= "null")stri ngstream ss;ss«QV.back().serial;stri ng s=ss.str();(*it2).result=s;break;/opera nd_stack.push( res ); _void Quaternary_output() _while ( !QV.empty() cout << QV.fr on t().serial <<"("<< QV.fro nt().op <<<< QV.fro nt().v2 &l

23、t;<II")"<< endl;"<< QV.fro nt().v1 <<" , "<< QV.fro nt().result <<it2 = QV.begi n();QV.erase( it2 );(3) 測(cè)試數(shù)據(jù)和結(jié)果四兀式如下:1 < / ,2 , 4 , tl )2 < + ,itl . t2 )3 < + ,t2 , 3 , t34 < =,a , t3 , 14 >5 C + ,b , a , t5 >6 < =,bt5t6

24、)7 C >=,a , h , 9 )9 < J ,-,-,10)9 < -,a 亠 123 , t7 >10 ( -*a . 1 , te )11 < *j. a j- b j- ±912 < -,ts ,f tin >13 < -,b . tie ,>(4) 設(shè)計(jì)思路賦值運(yùn)算部分整體結(jié)構(gòu)流程如下:#* '"-"ETr 工右孤ng衛(wèi)結(jié)束,說(shuō)明:首先建立操作符棧和運(yùn)算符棧。每次掃描遇到操作符遍進(jìn)棧,遇到運(yùn)算符如果當(dāng)前??談t進(jìn)棧,否則和棧頂操作符的優(yōu)先級(jí)進(jìn)行比較,如果小于等于其優(yōu)先級(jí),則pop棧頂符號(hào),進(jìn)

25、行四元式生成,再將四元式壓入四元式隊(duì)列,然后繼續(xù)與棧頂元素比較直 至其優(yōu)先級(jí)大于其優(yōu)先級(jí)或??談t進(jìn)棧。If語(yǔ)句部分在對(duì)布爾表達(dá)式進(jìn)行判斷時(shí),先讓操作符和運(yùn)算符進(jìn)棧,轉(zhuǎn)移序號(hào)先賦為null等到掃描到if then之后的部分通過(guò)對(duì)其四元式生成確定了序號(hào),這時(shí)候再查找隊(duì)列進(jìn) 行回填序號(hào)。xian g();while ( token.value="+" | token.value="-")/四元式while ( !operator_stack.empty() && operator_stack.top()!="=" )/ 此處

26、要注意用while循環(huán),if會(huì)出錯(cuò),因?yàn)樾枰粩嗯袛嘀敝翖m數(shù)姆?hào)優(yōu)先級(jí)小于需要壓棧的符號(hào)此處生成四元式,四元式進(jìn)隊(duì)列for ( it2=QV.begin(); it2!=QV.end(); it2+ )/ 找回真出口if ( (*it2).result= "null")stri ngstream ss;ss<<QV.back().serial; stri ngs=ss.str();(*it2).result=s;break; I/如果??栈蛘邷?zhǔn)備進(jìn)棧的operator_stack.push( toke n. value );符號(hào)的優(yōu)先級(jí)大于棧頂?shù)膬?yōu)先級(jí)則進(jìn)棧t

27、oke n = getToke n(); xia ng();(5)四元式的總結(jié):這部分是我覺(jué)得此次試驗(yàn)最難的一部分。而且也是我花費(fèi)時(shí)間最多的一部分。在寫(xiě)賦值運(yùn)算的那部分時(shí),把一個(gè)while循環(huán)寫(xiě)成了 if (我一開(kāi)始以為運(yùn)算符進(jìn)棧只需 判斷一次)導(dǎo)致測(cè)試數(shù)據(jù)結(jié)果出錯(cuò)找了好久錯(cuò)誤才找到。If語(yǔ)句那部分的四元式的編寫(xiě)也十分困難,尤其是找回真假出口讓我考慮了很久。而且測(cè)試數(shù)據(jù)整個(gè)代碼有許多 這種語(yǔ)句,應(yīng)當(dāng)在每個(gè)語(yǔ)句結(jié)束時(shí)就輸出一次四元式,不然會(huì)導(dǎo)致次序的混亂。(一開(kāi)始我沒(méi)發(fā)現(xiàn),是把所有四元式進(jìn)隊(duì)列到最后程序結(jié)束時(shí)一起輸出的),最后調(diào)試了許久, 才發(fā)現(xiàn)問(wèn)題,于是在語(yǔ)句結(jié)果判斷分號(hào)時(shí),就調(diào)用四元式輸出函

28、數(shù)進(jìn)行輸出。20六、整體總結(jié)這次編譯原理大作業(yè)讓真的我受益良多,整個(gè)近千行代碼基本都是我一點(diǎn)一點(diǎn)慢慢敲 出來(lái)的,過(guò)程固然辛苦但是學(xué)到了不少。尤其是在做語(yǔ)法分析和四元式生成的部分, 代碼量較大,一開(kāi)始思路也不太清晰,但是還是一點(diǎn)一點(diǎn)硬著頭皮往下寫(xiě),結(jié)果在寫(xiě) 的過(guò)程中一些思路就出來(lái)了,看來(lái)有時(shí)候還是要多動(dòng)手,光苦思冥想并不行。對(duì)于這 次作業(yè)我自己是比較滿(mǎn)意的但是還是有一些不足:語(yǔ)法部分本來(lái)想對(duì)文法進(jìn)行拓展把 布爾表達(dá)式那部分的附加題解決掉,無(wú)奈時(shí)間有限,實(shí)在來(lái)不及寫(xiě),可能留到暑假自 己再完善吧。四元式部分其實(shí)做得并不完完善,有些測(cè)試數(shù)據(jù)會(huì)出現(xiàn)錯(cuò)誤結(jié)果,主要 是還是因?yàn)椴紶柋磉_(dá)式那部分文法沒(méi)有拓展,

29、在進(jìn)行復(fù)雜布爾表達(dá)式判斷時(shí)會(huì)出錯(cuò), 而且if語(yǔ)句真假口如果遇到復(fù)雜的算數(shù)運(yùn)算可能會(huì)出口回填錯(cuò)誤??傮w來(lái)說(shuō),這次作 業(yè)基本任務(wù)還是都完成了,通過(guò)這次大作業(yè)也對(duì)整個(gè)編譯器的設(shè)計(jì)有了比以前更深的 了解和體會(huì),看來(lái)還是實(shí)踐才能出真知。29附錄文法如下:1. 程序 函數(shù)塊2. 函數(shù)塊 函數(shù) 函數(shù)3. 函數(shù) functionid () 語(yǔ)句塊 end function4. 語(yǔ)句塊 begin 語(yǔ)句語(yǔ)句end5. 語(yǔ)句 分支語(yǔ)句| 賦值語(yǔ)句| 循環(huán)語(yǔ)句|輸入語(yǔ)句| 輸出語(yǔ)句| 變量定義語(yǔ)句6. 變量定義語(yǔ)句 def id , id as 數(shù)據(jù)類(lèi)型 ;7. 數(shù)據(jù)類(lèi)型 integer | float | str

30、ing8. 輸入語(yǔ)句 in put id , id ;9. 輸出語(yǔ)句 output 表達(dá)式 ,表達(dá)式;10. 賦值語(yǔ)句 id= 表達(dá)式 ;11. 分支語(yǔ)句 if 布爾表達(dá)式 語(yǔ)句塊 else 語(yǔ)句塊 12. 循環(huán)語(yǔ)句 while 布爾表達(dá)式 do 語(yǔ)句塊13. 表達(dá)式 項(xiàng) +| 項(xiàng) 14. 項(xiàng) 因子 *| / 因子 15. 因子 id | con | deci |( 表達(dá)式 )14.布爾表達(dá)式- 關(guān)系表達(dá)式and | or 布爾表達(dá)式 15.關(guān)系表達(dá)式- 表達(dá)式 關(guān)系 表達(dá)式16.關(guān)系 |=| | = | = |附錄:詞法分析完整代碼(復(fù)制可執(zhí)行)/*詞法分析程序BY謝卓函ON June 20

31、th*/#include <iostream>#include <algorithm>#include <cstring>#include <fstream>#include <string>#define MAXLINE 30using namespace std;/標(biāo)識(shí)符1,整數(shù)2,小數(shù)3,字符串4,保留字5,數(shù)學(xué)運(yùn)算符6,比較運(yùn)算符7,邏輯運(yùn)算符8,分隔符9/保5string key14="if","else","while","do","

32、float","string","begin","end","def","integer","input","output","as","function"留字string border5= "", "" , "" , "("/ 分隔符string arithmetic9="+" , "-"

33、; , "*" , "/" ,"<" , "<=" , "=" , ">" , ">=" ;/ 運(yùn)算符 6string text;/記錄標(biāo)識(shí)符1string contentMAXLINE;/保存從文件讀取的內(nèi)容int i=0;int templine = 0;/i為字符游標(biāo)31#int scan( string s ,int line )int j, flag =0;text = ""/賦空 textwhile(

34、 contentlinei='')判斷空格i+;/是空格跳過(guò)/判斷是否為字母或者下if( (contentlinei>=65 && contentlinei<=90) | (contentlinei>=91 && contentlinei<=122)劃線text += contentlinei;i+;while( (contentlinei>=65 && contentlinei<=90) | (contentlinei>=91 && contentlinei<=12

35、2) | contentlinei>='0'&& contentlinei<='9')判斷是否為數(shù)字或者字母或者下劃線text += contentlinei;i+;for( j=0; j<=13 ; j+ )if( text=keyj )/查表判斷是否為保留字return 5;if( text="and" | text="or")判斷是否為邏輯運(yùn)算符return 8;if( j=14 )return 1;若查表失敗說(shuō)明為標(biāo)識(shí)符elsewhile( contentlinei>=

36、9;0' && contentlinei<='9')判斷是否為數(shù)字text += contentlinei;i+;flag=1;if( flag=1 )if( contentlinei='.')text += contentlinei;i+;while( contentlinei>='0' && contentlinei<='9')判斷是否為數(shù)字text += contentlinei;i+;return 2;整數(shù)return 3;小數(shù)if( contentlinei= &

37、#39;'| contentlinei='' | contentlinei='' | contentlinei='(' | contentlinei=')' |contentlinei=',')判斷是否為分隔符 text = contentlinei;i+; return 9;if( contentlinei= '+' | contentlinei='-' | contentlinei='*' | contentlinei='=' )/ 判斷是

38、否為運(yùn)算符 text = contentlinei; i+;return 6;if( conten tli nei='v' | conten tli nei='>')if( contentlinei+1='=')text = contentlinei;text += contentlinei+1;i=i+2;return 7;else text = contentlinei;i+; return 7;if( contentlinei=' “')判斷是否為字符串text += contentlinei;i+;while( co

39、ntentlinei!='” ')text += contentlinei;i+;text += contentlinei;i+;return 4;if( contentlinei='/')判斷是否為注釋if( contentlinei+1='/')i=contentline.length();return 0;如果為行注釋那么游標(biāo)指向行末elseif( contentlinei+1='*')i=i+2;while( contentlinei!='*' | contentlinei+1!='/')i

40、f( i=contentline.length()line+;i=0;elsei+;i=i+2;templine = line;return -1;-1 代表塊注釋else text = contentlinei;i+; return 0;return 0;int main()ifstream infile("ceshi1.txt",ios:in);if( infile )cout << "文件讀取成功! "<< endl;elsecout << "文件讀取失敗!" << endl;in

41、t hang, mode,k=1,numline;k 用于定位行數(shù)cout << endl;cout << "測(cè)試數(shù)據(jù)如下:"<< endl;while ( getline(infile,contentk)cout << contentk << endl;k+;numline = k-; /numline 記錄了文件總行數(shù)cout << endl;cout << "詞法分析結(jié)果:"<< endl;for( k=1; k<=numline; k+ )whi

42、le( i!=contentk.length()mode = scan( contentk, k );if( mode!=0 && mode!= -1)單詞cout << " 所在行數(shù):"<< k << " 所在列數(shù):"<< i-text.length()+1 << "單詞類(lèi)別:"<< mode <<為:"<< text <<endl ;elseif( mode=0 )if( i<contentk

43、.length() ) i+;如果為行注釋 直接跳到下一行elseif( mode=-1 )/如果為塊注釋找回行號(hào)k=templine;i = 0;一行結(jié)束定位到下一行行頭getchar();return 0;附錄二 語(yǔ)法語(yǔ)義四元式生成代碼(復(fù)制可執(zhí)行)/*語(yǔ)法+語(yǔ)義+四元式分析程序BY謝卓函ON June 25th*/#include <iostream>#include <algorithm>#include <cstring>#include <fstream>#include <string>#include <cstd

44、io>#include <vector>#include <iterator>#includealgorithm#includefunctional#include <stack>#include <queue>#include <cstdlib>#include <sstream>#define MAXLINE 30using namespace std;/標(biāo)識(shí)符1,整數(shù)2,小數(shù)3,字符串4,保留字5,數(shù)學(xué)運(yùn)算符6,比較運(yùn)算符7,邏輯運(yùn)算符8,分隔符9/保string key14="if",&q

45、uot;else","while","do","float","string","begin","end","def","integer","input","output","as","function"留字string border5= "", "" , "" , "(&quo

46、t;/分隔符 5string arithmetic9="+" , "-" , "*" , "/" ,"<" , "<=" , "=" , ">" , ">=" ;/ 運(yùn)算符6string text;/記錄標(biāo)識(shí)符 1string contentMAXLINE;/保存從文件讀取的內(nèi)容string resultMAXLINE = "t1","t2","

47、;t3","t4","t5","t6","t7","t8","t9","t10"/*/*語(yǔ)法語(yǔ)義各產(chǎn)生式函數(shù)*/void chengxu();void hanshukuai();void hanshu();void yujukuai();void yuju();void bianliangdingyiyuju();void shujuleixing();void shuruyuju();void shuchuyuju();void fuzhiyu

48、ju();void fenzhiyuju();void xunhuanyuju();void biaodashi();void xiang();void yinzi();void buerbiaodashi();void guanxibiaodashi();void guanxi();void error();void Quaternary_output();void Quaternary_maker();int i=0,k=1,numline,mode;i為字符游標(biāo),k為行號(hào),numline記錄了文件總行數(shù)int templine = 0;int errornum = 0;int warni

49、ngnum = 0;int r = 0, serial = 1;string op,v1,v2,res;struct Tokenstring value;/ 值int mode;類(lèi)型int row;行int col;列token;struct Symtable/ 符號(hào)表結(jié)構(gòu)string name;int type;bool value;S;struct Quaternary/ 四元式結(jié)構(gòu)int serial;string op;string v1;string v2;string result;Q;/函數(shù)聲明Quaternary Quaternary_generater( int serial

50、, string op, string v1, string v2, string result );vector<Symtable> ST;vector<Symtable> : iterator it;vector<Quaternary> QV;vector<Quaternary> : iterator it2;stack<string> operator_stack;/ 操作數(shù)堆棧stack<string> operand_stack;/ 操作符堆棧/仿函數(shù)和綁定器struct compare: binary_func

51、tion<Symtable, string,bool>bool operator()( Symtable s, string str) const if (= str)return true;elsereturn false;;void push_in_token( Token token )/ 進(jìn)表操作S.name = token.value;S.type = -1;S.value = false;ST.push_back( S );vector<Symtable> : iterator find_token( Token token )/ 查表操作it

52、= find_if( ST.begin(), ST.end(), bind2nd( compare(),token.value ); return it; int scan( string s ,int line )int j, flag =0;text = ""/賦空 textwhile( contentlinei='')判斷空格i+;是空格跳過(guò)if( (contentlinei>=65 && contentlinei<=90) | (contentlinei>=91 && contentlinei<

53、=122) )/ 判斷是否為字母或者下劃線text += contentlinei;i+;while( (contentlinei>=65 && contentlinei<=90) | (contentlinei>=91 && contentlinei<=122) | contentlinei>='0'&& contentlinei<='9')判斷是否為數(shù)字或者字母或者下劃線text += contentlinei;i+;for( j=0; j<=13 ; j+ )if(

54、text=keyj )/查表判斷是否為保留字return 5;if( text="and" | text="or")判斷是否為邏輯運(yùn)算符return 8;if( j=14 )return 1;若查表失敗說(shuō)明為標(biāo)識(shí)符 else39while( contentlinei>='0' && contentlinei<='9')text += contentlinei;i+;flag=1;if( flag=1 )if( contentlinei='.')text += contentlin

55、ei;i+;while( contentlinei>='0' && contentlinei<='9')text += contentlinei;i+;return 2;整數(shù)return 3;小數(shù)if( contentlinei= ''| contentlinei='' | contentlinei='' |/判斷是否為數(shù)字判斷是否為數(shù)字contentlinei='(' | contentlinei=')' |contentlinei=','

56、;)判斷是否為分隔符 text = contentlinei;i+; return 9;if( contentlinei= '+' | contentlinei='-' | contentlinei='*' | contentlinei='=') text = contentlinei; i+;return 6;if( conten tli nei='v' | conten tli nei='>')if( contentlinei+1='=')text = contentlinei;text += contentlinei+1;i=i+2;return

溫馨提示

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

評(píng)論

0/150

提交評(píng)論