編譯原理課設報告最終版_第1頁
編譯原理課設報告最終版_第2頁
編譯原理課設報告最終版_第3頁
編譯原理課設報告最終版_第4頁
編譯原理課設報告最終版_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、 編譯原理課程設計PL0 Experiment Report(燕山大學 信息科學與工程學院) 姓 名 班 級 : 計算機* 學 生 學 號 : 130104010*&* 課 程 名 稱 : 編譯原理 指 導 教 師 : 888 2015年 12 月 24 日 一、設計目的研究、 改進或自行設計、 開發(fā)一個簡單的編譯程序或其部分功能, 加深對編譯理論和編譯過程的理解。 編程語言不限。二、設計任務擴展 PL/0 編譯程序功能目的: 擴充 PL/0 編譯程序功能要求: (1)閱讀、 研究 PL/0 編譯程序源文件。 (2)在上述工作基礎上, 可有選擇地補充、完善其中詞法分析、語法分析、語義分

2、析、目標代碼生成、目標代碼解釋執(zhí)行等部分的功能。如以語法分析部分為例,則可以增加處理更多語法成分的功能,如可處理一維數(shù)組、+、-、+=、-=、*=、/=、%(取余)、!(取反)、repeat、for、else、開方、處理注釋、錯誤提示、標示符或變量中可以有下劃線等。還可以增加類型,如增加字符類型、實數(shù)類型; 擴充函數(shù)如有返回值和返回語句的,有參數(shù)函數(shù)等; (3)設計編制典型的運行實例,以便能反映出自己所作的改進。 三、設計思想:PL/0 語言可以看成PASCAL 語言的子集,它的編譯程序是一個編譯解 釋執(zhí)行系統(tǒng)。PL/0 的目標程序為假想棧式計算機的匯編語言,與具體計算 機無關。 P

3、L/0的編譯程序和目標程序的解釋執(zhí)行程序都是用PASCAL語言書寫 的,因此PL/0 語言可在配備PASCAL 語言的任何機器上實現(xiàn) 。其編譯過程采用一趟掃描方式,以語法分析程序為核心,詞法分析和代碼生成程序都作為一個獨立的過程,當語法分析需要讀單詞時就調用詞法分析程序, 而當語法分析正確需要生成相應的目標代碼時,則調用代碼生成程序。 用表格管理程序建立變量、常量和過程表示符的說明與引用之間的信息聯(lián)系。當源程序編譯正確時,PL/0 編譯程序自動調用解釋執(zhí)行程序,對目標 代碼進行解釋執(zhí)行,并按用戶程序的要求輸入數(shù)據(jù)和輸出運行結果。四、設計內容:1 擴充語句for(<語句>;<條

4、件>;<語句>)<語句>;2 擴充語句if <條件> then <語句> else <語句>;3 擴充語句repeat <語句>;until <條件>;4 增加自增自減運算+和和+=,-=運算;5 修改不等號#,為!=;6 增加一維數(shù)組聲明格式:<ident><ident>/<number>:<ident>/<number>;賦值格式:<ident><index>:=<表達式>;調用格式:<ident&g

5、t;<index>五、程序結構:程序pl0程序block語句statement條件condition表達式expression項term因子factorPL/0源程序 詞法分析程序表格管理程序語法分析程序出錯管理程序代碼生成程序目標程序圖1 編譯程序結構 圖2功能模塊調用1.功能模塊作用如下:Pl0.c:主程序Error:出錯處理,打印出錯位置和錯誤編碼Getsym:詞法分析,讀取一個單詞Getch:漏掉空格,讀取一個字符Gen:生成目標代碼,并送入目標程序區(qū)Test:測試當前符號是否合法Block:分程序分析處理過程,詞法語法分析Enter:登陸名字表Position:查找標識符

6、在名字表中的位置Constdeclaration:常量定義處理Vardeclaraction:變量說明處理Listcode:列出目標代碼清單Statement:語句處理Expression:表達式處理Term:項處理Factor:因子處理Condition:條件處理Interpret:對目標代碼的解釋執(zhí)行程序Base:通過靜態(tài)鏈求出數(shù)據(jù)取得基地址增加兩個功能:Arraydeclaration:數(shù)組聲明處理Arraycoef:數(shù)組索引計算和“虛擬機”動作生成2.保留字:enum symbol nul,ident,number,plus,minus, times,slash,oddsym,eql,

7、neq, lss,leq,gtr,geq,lparen, rparen,comma,semicolon,period,becomes, beginsym,endsym,ifsym,thensym,elsesym,forsym, inc,dec,whilesym, writesym, readsym,dosym,callsym, constsym,varsym, procsym,repeatsym, untilsym, plusbk,minusbk, lbrack,rbrack,colon,共43個,其中補充保留字為:else, for, repeat, until, plusbk, minus

