《編譯原理》實(shí)驗(yàn)指導(dǎo)書2016_第1頁(yè)
《編譯原理》實(shí)驗(yàn)指導(dǎo)書2016_第2頁(yè)
《編譯原理》實(shí)驗(yàn)指導(dǎo)書2016_第3頁(yè)
《編譯原理》實(shí)驗(yàn)指導(dǎo)書2016_第4頁(yè)
《編譯原理》實(shí)驗(yàn)指導(dǎo)書2016_第5頁(yè)
已閱讀5頁(yè),還剩32頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、編譯原理實(shí)驗(yàn)指導(dǎo)書編 譯 原 理實(shí)驗(yàn)與課程設(shè)計(jì)指導(dǎo)書2016年10月目錄一、課程簡(jiǎn)介2二、實(shí)驗(yàn)?zāi)康?三、實(shí)驗(yàn)環(huán)境2四、實(shí)驗(yàn)任務(wù)2五、實(shí)驗(yàn)項(xiàng)目3實(shí)驗(yàn)一. 詞法分析3實(shí)驗(yàn)二. 自頂向下語(yǔ)法分析8實(shí)驗(yàn)三. 自底向上語(yǔ)法分析10實(shí)驗(yàn)四. 語(yǔ)義分析11實(shí)驗(yàn)五. 中間代碼生成12六、課程設(shè)計(jì)13七、考核方式13八、參考文獻(xiàn)14九、附錄PL0語(yǔ)言編譯源程序清單(部分)15編譯原理實(shí)驗(yàn)與課程設(shè)計(jì)指導(dǎo)一、課程簡(jiǎn)介1. 課程名稱:編譯原理(Principle of Compiler)2. 課程總學(xué)時(shí): 64 學(xué)時(shí)理論: 48 學(xué)時(shí);實(shí)驗(yàn): 16 學(xué)時(shí)3. 課程總學(xué)分: 4 學(xué)分二、實(shí)驗(yàn)?zāi)康木幾g原理是計(jì)算機(jī)類專業(yè)特

2、別是計(jì)算機(jī)軟件專業(yè)的一門重要專業(yè)課。設(shè)置該課程的目的在于系統(tǒng)地向?qū)W生講述編譯系統(tǒng)的結(jié)構(gòu)、工作流程及編譯程序各組成部分的設(shè)計(jì)原理和實(shí)現(xiàn)技術(shù),使學(xué)生通過(guò)學(xué)習(xí)既掌握編譯理論和方法方面的基本知識(shí),也具有設(shè)計(jì)、實(shí)現(xiàn)、分析和維護(hù)編譯程序等方面的初步能力。編譯原理是一門理論性和實(shí)踐性都比較強(qiáng)的課程。進(jìn)行上機(jī)實(shí)驗(yàn)的目的是使學(xué)生通過(guò)完成上機(jī)實(shí)驗(yàn)題目加深對(duì)課堂教學(xué)內(nèi)容的理解。同時(shí)培養(yǎng)學(xué)生實(shí)際動(dòng)手能力。三、實(shí)驗(yàn)環(huán)境微機(jī)CPU P4以上,256M以上內(nèi)存,安裝好C語(yǔ)言,或C+,或Visual C+開(kāi)發(fā)環(huán)境。四、實(shí)驗(yàn)任務(wù)用C/C+/Visual C+語(yǔ)言編寫某語(yǔ)言的詞法分析程序、語(yǔ)法分析程序、語(yǔ)義分析程序、中間代碼生成

3、程序。五、實(shí)驗(yàn)項(xiàng)目實(shí)驗(yàn)一. 詞法分析1. 實(shí)驗(yàn)?zāi)康膌 根據(jù)PL/0語(yǔ)言的文法規(guī)范,編寫PL/0語(yǔ)言的詞法分析程序。l 通過(guò)設(shè)計(jì)調(diào)試詞法分析程序,實(shí)現(xiàn)從源程序中分出各種單詞的方法;加深對(duì)課堂教學(xué)的理解;提高詞法分析方法的實(shí)踐能力。l 掌握從源程序文件中讀取有效字符的方法和產(chǎn)生源程序的內(nèi)部表示文件的法。 l 掌握詞法分析的實(shí)現(xiàn)方法。 l 上機(jī)調(diào)試編出的詞法分析程序。2. 實(shí)驗(yàn)準(zhǔn)備微機(jī)CPU P4以上,256M以上內(nèi)存,安裝好C語(yǔ)言,或C+,或Visual C+.3. 實(shí)驗(yàn)時(shí)間4學(xué)時(shí)4. 實(shí)驗(yàn)內(nèi)容(1) 試用手工編碼方式構(gòu)造識(shí)別以下給定單詞的某一語(yǔ)言的詞法分析程序。(2) 語(yǔ)言中具有的單詞包括五個(gè)有

