版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、<p><b> 目 錄</b></p><p> 1 課程設(shè)計(jì)的目的和要求2</p><p> 1.1 課程設(shè)計(jì)的目的2</p><p> 1.2 課程設(shè)計(jì)的要求2</p><p><b> 2 系統(tǒng)描述2</b></p><p>
2、 2.1 自底向上分析方法的描述:2</p><p> 2.2 算符優(yōu)先文法的描述:2</p><p> 3)輸入符號串,進(jìn)行移進(jìn)-規(guī)約分析。3</p><p><b> 3 概要設(shè)計(jì)3</b></p><p> 3.1 設(shè)計(jì)思路3</p><p> 3.2 系統(tǒng)功
3、能結(jié)構(gòu)4</p><p> 3.3 技術(shù)路線或?qū)崿F(xiàn)方法5</p><p> 3.4 開發(fā)環(huán)境5</p><p><b> 4 詳細(xì)設(shè)計(jì)5</b></p><p> 4.1 模塊劃分5</p><p> 4.2主要算法的流程圖7</p><p>
4、; 4.3 數(shù)據(jù)分析與定義8</p><p> 4.4 系統(tǒng)界面設(shè)計(jì)8</p><p> 5 測試方法和測試結(jié)果9</p><p> 5.1 測試用例19</p><p> 5.2 測試用例210</p><p> 5.3測試用例311</p><p> 5
5、.4 測試用例412</p><p> 6 結(jié)論和展望13</p><p><b> 結(jié)論13</b></p><p><b> 展望13</b></p><p> 學(xué)習(xí)編譯技術(shù)課程的體會和對本門課程的評價(jià)13</p><p> 7 參考文獻(xiàn)13&
6、lt;/p><p><b> 8 源代碼14</b></p><p> 1 課程設(shè)計(jì)的目的和要求</p><p> 1.1 課程設(shè)計(jì)的目的</p><p> 本次設(shè)計(jì)的時(shí)間為1周,目的是通過使用高級語言實(shí)現(xiàn)部分算法加強(qiáng)對編譯技術(shù)和理論的理解。設(shè)計(jì)的題目要求具有一定的規(guī)模,應(yīng)涵蓋本課程內(nèi)容和實(shí)際應(yīng)用相關(guān)的主要技
7、術(shù)。</p><p> 1.2 課程設(shè)計(jì)的要求</p><p> 1、文法使用產(chǎn)生式來定義;</p><p> 2、用大寫字母和小寫字母分別表示非終結(jié)符和終結(jié)符;產(chǎn)生式使用->;</p><p> 3、文法中的空字符串統(tǒng)一使用@表示;</p><p> 4、分別給出每一個(gè)非終結(jié)符的FIRSTVT集和L
8、ASTVT集;</p><p> 5、畫出算符優(yōu)先關(guān)系表</p><p> 6、判定給定的文法是否是算符優(yōu)先文法;</p><p> 7、給定符號串判定是否是文法中的句子,分析過程用分析表格的方式打印出來。</p><p><b> 2 系統(tǒng)描述</b></p><p> 本次實(shí)驗(yàn)使用
9、windows vista操作系統(tǒng)下visual C++6.0平臺,使用C語言,利用讀文件方式將待分析的文法讀入到程序中,通過定義數(shù)組和結(jié)構(gòu)體作為具有一定意義或關(guān)系的表或棧,存放FIRSTVT、LASTVT、算符優(yōu)先關(guān)系表的元素。</p><p> 系統(tǒng)能夠?qū)τ晌募x入的文法進(jìn)行分析,構(gòu)造出FIRSTVT表和LASTVT表以及算符優(yōu)先關(guān)系表??梢愿鶕?jù)構(gòu)造的優(yōu)先關(guān)系表對輸入的任意符號串進(jìn)行分析,判斷是否為本文法的
10、句子,若是則打印規(guī)約過程。結(jié)果顯示到DOS界面上。</p><p> 2.1 自底向上分析方法的描述:</p><p> 對輸入的符號串自左向右進(jìn)行掃描,并將輸入符逐個(gè)移入棧中,邊移入邊分析,一旦棧頂符號串形成某個(gè)句型的句柄時(shí)(該句柄對應(yīng)某個(gè)產(chǎn)生式的右部),就用該產(chǎn)生式的左部非終結(jié)符代替相應(yīng)右部的文法符號串,這一過程稱為規(guī)約。重復(fù)這一過程,直到棧中只剩下文法的開始符則分析成功。<
11、;/p><p> 2.2 算符優(yōu)先文法的描述:</p><p> 只規(guī)定算符之間的優(yōu)先關(guān)系,也就是說只考慮終結(jié)符之間的優(yōu)先關(guān)系。由于算富有先分析不考慮非終結(jié)符之間的優(yōu)先關(guān)系,在規(guī)約過程中只要找到最左素短語就可以規(guī)約。</p><p> 如給定一個(gè)文法G[S]:</p><p><b> S->#E#</b>&
12、lt;/p><p><b> E->E+T</b></p><p><b> E->T</b></p><p><b> T->T*F</b></p><p><b> T->F</b></p><p>
13、<b> F->P/F</b></p><p><b> F->P</b></p><p><b> P->(E)</b></p><p><b> P->i</b></p><p> 利用算符優(yōu)先文法分析過程處理如下:&
14、lt;/p><p> 1)計(jì)算給定文法中任意兩個(gè)終結(jié)符對(a,b)之間的優(yōu)先關(guān)系,首先計(jì)算兩個(gè)集合</p><p> FIRSTVT(B)={b|B->b…或B->Cb…}</p><p> LASTVT(B)={a|B->…a或B->…aC}</p><p> 表2-1FIRSTVT集和LASTVT集</
15、p><p> 2)計(jì)算三種優(yōu)先關(guān)系,求出算符優(yōu)先關(guān)系表:</p><p> 表2-2算符優(yōu)先關(guān)系表</p><p> 3)輸入符號串,進(jìn)行移進(jìn)-規(guī)約分析。</p><p><b> 3 概要設(shè)計(jì)</b></p><p><b> 3.1 設(shè)計(jì)思路</b></p
16、><p> 1)首先在源程序相同的目錄下創(chuàng)建一個(gè)txt文檔,并在文檔中輸入待分析的文法。然后定義一個(gè)輸入流文件,調(diào)用這個(gè)流文件中的open函數(shù)打開該txt文件,再定義一個(gè)二維數(shù)組通過循環(huán)接收讀入的產(chǎn)生式。</p><p> 2)接著開始構(gòu)造FIRSTVT、LASTVT、算符優(yōu)先關(guān)系表。在構(gòu)造表的時(shí)候首先定義了兩個(gè)重要的結(jié)構(gòu)體。一個(gè)結(jié)構(gòu)體作為存放具有一定關(guān)系的一對非終結(jié)符和終結(jié)符,另一個(gè)結(jié)構(gòu)
17、體作為存放上述元素的棧,包括棧頂指針、棧底指針、棧的長度。既然定義了棧,就存在對棧的初始化、棧是否為空的判斷、入棧、出棧操作,利用循環(huán)和指針的操作來定義這些函數(shù),以完成元素的進(jìn)棧和彈出。</p><p> 定義了這兩個(gè)結(jié)構(gòu)體,就可以用來構(gòu)造FIRSTVT、LASTVT、算符優(yōu)先關(guān)系表。在構(gòu)造FIRSTVT表時(shí),通過循環(huán)找出每條產(chǎn)生式中的非終結(jié)符的FIRSTVT集,并把該非終結(jié)符和終結(jié)符壓棧,設(shè)置標(biāo)志位,標(biāo)志一對
18、非終結(jié)符和終結(jié)符具有對應(yīng)關(guān)系。LASTVT表的構(gòu)造則是將求FIRSTVT的過程翻轉(zhuǎn)過來,可以僅僅將函數(shù)中的參數(shù)稍作修改就能夠完成。</p><p> 3)構(gòu)造算符優(yōu)先關(guān)系表。算符優(yōu)先關(guān)系表是一個(gè)二維數(shù)組,用來存放任意兩個(gè)終結(jié)符之間的優(yōu)先關(guān)系。首先構(gòu)造表頭,通過掃描所有產(chǎn)生式將終結(jié)符不重復(fù)的存放在一個(gè)一維數(shù)組中并置為優(yōu)先關(guān)系表的行和列,并將優(yōu)先關(guān)系表其他內(nèi)容全部初始化為空。接著遍歷所有產(chǎn)生式,找出任意兩個(gè)終結(jié)符之
19、間存在的關(guān)系(可以沒有關(guān)系),并判斷任意兩終結(jié)符是否至多存在一種優(yōu)先關(guān)系,如發(fā)現(xiàn)優(yōu)先關(guān)系表不為空,則證明該文法不是算符優(yōu)先文法,否則,將相應(yīng)的關(guān)系填入到相應(yīng)的行列對應(yīng)的單元中。</p><p> 4)輸入串分析過程的設(shè)計(jì)。首先將大于、小于、等于和無關(guān)系分別定義成一種類型的數(shù)據(jù)表示,通過查詢符號棧棧頂以及當(dāng)前符號之間的優(yōu)先關(guān)系來判斷移進(jìn)和規(guī)約的操作。</p><p> 3.2 系統(tǒng)功能
20、結(jié)構(gòu)</p><p> 圖3-1 系統(tǒng)功能結(jié)構(gòu)圖</p><p><b> 函數(shù)功能:</b></p><p> Main()函數(shù):調(diào)用主函數(shù),運(yùn)行程序;</p><p> FirstVt()函數(shù):構(gòu)造FIRSTVT表;</p><p> LastVt()函數(shù):構(gòu)造LASTVT表;&l
21、t;/p><p> OpPrioTable()函數(shù):構(gòu)造算符優(yōu)先關(guān)系表;</p><p> InputAnalyse()函數(shù):分析輸入串是否為文法中的句子,并給出規(guī)約過程。</p><p> 3.3 技術(shù)路線或?qū)崿F(xiàn)方法</p><p> 算符優(yōu)先分析法的具體過程如下:</p><p> 1、首先先輸入文件的路徑
22、,在readfile(char sen[][col])函數(shù)中,將需要分析的文法通過輸入流文件打開函數(shù)open()復(fù)制到sen[row][col]中。</p><p> 2、然后利用FirstVt( )構(gòu)造產(chǎn)生式sen[row][col]的FirstVt表。先找出形如A->…a…(a為第一個(gè)終結(jié)符)的產(chǎn)生式,把(A,a)壓入Operator棧中。從Operator棧頂拋出項(xiàng)(A,a),填入first表相應(yīng)位
23、置。在找出形如B->A…的產(chǎn)生式,把(B,a)壓入Operator棧中。循環(huán)直到Operator棧為空,此時(shí)FirstVt表構(gòu)造完畢。</p><p> 3、然后把產(chǎn)生式右部翻轉(zhuǎn),調(diào)用FirstVt函數(shù)求出LastVt表。</p><p> 4、接著調(diào)用OpPriotable()構(gòu)造算符優(yōu)先關(guān)系表opTable。先把產(chǎn)生式中所有終結(jié)符填入opTable表第一行和第一列,然后利用產(chǎn)
24、生式和FirstVt表LastVt表分別找出滿足=關(guān)系、<關(guān)系、>關(guān)系的算符填表。若相應(yīng)位已有關(guān)系,說明兩個(gè)終結(jié)符之間至少有兩種優(yōu)先關(guān)系,該文法不是算符優(yōu)先文法。</p><p> 5、最后調(diào)用InputAnalyse()對輸入串進(jìn)行分析。初始化分析棧S,依次判斷當(dāng)前輸入符a和分析棧中離棧頂最近的終結(jié)符S[ j ]的關(guān)系,若S[ j ]< a ,則a移近,若S[ j ]< a ,則往前找
25、到第一個(gè)S[ j ]>a,將S[ j -1]到棧頂S[ k ]規(guī)約,若S[ j ]= a ,如果S[ j ]=#,則接受,如果S[ j ]!=#,則移進(jìn)。直到接受或者出錯(cuò),算符優(yōu)先分析結(jié)束。</p><p><b> 3.4 開發(fā)環(huán)境</b></p><p> 實(shí)驗(yàn)使用windows vista操作系統(tǒng)下的Microsoft Visual C++ 6.0平
26、臺,用C語言完成。</p><p><b> 4 詳細(xì)設(shè)計(jì)</b></p><p><b> 4.1 模塊劃分</b></p><p> 實(shí)驗(yàn)分為五個(gè)模塊,分別是:</p><p> 1、文件的導(dǎo)入:</p><p> readfile(sen[][])
27、;</p><p> 2、FirstVt、LastVt集的構(gòu)造:</p><p> FirstVt(sen[][],first[][],sen_len,frist_len);</p><p> LastVt(sen[][],last[][],sen_len,frist_len);</p><p> 算符優(yōu)先關(guān)系表OpPriotabl
28、e的構(gòu)造:</p><p> OpPriotable(sen,first,last,opTable,sen_len,first_len,&opTable_len);</p><p> 4、算符優(yōu)先分析過程的實(shí)現(xiàn):</p><p> InputAnalyse(opTable[][col],string[col],opTable_len);</p&g
29、t;<p> 5、主函數(shù):main()。</p><p><b> 主要算法的流程圖</b></p><p> 圖4-1 算符優(yōu)先分析法程序流程圖</p><p> 4.3 數(shù)據(jù)分析與定義</p><p> 1、文法(產(chǎn)生式):文法使用產(chǎn)生式來定義</p><p>
30、char sen[row][col]:用二維數(shù)組表示產(chǎn)生式;</p><p> int sen_len:產(chǎn)生式的個(gè)數(shù);</p><p> 2、FIRSTVT集:</p><p> char first[row][col]:用二維數(shù)組構(gòu)造FIRSTVT表</p><p> int frist_len:FIRSTVT表的行數(shù);</
31、p><p> 3、LASTVT集:</p><p> char last[row][col]:用二維數(shù)組構(gòu)造LASTVT表;</p><p> int frist_len:LASTVT表的行數(shù);</p><p> 4、算符優(yōu)先關(guān)系表:</p><p> char opTable[row][col]:用二維數(shù)組表示
32、算符優(yōu)先關(guān)系表;</p><p> int opTable_len:算符優(yōu)先關(guān)系表的行數(shù)和列數(shù);</p><p><b> 5、算符優(yōu)先分析表</b></p><p> char string[col]:用一維數(shù)組記錄輸入串;</p><p> char S[SIZE]:用一維數(shù)組表示分析棧 ;</p>
33、;<p> char a:當(dāng)前輸入字符;</p><p><b> 6、其他數(shù)據(jù)結(jié)構(gòu):</b></p><p> typedef struct</p><p><b> {</b></p><p> char nonterm; //非終結(jié)符</p>
34、<p> char term; //終結(jié)符</p><p> }StackElement;</p><p> FIRSTVT表或LASTVT表中一個(gè)表項(xiàng)(A,a);</p><p> 7、typedef struct </p><p><b> {</b>&
35、lt;/p><p> StackElement *top;</p><p> StackElement *bottom;</p><p> int stacksize;</p><p><b> }stack;</b></p><p> 以形如表項(xiàng)(A,a)為元素的棧,在構(gòu)造FirstVt集
36、的過程中用到;</p><p> 4.4 系統(tǒng)界面設(shè)計(jì)</p><p> 本實(shí)驗(yàn)沒有考慮界面設(shè)計(jì),將結(jié)果直接打印輸出在DOS界面下。</p><p> 5 測試方法和測試結(jié)果</p><p> 5.1 測試用例1</p><p> 測試目的:使用算符優(yōu)先分析法對一個(gè)算符文法中的句子進(jìn)行分析。</p
37、><p> 讀入一個(gè)算符優(yōu)先文法進(jìn)行分析,給出文件路徑D:\\courses\\C_source_file\\成品\\算符優(yōu)先文法1.txt。結(jié)果如下:</p><p> 圖5-1 測試用例1運(yùn)行截圖1</p><p> 輸入一個(gè)字符串,使得該字符串是該文法的一個(gè)句子。則輸入字符串i+i*i/(i+i)#時(shí)運(yùn)行結(jié)果為:</p><p>
38、圖5-2 測試用例1運(yùn)行截圖2</p><p> 5.2 測試用例2</p><p> 測試目的:使用算符優(yōu)先分析法,分析一個(gè)字符串不是該文法的句子,并輸出出錯(cuò)信息。</p><p> 輸入一個(gè)字符串,使得該字符串不是文法的句子。</p><p> 圖5-3 測試用例2運(yùn)行截圖</p><p><b&g
39、t; 測試用例3</b></p><p> 測試目的:讀入一個(gè)文法,判斷該文法不是算符優(yōu)先文法。</p><p> 讀入一個(gè)非算符優(yōu)先文法進(jìn)行分析,給出文件路徑:D:\\courses\\C_source_file\\成品\\非算符優(yōu)先文法1.txt。運(yùn)行結(jié)果如下:</p><p> 圖5-4 測試用例3運(yùn)行截圖</p><p
40、> 5.4 測試用例4</p><p> 測試目的:輸入一個(gè)非算符文法,判斷該文法不是算符文法。</p><p> 讀入一個(gè)非算符文法,給出路徑:D:\\courses\\C_source_file\\成品\\非算符文法.txt。運(yùn)行結(jié)果如下:</p><p> 圖5-5 測試用例4運(yùn)行截圖</p><p><b>
41、 6 結(jié)論和展望</b></p><p><b> 結(jié)論</b></p><p> 本次實(shí)驗(yàn)我們基本完成了實(shí)驗(yàn)題目的要求。求出了一個(gè)文法中每一個(gè)非終結(jié)符的FIRSTVT集和LASTVT集,畫出算符優(yōu)先關(guān)系表,并判定出給定的文法是否是算符優(yōu)先文法。當(dāng)給定一個(gè)符號串時(shí),能夠判定是否是文法中的句子,并能夠?qū)⒎治鲞^程打印出來。通過算符優(yōu)先分析方法,可以對任
42、意一個(gè)文法進(jìn)行自底向上的分析。同時(shí),算符優(yōu)先分析法也存在不足之處,由于忽略文法中的非終結(jié)符,會將本不屬于文法的句子正確規(guī)約,從而引起錯(cuò)誤。</p><p><b> 展望</b></p><p> 本次實(shí)驗(yàn)完成了題目的要求,準(zhǔn)確把握了將文法通過讀文件形式、手動輸入分析字符串的題目要求,并在滿足要求的基礎(chǔ)上進(jìn)行了創(chuàng)新,添加了對算符文法的判斷功能。實(shí)驗(yàn)中,小組成員的分
43、工與合作充分體現(xiàn)了軟件工程的思想。需求分析理解準(zhǔn)確,小組成員任務(wù)明確,統(tǒng)一函數(shù)頭、參數(shù),各自完成分內(nèi)工作,整合工作快速、高效。</p><p> 同時(shí),實(shí)驗(yàn)中還存在很多不足。調(diào)試程序中的錯(cuò)誤占用了大部分時(shí)間,以至于沒有考慮使用界面展示結(jié)果。雖然使用C++開發(fā)工具,但實(shí)質(zhì)上還是在使用C編代碼。在今后的實(shí)踐中還需注意。</p><p> 學(xué)習(xí)編譯技術(shù)課程的體會和對本門課程的評價(jià)</p
44、><p> 在上編譯課的時(shí)候,小組成員都覺得自己對算符優(yōu)先文法已經(jīng)掌握了,但等真正用程序去實(shí)現(xiàn)時(shí),才發(fā)現(xiàn)有很多細(xì)節(jié)我當(dāng)時(shí)沒有注意到。也正以為沒有注意到這些細(xì)節(jié),導(dǎo)致成員們編程時(shí)會出現(xiàn)各種錯(cuò)誤,大部分都是在循環(huán)時(shí)下標(biāo)或者循環(huán)次數(shù)的控制上出錯(cuò)。在進(jìn)行到一定階段后發(fā)現(xiàn)犯的低級錯(cuò)誤越來越少了,對算符優(yōu)先文法也愈發(fā)的吃透了,編程水平也有了進(jìn)一步的提高。</p><p> 編譯原理如果要深入研究,那會
45、是一門非常深?yuàn)W的學(xué)問,對于現(xiàn)階段只有60多學(xué)時(shí)的本科生來說,只能涉及到它一些最基本的原理,和最宏觀的方法,要想微觀的去研究,還需要在以后的時(shí)間里去鉆研。在這次實(shí)驗(yàn)中,小組成員也只是用高級語言模擬了編譯的一個(gè)小方法,在完成實(shí)驗(yàn)的過程中,小組成員對編譯原理有了進(jìn)一步的了解,更提高了動手編程能力,是一次經(jīng)驗(yàn)和知識的積累。</p><p><b> 7 參考文獻(xiàn)</b></p>&
46、lt;p> [1] 張素琴.編譯原理(第2版)[M]. 北京:清華大學(xué)出版社,2005.6,102-121.</p><p> [2] 陳維興.C++面向?qū)ο蟪绦蛟O(shè)計(jì)教程[M]. 北京:清華大學(xué)出版社,2004.8,258-272.</p><p><b> 8 源代碼</b></p><p> #include<iost
47、ream.h></p><p> #include<stdlib.h></p><p> #include <fstream.h></p><p> #define row 50</p><p> #define col 50</p><p> #define SIZE 50&l
48、t;/p><p> //兩個(gè)重要結(jié)構(gòu)體的定義</p><p> //FIRSTVT表或LASTVT表中一個(gè)表項(xiàng)(A,a)結(jié)構(gòu)體的初始化</p><p> typedef struct</p><p><b> {</b></p><p> char nonterm; //非終結(jié)
49、符</p><p> char term; //終結(jié)符</p><p> }StackElement;</p><p> //存放(A,a)的棧的初始化</p><p> typedef struct </p><p><b> {</b><
50、;/p><p> StackElement *top;</p><p> StackElement *bottom;</p><p> int stacksize;</p><p><b> }stack;</b></p><p> //初始化(A,a)棧</p><p&
51、gt; void InitStack(stack &S)</p><p><b> {</b></p><p> S.bottom = new StackElement[SIZE]; </p><p> if(!S.bottom) </p><p> cout<<
52、;"存儲空間分配失敗!"<<endl; </p><p> S.top = S.bottom;</p><p> S.stacksize = SIZE;</p><p><b> }</b></p><p> //判斷(A,a)棧是否為空</p>&
53、lt;p> bool ifEmpty(stack S)</p><p><b> {</b></p><p> if(S.top==S.bottom) return true; //如果棧為空,則返回true</p><p> else return false; //否則不為空,返回false&
54、lt;/p><p><b> }</b></p><p> //插入棧頂(A,a)元素</p><p> void Insert(stack &S,StackElement e)</p><p><b> {</b></p><p> if(S.top-S.bo
55、ttom>=S.stacksize)</p><p> cout<<"棧已滿,無法插入!"<<endl;</p><p><b> else</b></p><p><b> {</b></p><p> S.top->nonterm=
56、e.nonterm;</p><p> S.top->term=e.term;</p><p><b> S.top++;</b></p><p><b> }</b></p><p><b> }</b></p><p> //彈出棧頂
57、(A,a)元素</p><p> StackElement Pop(stack &S)</p><p><b> {</b></p><p> StackElement e;</p><p> e.nonterm = '\0';</p><p> e.term =
58、 '\0';</p><p> if(S.top==S.bottom)</p><p><b> {</b></p><p> cout<<"棧為空,無法進(jìn)行刪除操作!"<<endl;</p><p><b> return e;</b&
59、gt;</p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p><b> S.top--;</b></p><p> e.nonterm=S.
60、top->nonterm;</p><p> e.term=S.top->term;</p><p><b> return e;</b></p><p><b> }</b></p><p><b> }</b></p><p>
61、 //終結(jié)符與非終結(jié)符的判斷函數(shù)(布爾類型)</p><p> bool TerminalJud(char c)</p><p><b> {</b></p><p> if(c>='A'&&c<='Z')return false; //非終結(jié)符返回false&l
62、t;/p><p> else return true; //終結(jié)符返回true</p><p><b> }</b></p><p> //判斷非終結(jié)符在first表中是否已存在</p><p> bool ItemJud(char first[][col],int frist_len,c
63、har C)</p><p><b> {</b></p><p> for(int i=0;i<frist_len;i++)</p><p><b> {</b></p><p> if(first[i][0]==C) </p><p> return t
64、rue; //如果first表中已存在此非終結(jié)符,則返回true</p><p><b> }</b></p><p> return false;</p><p><b> }</b></p><p><b> //讀文件函數(shù)</b></p>&
65、lt;p> int readfile(char sen[][col])</p><p><b> {</b></p><p> char addr[50];</p><p> cout<<"請輸入要讀文件的地址(\\用\\\\表示):"<<endl;</p><p&g
66、t; cin>>addr;</p><p> ifstream fin;</p><p> fin.open(addr,ios::in);</p><p><b> if(!fin)</b></p><p><b> {</b></p><p> co
67、ut<<"Cannot open file!\n"<<endl;</p><p><b> }</b></p><p> for(int i=0;!fin.eof();i++)</p><p><b> {</b></p><p> fin>
68、>sen[i];</p><p> cout<<sen[i]<<endl;</p><p><b> }</b></p><p><b> return i;</b></p><p><b> }</b></p><p&
69、gt; //FIRSTVT表和LASTVT表中表項(xiàng)(非終結(jié)符)的初始化</p><p> void ItemInit(char sen[][col],char first[][col],char last[][col],int sen_len,int &frist_len)</p><p><b> {</b></p><p>&
70、lt;b> int i;</b></p><p> frist_len=1;</p><p> first[0][0]=sen[0][0];</p><p> last[0][0]=sen[0][0];</p><p> for(i=1;i<sen_len;i++)</p><p>&
71、lt;b> {</b></p><p> if(TerminalJud(sen[i][0])==false && ItemJud(first,frist_len,sen[i][0])==false) //k是當(dāng)前first和last表的長度</p><p><b> {</b></p><p> fi
72、rst[frist_len][0]=sen[i][0];</p><p> last[frist_len][0]=sen[i][0];</p><p> frist_len++;</p><p><b> }</b></p><p><b> }</b></p><p&g
73、t;<b> }</b></p><p> void FirstVt(char sen[][col],char first[][col],int sen_len,int frist_len) // frist_len 是 first 表的行數(shù) sen_len是產(chǎn)生式的個(gè)數(shù)</p><p><b> {</b></p>
74、<p> StackElement DFS,record[SIZE];</p><p> stack Operator; //創(chuàng)建存放(A,a)的棧</p><p> InitStack(Operator); </p><p> int i,j,r=0;</p><p> for(i=0;i<sen_
75、len;i++) //第一次掃描,將能直接得出的first(A,a)放進(jìn)棧中</p><p><b> {</b></p><p> for(j=3;sen[i][j]!='\0';j++)</p><p><b> {</b></p><p> i
76、f(TerminalJud(sen[i][j])==true) //遇到的第一個(gè)終結(jié)符壓入</p><p><b> {</b></p><p> int exist=0;</p><p> DFS.nonterm=sen[i][0];</p><p> DFS.term=sen
77、[i][j];</p><p> for(int i1=0;i<r;i++)</p><p><b> {</b></p><p> if(record[i1].nonterm==sen[i][0]&&record[i1].term==sen[i][j])</p><p><b>
78、 {</b></p><p><b> exist=1;</b></p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b></p><p> r
79、ecord[r].nonterm=sen[i][0];</p><p> record[r].term=sen[i][j];</p><p> if(exist==0)</p><p><b> {</b></p><p> Insert(Operator,DFS);//A-aB A-aC (A,a)壓棧兩次?&
80、lt;/p><p> record[r].nonterm=sen[i][0];</p><p> record[r].term=sen[i][j];</p><p><b> r++;</b></p><p><b> }</b></p><p><b> b
81、reak;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> int location[col]; //輔助數(shù)組,用來記錄first表中放入終結(jié)符的位置&
82、lt;/p><p> for(i=0;i<frist_len;i++) </p><p> location[i]=1;</p><p> while(!ifEmpty(Operator))</p><p><b> {</b></p><p> int exist=0;
83、 //標(biāo)志位,記錄即將入棧的元素是否已經(jīng)存在</p><p> StackElement IDElement,DElement;</p><p> DElement=Pop(Operator); //彈出棧頂元素</p><p> for(i=0;i<frist_len;i++)</p><p><b>
84、 {</b></p><p> if(first[i][0]==DElement.nonterm)</p><p><b> {</b></p><p> int n=location[i];</p><p> first[i][n]=DElement.term; //將終結(jié)符填入相應(yīng)的fi
85、rst表中</p><p> location[i]++;</p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b></p><p> for(j=0;j<sen_len;
86、j++)</p><p><b> { </b></p><p> if(sen[j][3]==DElement.nonterm) //找出能推出當(dāng)前非終結(jié)符的產(chǎn)生式的左部</p><p><b> {</b></p><p> IDElement.nonterm=sen[j][0
87、];</p><p> IDElement.term=DElement.term;</p><p> //判斷將要放進(jìn)棧里的元素曾經(jīng)是否出現(xiàn)過,若沒有,才壓入棧</p><p> for(int r0=0;r0<r;r0++) //r記錄record數(shù)組中的元素個(gè)數(shù)</p><p><b> {</b
88、></p><p> if(record[r0].nonterm==IDElement.nonterm && record[r0].term==IDElement.term) </p><p><b> {</b></p><p><b> exist=1;</
89、b></p><p><b> break;</b></p><p><b> }</b></p><p> } </p><p> if(exist==0)</p><p><b> {</b></p>
90、;<p> Insert(Operator,IDElement);</p><p> record[r].nonterm=IDElement.nonterm;</p><p> record[r].term=IDElement.term;</p><p><b> r++;</b></p><p>
91、;<b> }</b></p><p><b> }//if</b></p><p><b> }//for</b></p><p><b> }//while</b></p><p><b> }</b></p>
92、;<p> void LastVt(char sen[][col],char last[][col],int sen_len,int frist_len) //firstvt表與lastvt表行數(shù)一樣 first_len表示last 表的行數(shù)</p><p><b> {</b></p><p> int i,j,i1,j1;</p
93、><p> char c,record[row][col]={'\0'};</p><p> for(i=0;i<sen_len;i++)</p><p><b> { </b></p><p> for(j=0;sen[i][j]!='\0';j++)</p>
94、<p><b> {</b></p><p> record[i][j]=sen[i][j];</p><p><b> }</b></p><p><b> j=j-1;</b></p><p> for(i1=3,j1=j;i1<j1;i1++,j
95、1--) //做翻轉(zhuǎn),就可以用求first的方法求last</p><p><b> {</b></p><p> c=record[i][i1];</p><p> record[i][i1]=record[i][j1];</p><p> record[i][j1]=c;&l
96、t;/p><p><b> }</b></p><p><b> }//for</b></p><p> FirstVt(record,last,sen_len,frist_len);</p><p><b> }</b></p><p> //
97、判斷非終結(jié)符在term表中是否已存在</p><p> bool TermTableJud(char term[col],int term_len,char C) </p><p><b> {</b></p><p> for(int i=0;i<term_len;i++)</p><p><b&
98、gt; {</b></p><p> if(term[i]==C) </p><p> return true; //如果first表中已存在此非終結(jié)符,則返回1</p><p><b> }</b></p><p> return false;</p><p>&
99、lt;b> }</b></p><p> //構(gòu)造算符優(yōu)先關(guān)系表</p><p> bool OpPriotable(char sen[][col],char first[][col],char last[][col],char opTable[][col],int sen_len,int first_len,int &opTable_len)
100、</p><p><b> {</b></p><p> int i,j,term_len=0;</p><p> int i2,i3,opr,opc;</p><p> char c1,c2,c3;</p><p> char term[SIZE]={'\0'};<
101、;/p><p> for(i=0;i<sen_len;i++) //一維數(shù)組term記錄關(guān)系表中存在的所有終結(jié)符</p><p><b> {</b></p><p> for(j=3;sen[i][j]!='\0';j++)</p><p><b> {</
102、b></p><p> if(TerminalJud(sen[i][j])==true)</p><p> if(TermTableJud(term,term_len,sen[i][j])==false) //term_len記錄term表的長度</p><p><b> {</b></p><p> t
103、erm[term_len]=sen[i][j];</p><p> term_len++;</p><p><b> }</b></p><p><b> }</b></p><p> } //得到終結(jié)符表</p><p
104、> for(i=0;i<term_len+1;i++) //給優(yōu)先關(guān)系表賦初值,都等于空</p><p> for(j=0;j<term_len+1;j++)</p><p> opTable[i][j]=' ';</p><p> for(i=1;i<term_len+1;i++)
105、//設(shè)置優(yōu)先關(guān)系表的表頭</p><p><b> {</b></p><p> opTable[i][0]=term[i-1]; </p><p> opTable[0][i]=term[i-1]; </p><p><b> }</b></p><p> f
106、or(i=0;i<sen_len;i++) //找等于關(guān)系</p><p><b> {</b></p><p> for(j=5;sen[i][j]!='\0';j++)</p><p><b> {</b></p><p> if(TerminalJu
107、d(sen[i][j-2])==true&&TerminalJud(sen[i][j-1])==false&&TerminalJud(sen[i][j])==true)</p><p><b> {</b></p><p> c1=sen[i][j-2]; </p><p> c2=sen[i
108、][j]; </p><p> for(opr=1;opr<term_len+1;opr++) //在opTable表中找到該存入的行標(biāo)opr</p><p><b> {</b></p><p> if(opTable[opr][0]==c1)</p><p><b&g
109、t; break;</b></p><p><b> }</b></p><p> for(opc=1;opc<term_len+1;opc++) //在opTable表中找到該存入的列標(biāo)opc</p><p><b> {</b></p><p>
110、 if(opTable[0][opc]==c2)</p><p><b> break;</b></p><p><b> }</b></p><p> if(opTable[opr][opc]!=' ')</p><p><b> {</b></
111、p><p> cout<<"不是算符優(yōu)先文法!"<<endl;</p><p> return false;</p><p><b> }</b></p><p><b> else</b></p><p><b>
112、 {</b></p><p> opTable[opr][opc]='=';</p><p><b> }</b></p><p><b> }//if</b></p><p><b> }//for(j)</b></p>
113、<p> for(j=4;sen[i][j]!='\0';j++)</p><p><b> {</b></p><p> if(TerminalJud(sen[i][j-1])==true&&TerminalJud(sen[i][j])==true)</p><p><b> {&
114、lt;/b></p><p> c1=sen[i][j-1];</p><p> c2=sen[i][j];</p><p> for(opr=1;opr<term_len+1;opr++) //在opTable表中找到該存入的行標(biāo)opr</p><p><b> {</b><
115、/p><p> if(opTable[opr][0]==c1)</p><p><b> break;</b></p><p><b> }</b></p><p> for(opc=1;opc<term_len+1;opc++) //在opTable表中找到該存入的
116、列標(biāo)j2</p><p><b> {</b></p><p> if(opTable[0][opc]==c2)</p><p><b> break;</b></p><p><b> }</b></p><p> if(opTable[op
117、r][opc]!=' ')</p><p><b> {</b></p><p> cout<<"不是算符優(yōu)先文法!"<<endl;</p><p> return false;</p><p><b> }</b></p&g
118、t;<p><b> else</b></p><p><b> {</b></p><p> opTable[opr][opc]='=';</p><p><b> }</b></p><p><b> }</b>
119、</p><p><b> }</b></p><p><b> }//for(i)</b></p><p> for(i=0;i<sen_len;i++) //找小于關(guān)系</p><p><b> {</b></p><p>
120、; for(j=3;sen[i][j]!='\0';j++)</p><p><b> {</b></p><p> if(TerminalJud(sen[i][j])==true&&TerminalJud(sen[i][j+1])==false)</p><p><b> {</b>
121、;</p><p> c1=sen[i][j]; //c1記錄終結(jié)符</p><p> c2=sen[i][j+1]; //c2記錄非終結(jié)符</p><p> for(opr=1;opr<term_len+1;opr++) //在opTable表中找到該存入的行標(biāo)opr</p><p>
122、;<b> {</b></p><p> if(opTable[opr][0]==c1)</p><p><b> break;</b></p><p><b> }</b></p><p> for(opc=0;opc<first_len;opc++)
123、 //找出非終結(jié)符在first表中的列標(biāo)opc</p><p><b> {</b></p><p> if(first[opc][0]==c2)</p><p><b> break;</b></p><p><b> }</b></p>
124、<p> for(i2=1;first[opc][i2]!='\0';i2++)</p><p><b> {</b></p><p> c3=first[opc][i2];</p><p> for(i3=1;i3<term_len+1;i3++)</p><p> if(op
125、Table[0][i3]==c3)</p><p><b> {</b></p><p> if(opTable[opr][i3]!=' ')</p><p><b> {</b></p><p> cout<<"不是算符優(yōu)先文法!"<&
126、lt;endl;</p><p> return false;</p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p><p> opTable[opr][i3]='
127、;<';</p><p><b> }</b></p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b></p><p><b>
128、}//if</b></p><p><b> }//for(j)</b></p><p><b> }//for(i)</b></p><p> for(i=0;i<sen_len;i++) //找大于關(guān)系</p><p><b> {<
129、/b></p><p> for(j=3;sen[i][j]!='\0';j++)</p><p><b> {</b></p><p> if(TerminalJud(sen[i][j])==false&&sen[i][j+1]!='\0'&&TerminalJud(
130、sen[i][j+1])==true)</p><p><b> {</b></p><p> c1=sen[i][j]; //c1記錄非終結(jié)符</p><p> c2=sen[i][j+1]; //c2記錄終結(jié)符</p><p> for(opr=1;opr<term_len+
131、1;opr++) //在opTable表中找到該存入的列標(biāo)j1</p><p><b> {</b></p><p> if(opTable[0][opr]==c2)</p><p><b> break;</b></p><p><b> }</b>
132、</p><p> for(opc=0;opc<first_len;opc++) //找出非終結(jié)符在last表中的行標(biāo)j2</p><p><b> {</b></p><p> if(last[opc][0]==c1)</p><p><b> break;</b&g
133、t;</p><p><b> }</b></p><p> for(i2=1;last[opc][i2]!='\0';i2++)</p><p><b> {</b></p><p> c3=last[opc][i2];</p><p> for(
134、i3=1;i3<term_len+1;i3++)</p><p> if(opTable[i3][0]==c3)</p><p><b> {</b></p><p> if(opTable[i3][opr]!=' ')</p><p><b> {</b></p
135、><p> cout<<"不是算符優(yōu)先文法!"<<endl;</p><p> return false;</p><p><b> }</b></p><p><b> else</b></p><p><b>
136、{</b></p><p> opTable[i3][opr]='>';</p><p><b> }</b></p><p><b> break;</b></p><p><b> }</b></p><p>
137、;<b> }</b></p><p><b> }//if</b></p><p><b> }//for(j)</b></p><p><b> }//for(i)</b></p><p> opTable_len=term_len+1
138、;</p><p> return true;</p><p><b> }</b></p><p> //判斷兩算符優(yōu)先關(guān)系并給出類型供構(gòu)造分析表</p><p> int RelationshipJud(char c1,char c2,char opTable[][col],int opTable_len)&
139、lt;/p><p><b> {</b></p><p><b> int i,j;</b></p><p> for(i=1;i<opTable_len;i++)</p><p><b> {</b></p><p> if(opTable
溫馨提示
- 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 簡單優(yōu)先分析法編譯原理課程設(shè)計(jì)
- 編譯原理課程設(shè)計(jì)報(bào)告--- slr(1)文法與算符優(yōu)先文法程序?qū)崿F(xiàn)
- 詞法分析和算符優(yōu)先分析課程設(shè)計(jì)
- 算符優(yōu)先分析方法
- 十進(jìn)制的語法分析及語義分析程序設(shè)計(jì)(算符優(yōu)先分析法)講述
- 編譯原理課程設(shè)計(jì)詞法分析
- 編譯原理課程設(shè)計(jì)--詞法分析
- 編譯原理課程設(shè)計(jì)
- 編譯原理課程設(shè)計(jì)
- 編譯原理課程設(shè)計(jì)--- 詞法分析程序
- 編譯原理課程設(shè)計(jì)--構(gòu)造lr(0)分析法語法分析器
- 編譯原理課程設(shè)計(jì)--編譯器
- 編譯原理課程設(shè)計(jì)報(bào)告
- 編譯原理課程設(shè)計(jì) (2)
- 編譯原理課程設(shè)計(jì)報(bào)告
- 課程設(shè)計(jì)----編譯原理詞法分析器
- 編譯原理課程設(shè)計(jì)報(bào)告_編譯器
- 編譯原理課程設(shè)計(jì)-ll1文法分析器設(shè)計(jì)
- 編譯原理課程設(shè)計(jì)報(bào)告 (2)
- 編譯原理課程設(shè)計(jì)報(bào)告詞法分析器
評論
0/150
提交評論