8、bk, Lbrack, rbrack, colon3.名字表中的類型enum object constant, variable, procedure, arrays, 共4個,擴充arrays,以便實現(xiàn)數(shù)組4.虛擬機代碼enum fct lit, opr, lod, sto, cal, inte, jmp, jpc,lda, sta, 共10個,補充的lda,sta用于數(shù)組操作6. 錯誤信息(1)const,var,procedure后應為標識符(2) 常數(shù)說明中的=后應是數(shù)字(3)常數(shù)說明中的標識符后應是=(4)常數(shù)說明中的=寫成了:=(5)漏掉了,或;(6)過程說明后的符號不正確(應是語

9、句開始符,或過程定義符)(7)應是語句開始符(8)標識符未說明(9)程序結尾丟了句號。(10)語句之間漏了;(11)call后應為標識符(12)賦值語句中,賦值號左部標識符屬性應是變量(13)賦值號左部標識符屬性應是賦值號(14)程序體內語句部分的后跟符不正確(15)call后標識符屬性應為過程(16)條件語句中丟了then(17)丟了end或;(18)while循環(huán)語句中丟了do(19)語句后的符號不正確6.名字表結構struct tablestructchar nameal;enum object kind;int val;int level;int adr;int size;/擴充名字表

10、結構,增加一個data域保存數(shù)組的下界int data; /* 其他數(shù)據(jù),對arrays來說是下界*/7.語法描述圖:程序分程序 .圖3 程序語法描述圖,。;,;=語句constidentnumbervaridentprocedureident分程序圖4 分程序語法描述圖語句語句until表達式表達式:=if條件endthen語句條件do語句(表達式),(ident,)begin語句語句;identcallidentwhilerepeatreadwritedecsincsincsdecselse語句for條件語句圖5 語句語法描述圖 條件=<>#>=odd表達式表達式<