4、代表性的關(guān)鍵字begin、end、if、then、else;標(biāo)識(shí)符;整型常數(shù);六種關(guān)系運(yùn)算符;一個(gè)賦值符和四個(gè)算術(shù)運(yùn)算符。參考實(shí)現(xiàn)方法簡(jiǎn)述如下。(3) 單詞的分類:構(gòu)造上述語(yǔ)言中的各類單詞符號(hào)及其分類碼表。表1 語(yǔ)言中的各類單詞符號(hào)及其分類碼表單詞符號(hào)類別編碼類別碼的助記符單詞值begin1BEGINend2ENDif3IFthen4THENelse5ELSE標(biāo)識(shí)符6ID字母打頭的字母數(shù)字串整常數(shù)7INT數(shù)字串<8LT<=9LE=10EQ<>11NE>12GT>=13GE:=14IS+15PL-16MI*17MU/18DI5、 實(shí)驗(yàn)方法與處理過(guò)程在一個(gè)程序設(shè)

5、計(jì)語(yǔ)言中,一般都含有若干類單詞符號(hào),為此可首先為每類單詞建立一張狀態(tài)轉(zhuǎn)換圖,然后將這些狀態(tài)轉(zhuǎn)換圖合并成一張統(tǒng)一的狀態(tài)圖,即得到了一個(gè)有限自動(dòng)機(jī),再進(jìn)行必要的確定化和狀態(tài)數(shù)最小化處理,最后據(jù)此構(gòu)造詞法分析程序。在此為了使詞法分析程序結(jié)構(gòu)比較清晰,且盡量避免某些枝節(jié)問(wèn)題的糾纏,假定要編譯的語(yǔ)言中,全部關(guān)鍵字都是保留字,程序員不得將它們作為源程序中的標(biāo)識(shí)符;在源程序的輸入文本中,關(guān)鍵字、標(biāo)識(shí)符、整常數(shù)之間,若未出現(xiàn)關(guān)系和算術(shù)運(yùn)算符以及賦值符,則至少須用一個(gè)空白字符加以分隔。作了這些限制以后,就可以把關(guān)鍵字和標(biāo)識(shí)符的識(shí)別統(tǒng)一進(jìn)行處理。即每當(dāng)開(kāi)始識(shí)別一個(gè)單詞時(shí),若掃視到的第一個(gè)字符為字母,則把后續(xù)輸入的

6、字母或數(shù)字字符依次進(jìn)行拼接,直至掃視到非字母、數(shù)字字符為止,以期獲得一個(gè)盡可能長(zhǎng)的字母數(shù)字字符串,然后以此字符串查所謂保留字表(此保留字表已事先造好),若查到此字符串,則取出相應(yīng)的類別碼;反之,則表明該字符串應(yīng)為一標(biāo)識(shí)符。采用上述策略后,針對(duì)表I中部分單詞可以構(gòu)造一個(gè)如圖1所示的有限自動(dòng)機(jī)(以狀態(tài)轉(zhuǎn)換圖表示)。在圖1中添加了當(dāng)進(jìn)行狀態(tài)轉(zhuǎn)移時(shí),詞法分析程序應(yīng)執(zhí)行的語(yǔ)義動(dòng)作。根據(jù)圖1,可用C語(yǔ)言編寫出符合以上幾項(xiàng)要求的一個(gè)相應(yīng)的掃描器程序,如程序一所示。圖1 識(shí)別表I所列語(yǔ)言中的部分單詞的DFA及相關(guān)的語(yǔ)義過(guò)程圖1及程序一中所出現(xiàn)的語(yǔ)義變量及語(yǔ)義函數(shù)的含義和功能說(shuō)明如下。函數(shù)GETCHAR:每調(diào)用

7、一次,就把掃描指示器當(dāng)前所指示的源程序字符送入字符變量ch,然后把掃描指示器前推一個(gè)字符位置。字符數(shù)組TOKEN:用來(lái)依次存放一個(gè)單詞詞文中的各個(gè)字符。函數(shù)CAT:每調(diào)用一次,就把當(dāng)前ch中的字符拼接于TOKEN中所存字符串的右邊。函數(shù)LOOKUP:每調(diào)用一次,就以TOKEN中的字符串查保留字表,若查到,就將相應(yīng)關(guān)鍵字的類別碼賦給整型變量c;否則將c置為零。函數(shù)RETRACT:每調(diào)用一次,就把掃描指示器回退一個(gè)字符位置(即退回多讀的那個(gè)字符)。函數(shù)OUT:一般僅在進(jìn)入終態(tài)時(shí)調(diào)用此函數(shù),調(diào)用的形式為OUT(c,VAL)。其中,實(shí)參c為相應(yīng)單詞的類別碼或其助記符;當(dāng)所識(shí)別的單詞為標(biāo)識(shí)符和整數(shù)時(shí),實(shí)

