2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩29頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論