11、=圖6條件語法描述圖表達式項項+ 圖7 表達式語法描述圖項因子因子/*%圖8 項語法描述圖因子)(表達式identnumberincsdecsdecsincs圖9 因子語法描述圖四、功能擴充1.語句處理中加入for循環(huán)語句if(sym = forsym)getsymdo;if(sym != lparen) error(34);/沒有左括號出錯else getsymdo;statementdo(nxtlev, ptx, lev); /S1代碼if(sym != semicolon) error(10); /語句缺少分號出錯elsecx1=cx;getsymdo;conditiondo(nxtle

12、v, ptx, lev); /E代碼if(sym!=semicolon)error(10);/語句缺少分號出錯else cx2=cx;gendo(jpc,0,0);cx3=cx;gendo(jmp,0,0);getsymdo;cx4=cx;statementdo(nxtlev, ptx, lev);/S2代碼if(sym != rparen) error(22);/缺少右括號出錯else gendo(jmp,0,cx1);getsymdo;cx5=cx;statementdo(nxtlev, ptx, lev); /S3代碼codecx3.a=cx5;gendo(jmp,0,cx4);code

13、cx2.a=cx;2.在語句處理中增加repeat-until語句if(sym = repeatsym)cx1 = cx;getsymdo;statementdo(nxtlev, ptx, lev);if(sym = untilsym)getsymdo;conditiondo(nxtlev, ptx, lev);cx2=cx;gendo(jpc, 0, 0);codecx2.a=cx1; else error(33); /沒有寫until出錯3.擴充+和運算符對于+和-運算符,擴充時要注意存在兩個情況:1)作為語句的時候;2)作為表達式中的因子的時候。 注意:擴充時增加因子開始符facbegs

14、ysincs=true和facbegsysdecs=true。 擴充的語法描述見結構設計中的PL/0分程序和主要語句的語法描述中的描述圖,詳細代碼見程序。 1)作為語句的時候,有四種情況: a+; a-; +a; -a; 文法的EBNF表示形式為: <自增自減語句>:=<標識符>+ |-|+|- <標識符> 文法分析過程大體如下圖: 語句開始符SYM=+或者-讀下個SYM,如是ident,確定為自增自減語句語句開始符SYM=ident讀下個SYM,如是+或者-,確定為自增自減語句 +a和a a+和a生成中間代碼對于a+;+a;和a-;-a;語句的處理如下:

15、先將變量的值取出放在棧頂,后將1入棧,后執(zhí)行加法或減法運算oprv指令的2(加法)、3(減法),后將運算后的棧頂值存回變量。 a+;和+a;語句的中間代碼:lod 0 3;lit 0 1;opr 0 2;sto 0 3;a-;和-a;語句的中間代碼:lod 0 3;lit 0 1;opr 0 3;sto 0 3; 2) 作為因子的時候,有兩種情況: a+和a-作為因子,比如:b:=a+*a-;語句 +a和-a作為因子,比如:b:=-a+2*+a;語句 文法的EBNF表示形式為: <表達式>:=. +|-<標識符>|<標識符>+| -. 其中的.表示前后都可以

16、有其他的項或因子 生成中間代碼A對于因子+a和-a的中間代碼生成處理和a+;等語句處理一樣; B對于因子a+和a的中間代碼生成處理如下:a+:lod 0 3;lit 0 1;opr 0 2;sto 0 3;lod 0 3;lit 0 1;opr 0 3; a-:lod 0 3;lit 0 1;opr 0 3;sto 0 3;lod 0 3;lit 0 1;opr 0 2; 先將變量的值取出放在棧頂,后將1入棧,后執(zhí)行加法或減法運算opr指令的2(加法)、3(減法),后將運算后的棧頂值存回變量,后將變量的值又取出來放入棧頂,后將1入棧,如果是a+就執(zhí)行減法,如果是a就執(zhí)行加法,以實現(xiàn)先用a的值后

17、再加1。4.語句處理中加入if-then-else語句在原有程序if(sym=then).后加入下列代碼:cx1 = cx;gendo(jpc, 0, 0);statementdo(fsys, ptx, lev);if(sym = elsesym)getsymdo;cx2 = cx;gendo(jmp, 0, 0);codecx1.a = cx;statementdo(fsys, ptx, lev);codecx2.a = cx;elsecodecx1.a = cx;5.修改不等號#為!=注釋源程序中的ssym'#' = neq語句,在getsym中加入下列代碼:/修改不等號為

18、!=else if(ch='!')getchdo;if(ch='=')sym=neq;getchdo; else sym=nul; 6.加入對一維數(shù)組的支持本程序將數(shù)組看做變量的一種,由var聲明函數(shù)調用array聲明函數(shù)完成數(shù)組聲明,這樣就處加入文件輸出的相關語句外,可以完全保留block函數(shù)和enter函數(shù);通過改寫factor函數(shù)使數(shù)組因子包括了后綴的索引號,這樣就可以調用通用的表達式函數(shù)賦值數(shù)組了。為了方便完成數(shù)組相關功能,擴充了虛擬機處理代碼。數(shù)組的越界及非法調用錯誤處理沒有完善,僅給出了錯誤代碼。在頭文件pl0.h中:/*定義兩個全局變量,用來保存數(shù)

19、組定義的下界和容量*/static int g_arrBase = 0;static int g_arrSize = 0;/* 虛擬機代碼*/增加lda,sta專門由于數(shù)組的處理/增加兩個虛擬機指令lda,sta,分別用來從數(shù)組中取數(shù)和存到數(shù)組中/數(shù)組元素的訪問和存儲,是將()后的當成表達式,先處理,得到元素的索引,放在棧頂/最后根據(jù)數(shù)組的首地址,得到某個元素的地址enum fct .lda, sta /擴充名字表結構,增加一個data域保存數(shù)組的下界struct data; /* 其他數(shù)據(jù),對arrays來說是下界*/* 名字表中的類型*/enum objec

20、t .arrays /添加數(shù)組類型/數(shù)組聲明處理, 下界和上界允許已經定義過的常量標識符int arraydeclaration(int* ptx, int lev, int* pdx);/數(shù)組元素索引計算與“虛擬機”生成int arraycoef(bool *fsys,int *ptx,int lev);在源程序文件pl0.c中:編寫相關的arraydeclaration,arraycoef兩個功能函數(shù):/* 數(shù)組聲明處理, 下界和上界允許已經定義過的常量標識符*/int arraydeclaration(int* ptx, int lev, int* pdx) char arrIdal;