8、參VAL為TOKEN(即詞文分別為字母數(shù)字串和數(shù)字串),對(duì)于其余種類的單詞,VAL均為空串。函數(shù)OUT的功能是,在送出一個(gè)單詞的內(nèi)部表示之后,返回到調(diào)用該詞法分析程序的那個(gè)程序。程序一 根據(jù)圖1編寫的掃描器# include <stdio.h># include <ctype.h># include <string.h># define ID 6# define INT 7# define LT 8# define LE 9# define EQ 10# define NE 11# define GT 12# define GE 13char TOKEN20

9、;extern int lookup (char*);extern void out (int, char*);extern report_error (void);void scanner_example (FILE *fp)char ch; int i, c;ch=fgetc (fp);if (isalpha (ch) /*it must be a identifer!*/TOKEN0=ch; ch=fgetc (fp); i=1;while (isalnum (ch)TOKENi=ch; i+;ch=fgetc (fp);TOKENi= 0fseek(fp,-1,1); /* retra

10、ct*/c=lookup (TOKEN);if (c=0) out (ID,TOKEN); else out (c," ");elseif(isdigit(ch)TOKEN0=ch; ch=fgetc(fp); i=1;while(isdigit(ch)TOKENi=ch; i+;ch=fgetc(fp);TOKENi= 0;fseek(fp,-1,1);out(INT,TOKEN);elseswitch(ch)case : ch=fgetc(fp);if(ch=)out(LE," ");else if(ch=) out (NE," "

11、;);elsefseek (fp,-1,1);out (LT," ");break;case =: out(EQ, " "); break;case : ch=fgetc(fp);if(ch=)out(GE," ");elsefseek(fp,-1,1);out(GT," ");break;default: report_error( ); break;return;提示:掃描器所用的若干函數(shù)以及主程序有待于具體編寫,并需事先建立好保留字表,以備查詢。另外,在掃描源程序字符串時(shí),一旦識(shí)別出關(guān)鍵字、標(biāo)識(shí)符、整常數(shù)以及

12、運(yùn)算符中之一,即以二元式形式(類別編碼,值)輸出單詞。每次調(diào)用詞法分析程序,它均能自動(dòng)繼續(xù)掃描下去,形成下一個(gè)單詞,直至整個(gè)源程序全部掃描完畢,并形成相應(yīng)的單詞串形式的源程序。6、 輸出結(jié)果:以文件形式輸入的例子至少應(yīng)包含兩行以上的源代碼,并以對(duì)照的形式將掃描器的分析結(jié)果輸出,必要時(shí)給出正誤信息。例:以下例題說(shuō)明運(yùn)行時(shí)的輸入輸出效果:輸入:const a=10;var b,c;beginread(b);c:=a+b;write(c)end.輸出:(constsym ,const )(ident , a)(eql , =)(number, 10)(semicolon , ;)(varsym ,

13、var )(ident, b)(comma, , )(ident, c )(semicolon , ;)(begins ym,begin)(readsym, read )(lparen , ( )(ident, b)(rparen , ) )(semicolon , ;)(ident, c )(becomes , := )(ident, a )(plus , + )(ident, b )(semicolon , ;)(writesym ,write )(lparen , ( )(ident, c )(rparen , ) )(endsym , end )實(shí)驗(yàn)二. 自頂向下語(yǔ)法分析1. 實(shí)驗(yàn)?zāi)康?/p>

14、(1)通過(guò)設(shè)計(jì)、編制、調(diào)試一個(gè)典型的語(yǔ)法分析程序,實(shí)現(xiàn)對(duì)詞法分析程序所提供的單詞序列進(jìn)行語(yǔ)法檢查和結(jié)構(gòu)分析,進(jìn)一步掌握常用的語(yǔ)法分析方法。(2)選擇最有代表性的語(yǔ)法分析方法遞歸子程序法;選擇對(duì)各種常見(jiàn)程序語(yǔ)言都具備的語(yǔ)法結(jié)構(gòu),如賦值語(yǔ)句,特別是表達(dá)式,作為分析對(duì)象。2. 實(shí)驗(yàn)準(zhǔn)備微機(jī)CPU P4以上,256M以上內(nèi)存,安裝好C語(yǔ)言,或C+,或Visual C+.3. 實(shí)驗(yàn)時(shí)間4學(xué)時(shí)4. 實(shí)驗(yàn)內(nèi)容l 構(gòu)造遞歸下降LL(1)語(yǔ)法分析器。完成P87,例4.125. 實(shí)驗(yàn)要求l 語(yǔ)法分析器的編寫方法采用遞歸子程序法。擴(kuò)充完整例4.12的程序部分。l 輸入文法的句子,作為表達(dá)式語(yǔ)法分析器的輸入,進(jìn)行語(yǔ)法

15、解析,對(duì)于語(yǔ)法正確的表達(dá)式,報(bào)告“語(yǔ)法正確”;l 對(duì)于語(yǔ)法錯(cuò)誤的表達(dá)式,報(bào)告“語(yǔ)法錯(cuò)誤”, 指出錯(cuò)誤原因。l 把語(yǔ)法分析器設(shè)計(jì)成一個(gè)獨(dú)立一遍的過(guò)程。6. 輸入輸出輸入:至少找到2個(gè)句子,其中一個(gè)是文法的句子,另一個(gè)不是,分別輸入。輸出:對(duì)于語(yǔ)法正確的表達(dá)式,報(bào)告“語(yǔ)法正確”;對(duì)于語(yǔ)法錯(cuò)誤的表達(dá)式,報(bào)告“語(yǔ)法錯(cuò)誤”, 指出錯(cuò)誤原因。實(shí)驗(yàn)三. 自底向上語(yǔ)法分析1. 實(shí)驗(yàn)?zāi)康慕o出算符優(yōu)先關(guān)系表的構(gòu)造方法,將FIRSTVT集合和LASTVT集合的算法擴(kuò)充成程序。2. 實(shí)驗(yàn)準(zhǔn)備微機(jī)CPU P4以上,256M以上內(nèi)存,安裝好C語(yǔ)言,或C+,或Visual C+.3. 實(shí)驗(yàn)時(shí)間4學(xué)時(shí)4. 實(shí)驗(yàn)內(nèi)容構(gòu)造求FI

16、RSTVT集合和LASTVT集合的程序。5. 實(shí)驗(yàn)要求l 擴(kuò)充P113求FIRSTVT集合的算法。l 完成LASTVT集合的算法。6. 輸入輸出輸入:文法。輸出:FIRSTVT集合和LASTVT集合。實(shí)驗(yàn)四. 語(yǔ)義分析1. 實(shí)驗(yàn)?zāi)康膌 通過(guò)上機(jī)實(shí)習(xí),加深對(duì)語(yǔ)法制導(dǎo)翻譯原理的理解,掌握將語(yǔ)法分析所識(shí)別的語(yǔ)法范疇變換為某種中間代碼的語(yǔ)義翻譯方法。l 掌握目前普遍采用的語(yǔ)義分析方法語(yǔ)法制導(dǎo)翻譯技術(shù)。l 要求在語(yǔ)法分析程序中添加語(yǔ)義處理,對(duì)于語(yǔ)法正確的算術(shù)表達(dá)式,輸出其計(jì)算值。2. 實(shí)驗(yàn)準(zhǔn)備微機(jī)CPU P4以上,256M以上內(nèi)存,安裝好C語(yǔ)言,或C+,或Visual C+.3. 實(shí)驗(yàn)時(shí)間4學(xué)時(shí)4. 實(shí)

17、驗(yàn)內(nèi)容在表達(dá)式的語(yǔ)法分析程序里,添加語(yǔ)義處理部分。5. 實(shí)驗(yàn)要求l 語(yǔ)義分析對(duì)象重點(diǎn)考慮經(jīng)過(guò)語(yǔ)法分析后已是正確的語(yǔ)法范疇,實(shí)習(xí)重點(diǎn)是語(yǔ)義子程序。l 在實(shí)驗(yàn)三“語(yǔ)法分析器”的里面添加PL/0語(yǔ)言“表達(dá)式”部分的語(yǔ)義處理。l 計(jì)算表達(dá)式的語(yǔ)義值。6. 輸入輸出輸入:算術(shù)表達(dá)式,例如: 2 + 3 * 5作為輸入。輸出:17實(shí)驗(yàn)五. 中間代碼生成1. 實(shí)驗(yàn)?zāi)康囊笤谡Z(yǔ)法分析程序中添加語(yǔ)義處理,對(duì)于語(yǔ)法正確的表達(dá)式,輸出其中間代碼。2. 實(shí)驗(yàn)準(zhǔn)備微機(jī)CPU P4以上,256M以上內(nèi)存,安裝好C語(yǔ)言,或C+,或Visual C+.3. 實(shí)驗(yàn)時(shí)間4學(xué)時(shí)4. 實(shí)驗(yàn)內(nèi)容在實(shí)驗(yàn)三的表達(dá)式語(yǔ)法分析程序里,添加語(yǔ)義

