




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、編編 譯譯 原原 理理 實驗指導書實驗指導書 上海大學計算機學院 編譯原理課程組 2010 年 10 月 目錄目錄 一、課程簡介.2 二、實驗?zāi)康?2 三、實驗環(huán)境.2 四、實驗任務(wù).2 五、PL0 語言簡介.2 1PL/0 語言文法的 EBNF.3 2PL/0 語言的詞匯表.4 六、實驗項目.5 實驗一. 詞法分析.5 實驗二. 語法分析.8 實驗三. 詞法、語法分析.10 實驗四. 語義分析.11 實驗五. 中間代碼生成.12 七、考核方式.13 八、參考文獻.14 九、附錄PL0 語言編譯源程序清單.15 編譯原理實驗指導編譯原理實驗指導 一、課程簡介一、課程簡介 1.1. 課程名稱:課
2、程名稱:編譯原理(Principle of Compiler) 2.2. 課程編碼:課程編碼: 3.3. 課程總學時課程總學時: 60 學時理論: 40 學時;實驗: 20 學時 4.4. 課程總學分課程總學分: 5 學分 二、實驗?zāi)慷嶒災(zāi)康牡?編譯原理是計算機類專業(yè)特別是計算機軟件專業(yè)的一門重要專業(yè)課。設(shè)置 該課程的目的在于系統(tǒng)地向?qū)W生講述編譯系統(tǒng)的結(jié)構(gòu)、工作流程及編譯程序各 組成部分的設(shè)計原理和實現(xiàn)技術(shù),使學生通過學習既掌握編譯理論和方法方面 的基本知識,也具有設(shè)計、實現(xiàn)、分析和維護編譯程序等方面的初步能力。編 譯原理是一門理論性和實踐性都比較強的課程。進行上機實驗的目的是使學生 通過
3、完成上機實驗題目加深對課堂教學內(nèi)容的理解。同時培養(yǎng)學生實際動手能 力。 三、實驗環(huán)境三、實驗環(huán)境 微機 CPU P4 以上,256M 以上內(nèi)存,安裝好 C 語言,或 C+,或 Visual C+開發(fā)環(huán)境。 四、實驗任務(wù)四、實驗任務(wù) 用 C/C+/Visual C+語言編寫 PL0 語言的詞法分析程序、語法分析程序、 語義分析程序、中間代碼生成程序。 五、五、PL0 語言簡介語言簡介 PL0 語言功能簡單、結(jié)構(gòu)清晰、可讀性強,而又具備了一般高級程序設(shè)計 語言的必須部分,因而 PL0 語言的編譯程序能充分體現(xiàn)一個高級語言編譯程序 實現(xiàn)的基本方法和技術(shù)。 1PL/0 語言文法的語言文法的 EBNF
4、:=. := :=CONST,; := := :=VAR , ; :=| :=; ; :=PROCEDURE ; :=| | :=:= :=BEGIN ; END := |ODD := +|- := := | () := +|- := *|/ := =|#|= := IF THEN := CALL 標識符 := WHILE DO := READ(,) := WRITE(,) := a|b|X|Y|Z := 0|1|8|9 2PL/0 語言的詞匯表語言的詞匯表 序 號 類 別 單詞編碼 1基 本 字 begin, call, const, do, end if, odd, procedure,
5、read then, var, while, write beginsym, callsym, constsym dosym, endsym, ifsym, oddsym proceduresym, readsym, thensym varsym, whilesym, writesym 2標 識 符 ident 3常 數(shù) number 4運 算 符 +, -, *, /, odd =, , , , =, := plus, minus, times, slash, oddsym eql, neq, lss, leq, gtr, geq, becomes 5界 符 ( ) , ;.Lparen,
6、rparen, comma, semicolon period 六、實驗項目六、實驗項目 實驗實驗一一. 詞法分析詞法分析 1.實驗?zāi)康膶嶒災(zāi)康?根據(jù) PL/0 語言的文法規(guī)范,編寫 PL/0 語言的詞法分析程序。 通過設(shè)計調(diào)試詞法分析程序,實現(xiàn)從源程序中分出各種單詞的方法; 加深對課堂教學的理解;提高詞法分析方法的實踐能力。 掌握從源程序文件中讀取有效字符的方法和產(chǎn)生源程序的內(nèi)部表示 文件的法。 掌握詞法分析的實現(xiàn)方法。 上機調(diào)試編出的詞法分析程序。 2.實驗準備實驗準備 微機 CPU P4 以上,256M 以上內(nèi)存,安裝好 C 語言,或 C+,或 Visual C+. 3.實驗時間實驗時間
7、 4 學時 4.實驗內(nèi)容實驗內(nèi)容 已給 PL/0 語言文法,輸出單詞符號(關(guān)鍵字、專用符號以及其它標記) 。 5.實驗要求實驗要求 確定編譯中使用的表格、標識符與關(guān)鍵字的區(qū)分方法等。 把詞法分析器設(shè)計成一個獨立一遍的過程。 詞法分析器的輸出形式采用二元式序列,即: (單詞種類, 單詞的值) 6.輸入輸出輸入輸出 輸入:PL/0 源程序。例: const a=10; var b,c; begin read(b); c:=a+b; write(c) end. 輸出: (constsym,const) (ident , a) (eql , =) (number, 10) (semicolon, ;)
8、 (varsym, var ) (ident, b) (comma, , ) (ident, c ) (semicolon, ;) (beginsym,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 ) (
9、period, .) 實驗二實驗二. 語法分析語法分析 1.實驗?zāi)康膶嶒災(zāi)康?給出 PL/0 文法規(guī)范,要求編寫 PL/0 語言的語法分析程序。 通過設(shè)計、編制、調(diào)試一個典型的語法分析程序,實現(xiàn)對詞法分析 程序所提供的單詞序列進行語法檢查和結(jié)構(gòu)分析,進一步掌握常用 的語法分析方法。 選擇最有代表性的語法分析方法,如遞歸子程序法;選擇對各種常 見程序語言都具備的語法結(jié)構(gòu),如賦值語句,特別是表達式,作為 分析對象。 2.實驗準備實驗準備 微機 CPU P4 以上,256M 以上內(nèi)存,安裝好 C 語言,或 C+,或 Visual C+. 3.實驗時間實驗時間 4 學時 4.實驗內(nèi)容實驗內(nèi)容 已給 P
10、L/0 語言文法,構(gòu)造表達式部分的語法分析器。 分析對象算術(shù)表達式的 BNF 定義如下: := +|- := := | () := +|- := *|/ := =|#|= 5.實驗要求實驗要求 將實驗一“詞法分析”的輸出結(jié)果,作為表達式語法分析器的輸入, 進行語法解析,對于語法正確的表達式,報告“語法正確” ; 對于語法錯誤的表達式,報告“語法錯誤” , 指出錯誤原因。 把語法分析器設(shè)計成一個獨立一遍的過程。 語法分析器的編寫方法采用遞歸子程序法。 6.輸入輸出輸入輸出 輸入: PL/0 表達式,用實驗一的輸出形式作為輸入。例如: 對于 PL/0 表 達式, (a+15)*b 用下列形式作為輸
11、入: (lparen,( ) (ident, a) (plus, + ) (number, 15) (rparen,) ) (times, * ) (ident, b ) 輸出: 對于語法正確的表達式,報告“語法正確” ; 對于語法錯誤的表達式,報告“語法錯誤” , 指出錯誤原因。 有余力的同學,可適當擴大分析對象。譬如:有余力的同學,可適當擴大分析對象。譬如: 算術(shù)表達式中變量名可以是一般標識符,還可含一般常數(shù)、數(shù) 組元素、函數(shù)調(diào)用等等。 除算術(shù)表達式外,還可擴充分析布爾、字符、位等不同類型的 各種表達式。 加強語法檢查,盡量多和確切地指出各種錯誤。 實驗實驗三三. 詞法、詞法、語法分析語法
12、分析 1.實驗?zāi)康膶嶒災(zāi)康?給出 PL/0 文法規(guī)范,要求結(jié)合編寫 PL/0 語言的詞法、語法分析程序。 2.實驗準備實驗準備 微機 CPU P4 以上,256M 以上內(nèi)存,安裝好 C 語言,或 C+,或 Visual C+. 3.實驗時間實驗時間 4 學時 4.實驗內(nèi)容實驗內(nèi)容 已給 PL/0 語言文法,構(gòu)造表達式部分的詞法和語法分析器。 5.實驗要求實驗要求 將實驗一“詞法分析器”與實驗二“語法分析器”之間的銜接方式 由獨立一遍改為獨立子程序。 語法分析器的編寫方法采用遞歸子程序法。 6.輸入輸出輸入輸出 輸入: PL/0 表達式源語言,例如: (a+15)*b 作為輸入。 輸出: 對于語
13、法正確的表達式,報告“語法正確” ; 對于語法錯誤的表達式,報告“語法錯誤” , 指出錯誤原因。 實驗四實驗四. 語義分析語義分析 1.實驗?zāi)康膶嶒災(zāi)康?通過上機實習,加深對語法制導翻譯原理的理解,掌握將語法分析 所識別的語法范疇變換為某種中間代碼的語義翻譯方法。 掌握目前普遍采用的語義分析方法語法制導翻譯技術(shù)。 給出 PL/0 文法規(guī)范,要求在語法分析程序中添加語義處理,對于 語法正確的算術(shù)表達式,輸出其計算值。 2.實驗準備實驗準備 微機 CPU P4 以上,256M 以上內(nèi)存,安裝好 C 語言,或 C+,或 Visual C+. 3.實驗時間實驗時間 4 學時 4.實驗內(nèi)容實驗內(nèi)容 已給
14、 PL/0 語言文法,在表達式的語法分析程序里,添加語義處理部分。 5.實驗要求實驗要求 語義分析對象重點考慮經(jīng)過語法分析后已是正確的語法范疇,實習 重點是語義子程序。 在實驗三“語法分析器”的里面添加 PL/0 語言“表達式”部分的 語義處理。 計算表達式的語義值。 6.輸入輸出輸入輸出 輸入: PL/0 算術(shù)表達式,例如: 2 + 3 * 5 作為輸入。 輸出: 17 實驗五實驗五. 中間代碼生成中間代碼生成 1.實驗?zāi)康膶嶒災(zāi)康?給出 PL/0 文法規(guī)范,要求在語法分析程序中添加語義處理,對于語法 正確的表達式,輸出其中間代碼。 2.實驗準備實驗準備 微機 CPU P4 以上,256M
15、以上內(nèi)存,安裝好 C 語言,或 C+,或 Visual C+. 3.實驗時間實驗時間 4 學時 4.實驗內(nèi)容實驗內(nèi)容 已給 PL/0 語言文法,在實驗三的表達式語法分析程序里,添加語義處 理部分輸出表達式的中間代碼,用四元式序列表示。 5.實驗要求實驗要求 在實驗三“語法分析器”的里面添加 PL/0 語言“表達式”部分的 語義處理,輸出表達式的中間代碼。 中間代碼用四元式序列表示。 6.輸入輸出輸入輸出 輸入: PL/0 表達式,例如: a * (b + c) 。 輸出: ( + b c t1 ) ( * a t1 t2 ) 七、考核方式七、考核方式 1.實驗報告實驗報告 實驗采用分組的形式,
16、每個實習小組交一份實驗報告,應(yīng)包括以下內(nèi)容: 題目 設(shè)計思想 算法 調(diào)試數(shù)據(jù)(輸入/輸出) 2.評分標準評分標準 由指導教師根據(jù)實驗驗收情況并結(jié)合實驗報告質(zhì)量及學習態(tài)度等采 用 5 級記分制評分。 實驗成績占期終綜合測評成績的 30%. 八八、參考文獻、參考文獻 1編譯原理 (第二版) ,張素琴、呂映芝、蔣維杜,清華大學出版社, 2005 年出版。 2編譯程序設(shè)計原理 ,杜書敏、王永寧,北京大學出版社,1988 年出 版。 3計算機編譯原理 ,張幸兒,科學出版社,1999 年出版。 4編譯程序原理與技術(shù) ,李贛生等,清華大學出版社,1997 年 10 月出 版。 九、附錄九、附錄PL0 語言編
17、譯源程序清單語言編譯源程序清單(部分)(部分) 源代碼源代碼 pl0c.h /* 關(guān)鍵字個數(shù) */ #define norw 13 /* 名字表容量 */ #define txmax 100 /* 所有的add1用于定義數(shù)組 */ #define txmaxadd1 101 /* number的最大位數(shù) */ #define nmax 14 /* 符號的最大長度 */ #define al 10 /* 地址上界 */ #define amax 2047 /* 最大允許過程嵌套聲明層數(shù) */ #define levmax 3 /* 最多的虛擬機代碼數(shù) */ #define cxmax 200 #
18、define cxmaxadd1 201 /* 當函數(shù)中會發(fā)生fatal error時,返回-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=expression(a,b,c)return
19、 -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(a,b,c)return -1 #de
20、fine vardeclarationdo(a,b,c) if(-1=vardeclaration(a,b,c)return -1 typedef enum false,true bool; /* 符號 */ 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,readsym,dosym,call
21、s ym,constsym,varsym,procsym; #define symnum 32 /* 名字表中的類型 */ enum object constant,variable,procedur; /* 虛擬機代碼 */ enum fct lit,opr,lod,sto,cal,inte,jmp,jpc; #define fctnum 8 /* 虛擬機代碼結(jié)構(gòu) */ struct instruction enum fct f; /* 虛擬機代碼指令 */ int l; /* 引用層與聲明層的層次差 */ int a; /* 根據(jù)f的不同而不同 */ ; FILE* fas;/* 輸出名字
22、表 */ FILE* fa; /* 輸出虛擬機代碼 */ FILE* fa1; /* 輸出源文件及其各行對應(yīng)的首地址 */ FILE* fa2; /* 輸出結(jié)果 */ bool listswitch; /* 顯示虛擬機代碼與否 */ bool tableswitch; /* 顯示名字表與否 */ char ch; /* 獲取字符的緩沖區(qū),getch 使用 */ enum symbol sym; /* 當前的符號 */ char idal; /* 當前ident */ int num; /* 當前number */ int cc,ll,kk; /* getch使用的計數(shù)器,cc表示當前字符(ch
23、)的位置 */ int cx; /* 虛擬機代碼指針 */ char line81; /* 讀取行緩沖區(qū) */ char aal; /* 臨時符號 */ struct instruction codecxmaxadd1; /* 存放虛擬機代碼的數(shù)組 */ char wordnorwal; /* 保留字 */ enum symbol wsymnorw; /* 保留字對應(yīng)的符號值 */ enum symbol ssym256; /* 單字符的符號值 */ char mnemonicfctnum5; /* 虛擬機代碼指令名稱 */ bool declbegsyssymnum; /* 表示聲明開始的符
24、號集合 */ bool statbegsyssymnum; /* 表示語句開始的符號集合 */ bool facbegsyssymnum; /* 表示因子開始的符號集合 */ /* 名字表結(jié)構(gòu) */ struct tablestruct char nameal;/* 名字 */ enum object kind;/* 類型:const,var or procedure */ int val; /* 數(shù)值,僅const使用 */ int level; /* 所處層,僅const不使用 */ int adr; /* 地址,僅const不使用 */ int size; /* 需要分配的數(shù)據(jù)區(qū)空間,僅
25、procedure使用 */ ; struct tablestruct tabletxmaxadd1; /* 名字表 */ FILE* fin; FILE* fout; char fnameal; int err; /* 錯誤計數(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* s
26、1,bool* s2,int n); int subset(bool* sr,bool* 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 expre
27、ssion(bool* fsys,int* ptx,int lev); int statement(bool* 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,i
28、nt* s,int b); pl0c.c /* Windows 下c語言PL/0編譯程序 在Visual C+ 6.0和Visual C.NET上運行通過 使用方法: 運行后輸入PL/0源程序文件名 回答是否輸出虛擬機代碼 回答是否輸出名字表 fa.tmp輸出虛擬機代碼 fa1.tmp輸出源文件及其各行對應(yīng)的首地址 fa2.tmp輸出結(jié)果 fas.tmp輸出名字表 */ #include #include pl0c.h #include string.h /* 解釋執(zhí)行時使用的棧 */ #define stacksize 500 int main() bool nxtlevsymnum; in
29、it();/* 初始化 */ fas=fopen(fas.tmp,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);/* 是否輸出虛擬機代碼 */ scanf(%s,fname); listswitch=(fname0=y|fname0=Y); printf(List symbo
30、l 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,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); fclos
31、e(fin); printf(n); return 0; fclose(fa); fclose(fa1); if(sym!=period)error(9); if(err=0)interpret(); /* 調(diào)用解釋執(zhí)行程序 */ else printf(Errors in pl/0 program); fclose(fin); else printf(Cant open file!n); fprintf(fa1,Cant open file!n); fclose(fa1); fclose(fas); printf(n); return 0; /* 在適當?shù)奈恢蔑@示錯誤 */ void err
32、or(int n) char space81; memset(space,32,81); spacecc-1=0; /* 出錯時當前符號已經(jīng)讀完,所以cc-1 */ printf(*%s!%dn,space,n); fprintf(fa1,*%s!%dn,space,n); err+; /* 詞法分析,獲取一個符號 */ int getsym() int i,j,k; while(ch= |ch=10|ch=9)/* 忽略空格、換行和TAB */ getchdo; if(ch=a do if(k=a ak=0; strcpy(id,a); i=0; j=norw-1; do /* 搜索當前符號
33、是否為保留字 */ k=(i+j)/2; if(strcmp(id,wordk)=0)i=k+1; while(ij)sym=wsymk; else sym=ident; /* 搜索失敗則,是名字或數(shù)字 */ else if(ch=0 else if(ch=:)/* 檢測賦值符號 */ getchdo; if(ch=) sym=becomes; getchdo; else sym=nul; /* 不能識別的符號 */ else if(ch=)/* 檢測大于或大于等于符號 */ getchdo; if(ch=) sym=geq; getchdo; else sym=gtr; else sym=s
34、symch;/* 當符號不滿足上述條件時,全部按照單字符符號 處理 */ getchdo; return 0; /* 編譯程序主體 */ int block(int lev, /* 當前分程序所在層 */ int tx, /* 名字表當前尾指針 */ bool* fsys /* 當前模塊后跟符號集合 */ ) int i; int dx; /* 名字分配到的相對地址 */ int tx0; /* 保留初始tx */ int cx0; /* 保留初始cx */ bool nxtlevsymnum; /* 在下級函數(shù)的參數(shù)中,符號集合均為值參,但由于使用數(shù)租實現(xiàn), 傳遞進來的是指針,為防止下級函數(shù)
35、改變上級函數(shù)的集合,開辟新的空 間 傳遞給下級函數(shù),之后所有的nxtlev都是這樣 */ dx=3; tx0=tx;/* 記錄本層名字的初始位置 */ tabletx.adr=cx; gendo(jmp,0,0); if(levlevmax)error(32); do if(sym=constsym)/* 收到常量聲明符號,開始處理常量聲明 */ getsymdo; do constdeclarationdo( /* dx的值會被constdeclaration改變,使用 指針 */ while(sym=comma) getsymdo; constdeclarationdo( if(sym=s
36、emicolon) getsymdo; else error(5); while(sym=ident); if(sym=varsym)/* 收到變量聲明符號,開始處理變量聲明 */ getsymdo; do vardeclarationdo( while(sym=comma) getsymdo; vardeclarationdo( if(sym=semicolon) getsymdo; else error(5); while(sym=ident); while(sym=procsym) /* 收到過程聲明符號,開始處理過程聲明 */ getsymdo; if(sym=ident) enter
37、(procedur,/* 記錄過程名字 */ getsymdo; else error(4);/* procedure后應(yīng)為標識符 */ if(sym=semicolon) getsymdo; else error(5);/* 漏掉了分號 */ 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)
38、*symnum); nxtlevident=true; nxtlevprocsym=true; testdo(nxtlev,fsys,6); else error(5);/* 漏掉了分號 */ memcpy(nxtlev,statbegsys,sizeof(bool)*symnum); nxtlevident=true; testdo(nxtlev,declbegsys,7); while(inset(sym,declbegsys);/* 直到?jīng)]有聲明符號 */ codetabletx0.adr.a=cx;/* 開始生成當前過程代碼 */ tabletx0.adr=cx; /* 當前過程代碼地
39、址 */ tabletx0.size=dx;/* 聲明部分中每增加一條聲明都會給dx增加1,聲明部分已經(jīng)結(jié)束,dx就 是當前過程數(shù)據(jù)的size */ cx0=cx; gendo(inte,0,dx);/* 生成分配內(nèi)存代碼 */ /* 語句后跟符號為分號或end */ memcpy(nxtlev,fsys,sizeof(bool)*symnum);/* 每個后跟符號集和都包含上層后跟符號集和,以 便補救 */ nxtlevsemicolon=true; nxtlevendsym=true; statementdo(nxtlev, gendo(opr,0,0);/* 每個過程出口都要使用的釋放數(shù)
40、據(jù)段指令 */ memset(nxtlev,0,sizeof(bool)*symnum);/*分程序沒有補救集合 */ testdo(fsys,nxtlev,8); /* 檢測后跟符號正確性 */ listcode(cx0);/* 輸出代碼 */ return 0; /* 初始化 */ void init() int i; /* 設(shè)置單字符符號 */ for(i=0;iamax) error(31);/* 數(shù)值越界 */ num=0; table(*ptx).val=num; break; case variable:/* 變量名字 */ table(*ptx).level=lev; tabl
41、e(*ptx).adr=(*pdx); (*pdx)+; break; case procedur:/*過程名字*/ table(*ptx).level=lev; break; /* 查找名字的位置 */ /* 找到則返回在名字表中的位置,否則返回0 */ int postion(char* idt, /* 要查找的名字 */ int tx/* 當前名字表尾指針 */ ) int i; strcpy(,idt); i=tx; while(strcmp(,idt)!=0)i-; return i; /* 常量聲明處理 */ int constdecla
42、ration(int* ptx, int lev, int* pdx) if(sym=ident) getsymdo; if(sym=eql|sym=becomes) if(sym=becomes)error(1);/* 把=寫成了:= */ getsymdo; if(sym=number) enter(constant,ptx,lev,pdx); getsymdo; else error(2);/* 常量說明=后應(yīng)是數(shù)字 */ else error(3);/* 常量說明標識后應(yīng)是= */ else error(4);/* const后應(yīng)是標識 */ return 0; /* 變量聲明處理 *
43、/ int vardeclaration(int* ptx,int lev,int* pdx) if(sym=ident) enter(variable,ptx,lev,pdx);/* 填寫名字表 */ getsymdo; else error(4);/* var后應(yīng)是標識 */ return 0; /* 語句處理 */ int statement(bool* fsys,int* ptx,int lev) /* 參數(shù)意義見block和enter函數(shù) */ int i,cx1,cx2; bool nxtlevsymnum;/*意義見block函數(shù) */ if(sym=ident)/* 準備按照賦
44、值語句處理 */ i=postion(id,*ptx); if(i=0)error(11); /* 變量未找到 */ else if(tablei.kind!=variable) error(12);/* 賦值語句格式錯誤 */ i=0; getsymdo; if(sym=becomes) getsymdo; else error(13);/* 檢測賦值符號 */ memcpy(nxtlev,fsys,sizeof(bool)*symnum); expressiondo(nxtlev,ptx,lev);/* 處理賦值符號右側(cè)表達式 */ if(i!=0) gendo(sto,lev-table
45、i.level,tablei.adr);/* expression將執(zhí)行一系列指令, 但最終結(jié)果將會保存在棧頂,執(zhí)行sto命令完成賦值 */ else if(sym=readsym)/* 準備按照read語句處理 */ getsymdo; if(sym!=lparen)error(34);/* 格式錯誤,應(yīng)是左括號 */ else do getsymdo; if(sym=ident)i=postion(id,*ptx);/* 查找要讀的變量 */ else i=0; if(i=0)error(35); /* read()中應(yīng)是聲明過的變量名 */ else gendo(opr,0,16);/*
46、 生成輸入指令,讀取值到棧頂 */ gendo(sto,lev-tablei.level,tablei.adr);/* 儲存到變量 */ getsymdo; while(sym=comma); /* 一條read語句可讀多個變量 */ if(sym!=rparen) error(33);/* 格式錯誤,應(yīng)是右括號 */ while(!inset(sym,fsys)/* 出錯補救,直到收到上層函數(shù)的后跟符號 */ getsymdo; else getsymdo; else if(sym=writesym)/* 準備按照write語句處理,與read類似 */ getsymdo; if(sym=l
47、paren) do getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlevrparen=true; nxtlevcomma=true;/* write的后跟符號為) or , */ expressiondo(nxtlev,ptx,lev);/* 調(diào)用表達式處理,此處與read不 同,read為給變量賦值 */ gendo(opr,0,14);/* 生成輸出指令,輸出棧頂?shù)闹?*/ while(sym=comma); if(sym!=rparen)error(33);/* write()中應(yīng)為完整表達式 */ else getsymdo
48、; gendo(opr,0,15);/* 輸出換行 */ else if(sym=callsym)/* 準備按照call語句處理 */ getsymdo; if(sym!=ident)error(14);/* call后應(yīng)為標識符 */ else i=postion(id,*ptx); if(i=0)error(11); /* 過程未找到 */ else if(tablei.kind=procedur) gendo(cal,lev-tablei.level,tablei.adr);/* 生成 call指令 */ else error(15);/* call后標識符應(yīng)為過程 */ getsymd
49、o; else if(sym=ifsym)/* 準備按照if語句處理 */ getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlevthensym=true; nxtlevdosym=true;/* 后跟符號為then或do */ conditiondo(nxtlev,ptx,lev); /* 調(diào)用條件處理(邏輯運算)函數(shù) */ if(sym=thensym) getsymdo; else error(16);/* 缺少then */ cx1=cx;/* 保存當前指令地址 */ gendo(jpc,0,0);/* 生成條件跳轉(zhuǎn)指令,跳轉(zhuǎn)
50、地址未知,暫時寫0 */ statementdo(fsys,ptx,lev);/* 處理then后的語句 */ codecx1.a=cx;/* 經(jīng)statement處理后,cx為then后語句執(zhí)行完的 位置,它正是前面未定的跳轉(zhuǎn)地址 */ else if(sym=beginsym)/* 準備按照復合語句處理 */ getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlevsemicolon=true; nxtlevendsym=true;/* 后跟符號為分號或end */ /* 循環(huán)調(diào)用語句處理函數(shù),直到下一個符號不是語句開始符號或收 到
51、end */ statementdo(nxtlev,ptx,lev); while(inset(sym,statbegsys)|sym=semicolon) if(sym=semicolon) getsymdo; else error(10);/* 缺少; */ statementdo(nxtlev,ptx,lev); if(sym=endsym) getsymdo; else error(17);/* 缺少end或; */ else if(sym=whilesym)/* 準備按照while語句處理 */ cx1=cx;/* 保存判斷條件操作的位置 */ getsymdo; memcpy(nx
52、tlev,fsys,sizeof(bool)*symnum); nxtlevdosym=true;/* 后跟符號為do */ conditiondo(nxtlev,ptx,lev);/* 調(diào)用條件處理 */ cx2=cx;/* 保存循環(huán)體的結(jié)束的下一個位置 */ gendo(jpc,0,0);/* 生成條件跳轉(zhuǎn),但跳出循環(huán)的地址未 知 */ if(sym=dosym) getsymdo; else error(18);/* 缺少do */ statementdo(fsys,ptx,lev);/* 循環(huán)體 */ gendo(jmp,0,cx1);/* 回頭重新判斷條件 */ codecx2.a=
53、cx;/* 反填跳出循環(huán)的地址,與if類似 */ memset(nxtlev,0,sizeof(bool)*symnum);/* 語句結(jié)束無補救集合 */ testdo(fsys,nxtlev,19);/* 檢測語句結(jié)束的正確性 */ return 0; /* 表達式處理 */ int expression(bool* fsys,int* ptx,int lev)/* 參數(shù)意義見block和enter函數(shù) */ enum symbol addop; /* 用于保存正負號 */ bool nxtlevsymnum; if(sym=plus|sym=minus)/* 開頭的正負號,此時當前表達式被看作一個正的或負的項 */ addop=sym;/* 保存開頭的正負號 */ getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlevplus=true; nxtlevminus=t
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 教育政策在促進教師職業(yè)發(fā)展中的作用
- 心理健康教育與提升學生工作效能的策略研究
- 智能教育時代在線教學平臺的創(chuàng)新實踐
- 2025屆上海市盧灣高級中學高一物理第二學期期末達標檢測試題含解析
- 直方圖法分析質(zhì)量數(shù)據(jù)題目
- 在線互動課堂的技術(shù)支撐與教學實踐
- 基于大數(shù)據(jù)的嬰幼兒教育娛樂內(nèi)容創(chuàng)新研究
- 中職數(shù)學不等式課件
- 創(chuàng)新網(wǎng)絡(luò)驅(qū)動的教育資源優(yōu)化配置
- 2025年廣東省梅縣東山中學高二物理第二學期期末調(diào)研試題含解析
- 細胞生活的環(huán)境說課稿
- 野生菌中毒知識講座
- 數(shù)據(jù)中心安全防護體系
- 2025年部編版小學一年級語文下冊全冊教案
- 《贊美技巧》課件
- 業(yè)委會 物業(yè)合同范本
- 充電樁售后合同范本
- 2025年青藏鐵路集團有限公司招聘筆試參考題庫含答案解析
- 養(yǎng)老院護理員交接班制度與管理
- 2025四川遂寧發(fā)展投資集團限公司及直屬企業(yè)招聘21人高頻重點提升(共500題)附帶答案詳解
- 年中績效總結(jié)報告
評論
0/150
提交評論