21、/* 暫存數(shù)組標識名,避免被覆蓋*/ int cstId; /* 常量標識符的位置*/ int arrBase=-1, arrTop=-1; /* 數(shù)組下界、上界的數(shù)值*/getsymdo; if(sym=lbrack) /* 標識符之后是'',則識別為數(shù)組*/ strcpy(arrId, id); /* 檢查下界*/ getsymdo; if(sym=ident) if(cstId=position(id,(*ptx)!=0)arrBase=(constant=tablecstId.kind)?tablecstId.val:-1; elsearrBase=(sym=numbe

22、r)?num:-1; if(-1=arrBase)error(50);return -1; /* 檢查冒號*/getsymdo;if(sym!=colon) error(50);return -1; /* 檢查上界*/ getsymdo; if(sym=ident) if(cstId=position(id,(*ptx)!=0)arrTop=(constant=tablecstId.kind)?tablecstId.val:-1; elsearrTop=(number=sym)?num:-1; if(arrTop=-1)error(50);/隨意指定,因為原程序對錯誤號的規(guī)劃極差!return

23、 -1; /* 檢查'' */ getsymdo; if(sym!=rbrack) error(50);return -1; /* 上下界是否符合條件檢查*/ g_arrSize=arrTop-arrBase+1; g_arrBase=arrBase; if(g_arrSize<=0)error(50);return -1; /* 恢復數(shù)組的標識符*/ strcpy(id, arrId); return 1; return 0;/* 數(shù)組元素索引計算與“虛擬機”生成*/int arraycoef(bool *fsys,int *ptx,int lev) bool nxtl

24、evsymnum; int i = position(id,*ptx); getsymdo; if (sym=lbrack) /* 索引是括號內的表達式*/ getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlevrbrack=true; expressiondo(nxtlev,ptx,lev); if (sym=rbrack) gendo(lit,0,tablei.data); gendo(opr,0,3); /* 系數(shù)修正,減去下界的值*/ return 0; elseerror(22); /* 缺少右括號*/ elseerror(

25、51); /* 數(shù)組訪問錯誤*/ return -1;修改函數(shù)enter,block,vardeclaration,factor及statement,使其具備處理數(shù)組的功能:/將數(shù)組變量登陸名字表void enter(enum object k, int * ptx, int lev, int * pdx).case arrays: /* 數(shù)組名,進行記錄下界等*/ table(*ptx).level = lev; table(*ptx).adr = (*pdx); table(*ptx).data = g_arrBase; table(*ptx).size = g_arrSize; *pdx

26、 = (*pdx)+g_arrSize; break;./輸出數(shù)組名字表到控制臺和文件fas.tmpint block(int lev, int tx, bool * fsys).case arrays:printf("%d array %s ", i, );printf("lev=%d addr=%d size=%dn", tablei.level, tablei.adr, tablei.size);fprintf(fas, "%d array %s ", i, );fprintf(fas

27、, "lev=%d addr=%d size=%dn", tablei.level, tablei.adr, tablei.size);/加入數(shù)組聲明int vardeclaration(int * ptx, int lev, int * pdx)int arrayRet=-1; if (sym=ident) arrayRet=arraydeclaration(ptx,lev,pdx); /* 先判斷數(shù)組*/ switch(arrayRet) case 1: enter(arrays,ptx,lev,pdx); / 填寫數(shù)組名getsymdo; break; case 0:

28、 enter(variable,ptx,lev,pdx); / 填寫名字表 /getsymdo; break; default: return -1; /* 數(shù)組定義解析出錯*/ elseerror(4); /* var后應是標識*/ return 0;/*當因子是數(shù)組型變量時,調用arraycodefdo將數(shù)組的索引入棧頂,之后按vatiabler變量操作*/int factor(bool * fsys, int * ptx, int lev).switch (tablei.kind).case arrays: /* 名字為數(shù)組名*/arraycoefdo(fsys,ptx,lev);gen

29、do(lda,lev-tablei.level,tablei.adr); /* 找到變量地址并將其值入棧*/. . int statement(bool * fsys, int * ptx, int lev).if (sym = ident).if (tablei.kind != variable)&&(tablei.kind != arrays)error(12); i = 0;elseenum fct fct1 = sto; switch(tablei.kind)case arrays:arraycoefdo(fsys, ptx, lev);fct1 = sta; /* 數(shù)

30、組保存,要多讀一個棧*/case variable:./增加的兩個虛擬機代碼的處理:lda,stavoid interpret().case lda: /* 數(shù)組元素訪問,當前棧頂為元素索引,執(zhí)行后,棧頂變成元素的值*/st-1 = sbase(i.l,s,b) + i.a + st-1;break;case sta: /* 棧頂?shù)闹荡娴綌?shù)組中,索引為次棧頂*/t-=2;sbase(i.l,s,b) + i.a + st = st+1;break;.五、調試及運行結果1.測試repeat.until.語句功能 測試文件:4.txt 測試結果: var a,b,n; begin b:=4; a:=1; read(n); repeat a:=a+1;b:=b+1; until a>n; write(a); write(b);end.當輸入的n為3時,repeat.until.語句中的循環(huán)體執(zhí)行3次,所以a=4,b=72.測試增加的+,-功能 測試文件:2.txt 測試結果:var a,b;begin a:=1; b:=3; a

溫馨提示

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

評論

0/150

提交評論