18、處理部分輸出表達(dá)式的中間代碼,用四元式序列表示。5. 實(shí)驗(yàn)要求l 在實(shí)驗(yàn)三“語(yǔ)法分析器”的里面添加PL/0語(yǔ)言“表達(dá)式”部分的語(yǔ)義處理,輸出表達(dá)式的中間代碼。l 中間代碼用四元式序列表示。6. 輸入輸出輸入:表達(dá)式,例如: a * (b + c)。輸出:( + b c t1 )( * a t1 t2 )六、課程設(shè)計(jì)1、選題(四選一):(1)構(gòu)造遞歸下降分析程序語(yǔ)法分析器(2)構(gòu)造預(yù)測(cè)分析表語(yǔ)法分析器(3)構(gòu)造算符優(yōu)先分析語(yǔ)法分析器(4)構(gòu)造LR(0)分析法語(yǔ)法分析器2、設(shè)計(jì)方法: 小組分工,合作完成。從小到大,逐步擴(kuò)展。按照文法和程序的特點(diǎn),逐步完成設(shè)計(jì)和測(cè)試。3、設(shè)計(jì)報(bào)告: 應(yīng)包括:報(bào)告標(biāo)題

19、、主要工作概述、具體內(nèi)容(算法部分)、開(kāi)發(fā)經(jīng)驗(yàn)等。七、考核方式1、實(shí)驗(yàn)報(bào)告和課程設(shè)計(jì)報(bào)告實(shí)驗(yàn)獨(dú)立完成,提交實(shí)驗(yàn)報(bào)告;課程設(shè)計(jì)采用分組的形式,3人一組,每個(gè)實(shí)習(xí)小組交一份課程設(shè)計(jì)報(bào)告,格式要求絕對(duì)規(guī)范!內(nèi)容應(yīng)包括以下內(nèi)容:l 題目l 設(shè)計(jì)思想l 算法l 調(diào)試數(shù)據(jù)(輸入/輸出)2、評(píng)分標(biāo)準(zhǔn)l 由指導(dǎo)教師根據(jù)實(shí)驗(yàn)驗(yàn)收情況并結(jié)合實(shí)驗(yàn)報(bào)告質(zhì)量及學(xué)習(xí)態(tài)度等進(jìn)行評(píng)分。l 課程設(shè)計(jì)作為獨(dú)立考查課,學(xué)分為1。八、參考文獻(xiàn) 編譯原理課程組 35 of 371編譯原理(第二版),張素琴、呂映芝、蔣維杜,清華大學(xué)出版社,2005年出版。2編譯程序設(shè)計(jì)原理,杜書敏、王永寧,北京大學(xué)出版社,1988年出版。3計(jì)算機(jī)編譯原

20、理,張幸兒,科學(xué)出版社,1999年出版。4編譯程序原理與技術(shù),李贛生等,清華大學(xué)出版社,1997年10月出版。九、附錄PL0語(yǔ)言編譯源程序清單(部分)源代碼pl0c.h/* 關(guān)鍵字個(gè)數(shù) */#define norw 13/* 名字表容量 */#define txmax 100/* 所有的add1用于定義數(shù)組 */#define txmaxadd1 101/* number的最大位數(shù) */#define nmax 14/* 符號(hào)的最大長(zhǎng)度 */#define al 10/* 地址上界 */#define amax 2047/* 最大允許過(guò)程嵌套聲明層數(shù) */#define levmax 3/*

21、最多的虛擬機(jī)代碼數(shù) */#define cxmax 200#define cxmaxadd1 201/* 當(dāng)函數(shù)中會(huì)發(fā)生fatal error時(shí),返回-1告知調(diào)用它的函數(shù),最終退出程序 */#define getsymdo if(-1=getsym()return -1#define getchdo if(-1=getch()return -1#define testdo(a,b,c) if(-1=test(a,b,c)return -1#define gendo(a,b,c) if(-1=gen(a,b,c)return -1#define expressiondo(a,b,c) if(-1

22、=expression(a,b,c)return -1#define factordo(a,b,c) if(-1=factor(a,b,c)return -1#define termdo(a,b,c) if(-1=term(a,b,c)return -1#define conditiondo(a,b,c) if(-1=condition(a,b,c)return -1#define statementdo(a,b,c) if(-1=statement(a,b,c)return -1#define constdeclarationdo(a,b,c) if(-1=constdeclaration(

23、a,b,c)return -1#define vardeclarationdo(a,b,c) if(-1=vardeclaration(a,b,c)return -1typedef enum false,true bool;/* 符號(hào) */enum symbol nul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss,leq,gtr,geq,lparen,rparen,comma,semicolon,period,becomes,beginsym,endsym,ifsym,thensym,whilesym,writesym,read

24、sym,dosym,callsym,constsym,varsym,procsym;#define symnum 32/* 名字表中的類型 */enum object constant,variable,procedur;/* 虛擬機(jī)代碼 */enum fct lit,opr,lod,sto,cal,inte,jmp,jpc;#define fctnum 8/* 虛擬機(jī)代碼結(jié)構(gòu) */struct instructionenum fct f; /* 虛擬機(jī)代碼指令 */int l; /* 引用層與聲明層的層次差 */int a; /* 根據(jù)f的不同而不同 */;FILE* fas;/* 輸出名字

25、表 */FILE* fa; /* 輸出虛擬機(jī)代碼 */FILE* fa1; /* 輸出源文件及其各行對(duì)應(yīng)的首地址 */FILE* fa2; /* 輸出結(jié)果 */bool listswitch; /* 顯示虛擬機(jī)代碼與否 */bool tableswitch; /* 顯示名字表與否 */char ch; /* 獲取字符的緩沖區(qū),getch 使用 */enum symbol sym; /* 當(dāng)前的符號(hào) */char idal; /* 當(dāng)前ident */int num; /* 當(dāng)前number */int cc,ll,kk; /* getch使用的計(jì)數(shù)器,cc表示當(dāng)前字符(ch)的位置 */int

26、 cx; /* 虛擬機(jī)代碼指針 */char line81; /* 讀取行緩沖區(qū) */char aal; /* 臨時(shí)符號(hào) */struct instruction codecxmaxadd1; /* 存放虛擬機(jī)代碼的數(shù)組 */char wordnorwal; /* 保留字 */enum symbol wsymnorw; /* 保留字對(duì)應(yīng)的符號(hào)值 */enum symbol ssym256; /* 單字符的符號(hào)值 */char mnemonicfctnum5; /* 虛擬機(jī)代碼指令名稱 */bool declbegsyssymnum; /* 表示聲明開(kāi)始的符號(hào)集合 */bool statbegs

27、yssymnum; /* 表示語(yǔ)句開(kāi)始的符號(hào)集合 */bool facbegsyssymnum; /* 表示因子開(kāi)始的符號(hào)集合 */* 名字表結(jié)構(gòu) */struct tablestructchar nameal;/* 名字 */enum object kind;/* 類型:const,var or procedure */int val; /* 數(shù)值,僅const使用 */int level; /* 所處層,僅const不使用 */int adr; /* 地址,僅const不使用 */int size; /* 需要分配的數(shù)據(jù)區(qū)空間,僅procedure使用 */;struct tablestr

28、uct tabletxmaxadd1; /* 名字表 */FILE* fin;FILE* fout;char fnameal;int err; /* 錯(cuò)誤計(jì)數(shù)器 */void error(int n); int getsym();int getch();void init();int gen(enum fct x,int y,int z);int test(bool* s1,bool* s2,int n);int inset(int e,bool* s);int addset(bool* sr,bool* s1,bool* s2,int n);int subset(bool* sr,bool*

29、 s1,bool* s2,int n);int mulset(bool* sr,bool* s1,bool* s2,int n);int block(int lev,int tx,bool* fsys);void interpret();int factor(bool* fsys,int* ptx,int lev);int term(bool* fsys,int* ptx,int lev);int condition(bool* fsys,int* ptx,int lev);int expression(bool* fsys,int* ptx,int lev);int statement(bo

30、ol* fsys,int* ptx,int lev);void listcode(int cx0);int vardeclaration(int* ptx,int lev,int* pdx);int constdeclaration(int* ptx,int lev,int* pdx);int postion(char* idt,int tx);void enter(enum object k,int* ptx,int lev,int* pdx);int base(int l,int* s,int b);pl0c.c/* Windows 下c語(yǔ)言PL/0編譯程序在Visual C+ 6.0和V

31、isual C.NET上運(yùn)行通過(guò)使用方法:運(yùn)行后輸入PL/0源程序文件名回答是否輸出虛擬機(jī)代碼回答是否輸出名字表fa.tmp輸出虛擬機(jī)代碼fa1.tmp輸出源文件及其各行對(duì)應(yīng)的首地址fa2.tmp輸出結(jié)果fas.tmp輸出名字表*/#include <stdio.h>#include "pl0c.h"#include "string.h"/* 解釋執(zhí)行時(shí)使用的棧 */#define stacksize 500 int main()bool nxtlevsymnum;init();/* 初始化 */fas=fopen("fas.tmp

32、","w");fa1=fopen("fa1.tmp","w");printf("Input file? ");fprintf(fa1,"Input file? ");scanf("%s",fname);/* 輸入文件名 */fin=fopen(fname,"r");if(fin)fprintf(fa1,"%sn",fname);printf("List object code?(Y/N)");/* 是否輸出

33、虛擬機(jī)代碼 */scanf("%s",fname);listswitch=(fname0='y'|fname0='Y');printf("List symbol table?(Y/N)");/* 是否輸出名字表 */scanf("%s",fname);tableswitch=(fname0='y'|fname0='Y');err=0;cc=cx=ll=0;ch=' 'kk=al-1;if(-1!=getsym()fa=fopen("fa.tmp&

34、quot;,"w");fa2=fopen("fa2.tmp","w");addset(nxtlev,declbegsys,statbegsys,symnum);nxtlevperiod=true;if(-1=block(0,0,nxtlev)/* 調(diào)用編譯程序 */fclose(fa);fclose(fa1);fclose(fin);printf("n");return 0;fclose(fa);fclose(fa1);if(sym!=period)error(9);if(err=0)interpret();/*

35、調(diào)用解釋執(zhí)行程序 */elseprintf("Errors in pl/0 program");fclose(fin);elseprintf("Can't open file!n");fprintf(fa1,"Can't open file!n");fclose(fa1);fclose(fas);printf("n");return 0;/* 在適當(dāng)?shù)奈恢蔑@示錯(cuò)誤 */void error(int n)char space81;memset(space,32,81);spacecc-1=0; /*

36、出錯(cuò)時(shí)當(dāng)前符號(hào)已經(jīng)讀完,所以cc-1 */ printf("*%s!%dn",space,n);fprintf(fa1,"*%s!%dn",space,n);err+;/* 詞法分析,獲取一個(gè)符號(hào) */int getsym()int i,j,k;while(ch=' '|ch=10|ch=9)/* 忽略空格、換行和TAB */getchdo;if(ch>='a'&&ch<='z')/* 名字或保留字以a.z開(kāi)頭 */k=0;doif(k<al)ak=ch;k+;getchd

37、o;while(ch>='a'&&ch<='z'|ch>='0'&&ch<='9');ak=0;strcpy(id,a);i=0;j=norw-1;do /* 搜索當(dāng)前符號(hào)是否為保留字 */k=(i+j)/2;if(strcmp(id,wordk)<=0)j=k-1;if(strcmp(id,wordk)>=0)i=k+1;while(i<=j);if(i-1>j)sym=wsymk; else sym=ident; /* 搜索失敗則,是名字或數(shù)字 *

38、/elseif(ch>='0'&&ch<='9')/* 檢測(cè)是否為數(shù)字:以0.9開(kāi)頭 */k=0;num=0;sym=number;donum=10*num+ch-'0'k+;getchdo;while(ch>='0'&&ch<='9'); /* 獲取數(shù)字的值 */k-;if(k>nmax)error(30);elseif(ch=':')/* 檢測(cè)賦值符號(hào) */getchdo;if(ch='=')sym=becomes;g

39、etchdo;elsesym=nul;/* 不能識(shí)別的符號(hào) */elseif(ch='<')/* 檢測(cè)小于或小于等于符號(hào) */getchdo;if(ch='=')sym=leq;getchdo;elsesym=lss;elseif(ch='>')/* 檢測(cè)大于或大于等于符號(hào) */getchdo;if(ch='=')sym=geq;getchdo;elsesym=gtr;elsesym=ssymch;/* 當(dāng)符號(hào)不滿足上述條件時(shí),全部按照單字符符號(hào)處理 */getchdo;return 0;/* 編譯程序主體 */int

40、 block(int lev, /* 當(dāng)前分程序所在層 */ int tx, /* 名字表當(dāng)前尾指針 */ bool* fsys /* 當(dāng)前模塊后跟符號(hào)集合 */ )int i;int dx; /* 名字分配到的相對(duì)地址 */int tx0; /* 保留初始tx */int cx0; /* 保留初始cx */bool nxtlevsymnum; /* 在下級(jí)函數(shù)的參數(shù)中,符號(hào)集合均為值參,但由于使用數(shù)租實(shí)現(xiàn), 傳遞進(jìn)來(lái)的是指針,為防止下級(jí)函數(shù)改變上級(jí)函數(shù)的集合,開(kāi)辟新的空間 傳遞給下級(jí)函數(shù),之后所有的nxtlev都是這樣 */dx=3; tx0=tx;/* 記錄本層名字的初始位置 */tabl

41、etx.adr=cx;gendo(jmp,0,0);if(lev>levmax)error(32);doif(sym=constsym)/* 收到常量聲明符號(hào),開(kāi)始處理常量聲明 */getsymdo;doconstdeclarationdo(&tx,lev,&dx);/* dx的值會(huì)被constdeclaration改變,使用指針 */while(sym=comma) getsymdo;constdeclarationdo(&tx,lev,&dx);if(sym=semicolon)getsymdo;else error(5);while(sym=iden

42、t);if(sym=varsym)/* 收到變量聲明符號(hào),開(kāi)始處理變量聲明 */getsymdo;dovardeclarationdo(&tx,lev,&dx);while(sym=comma) getsymdo;vardeclarationdo(&tx,lev,&dx);if(sym=semicolon)getsymdo;else error(5);while(sym=ident);while(sym=procsym) /* 收到過(guò)程聲明符號(hào),開(kāi)始處理過(guò)程聲明 */getsymdo;if(sym=ident)enter(procedur,&tx,lev

43、,&dx);/* 記錄過(guò)程名字 */getsymdo;else error(4);/* procedure后應(yīng)為標(biāo)識(shí)符 */if(sym=semicolon)getsymdo;else error(5);/* 漏掉了分號(hào) */memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevsemicolon=true;if(-1=block(lev+1,tx,nxtlev)return -1;/* 遞歸調(diào)用 */if(sym=semicolon)getsymdo;memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);nx

44、tlevident=true;nxtlevprocsym=true;testdo(nxtlev,fsys,6);else error(5);/* 漏掉了分號(hào) */memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);nxtlevident=true;testdo(nxtlev,declbegsys,7);while(inset(sym,declbegsys);/* 直到?jīng)]有聲明符號(hào) */codetabletx0.adr.a=cx;/* 開(kāi)始生成當(dāng)前過(guò)程代碼 */tabletx0.adr=cx;/* 當(dāng)前過(guò)程代碼地址 */tabletx0.size=dx;/

45、* 聲明部分中每增加一條聲明都會(huì)給dx增加1,聲明部分已經(jīng)結(jié)束,dx就是當(dāng)前過(guò)程數(shù)據(jù)的size */cx0=cx;gendo(inte,0,dx);/* 生成分配內(nèi)存代碼 */* 語(yǔ)句后跟符號(hào)為分號(hào)或end */memcpy(nxtlev,fsys,sizeof(bool)*symnum);/* 每個(gè)后跟符號(hào)集和都包含上層后跟符號(hào)集和,以便補(bǔ)救 */nxtlevsemicolon=true;nxtlevendsym=true;statementdo(nxtlev,&tx,lev);gendo(opr,0,0);/* 每個(gè)過(guò)程出口都要使用的釋放數(shù)據(jù)段指令 */memset(nxtlev,

46、0,sizeof(bool)*symnum);/*分程序沒(méi)有補(bǔ)救集合 */testdo(fsys,nxtlev,8);/* 檢測(cè)后跟符號(hào)正確性 */listcode(cx0);/* 輸出代碼 */return 0;/* 初始化 */void init()int i;/* 設(shè)置單字符符號(hào) */for(i=0;i<=255;i+)ssymi=nul;ssym'+'=plus;ssym'-'=minus;ssym'*'=times;ssym'/'=slash;ssym'('=lparen;ssym')

47、9;=rparen;ssym'='=eql;ssym','=comma;ssym'.'=period;ssym'#'=neq;ssym''=semicolon;/* 設(shè)置保留字名字 */strcpy(&(word00),"begin");strcpy(&(word10),"call");strcpy(&(word20),"const");strcpy(&(word30),"do");strcpy(&

48、;(word40),"end");strcpy(&(word50),"if");strcpy(&(word60),"odd");strcpy(&(word70),"procedure");strcpy(&(word80),"read");strcpy(&(word90),"then");strcpy(&(word100),"var");strcpy(&(word110),"while&quo

49、t;);strcpy(&(word120),"write");/* 設(shè)置保留字符號(hào) */wsym0=beginsym;wsym1=callsym;wsym2=constsym;wsym3=dosym;wsym4=endsym;wsym5=ifsym;wsym6=oddsym;wsym7=procsym;wsym8=readsym;wsym9=thensym;wsym10=varsym;wsym11=whilesym;wsym12=writesym;/* 設(shè)置指令名稱 */strcpy(&(mnemoniclit0),"lit");strc

50、py(&(mnemonicopr0),"opr");strcpy(&(mnemoniclod0),"lod");strcpy(&(mnemonicsto0),"sto");strcpy(&(mnemoniccal0),"cal");strcpy(&(mnemonicinte0),"int");strcpy(&(mnemonicjmp0),"jmp");strcpy(&(mnemonicjpc0),"jpc&qu

51、ot;);/* 供getsym取一個(gè)字符,每次讀一行,存入line緩沖區(qū),line被getsym取空時(shí) 再讀一行*/int getch()if(cc=ll)if(feof(fin)printf("program incomplete");return -1;ll=0;cc=0;printf("%d ",cx);fprintf(fa1,"%d ",cx);ch=' 'while(ch!=10)fscanf(fin,"%c",&ch);printf("%c",ch);fprintf(fa1,"%c",ch);linell=ch;ll+;printf("n");fprintf(fa1,"n");ch=linecc;cc+;return 0;/* 生成一項(xiàng)名字表 */void enter(enum object k,/* 名字種類const,var or procedure */ int* ptx,/* 名字表尾指針的指針,為了可以改變名字表尾指針的值,以后所

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 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ì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論