




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、編譯原理課程設計題 目 _PL0編輯器擴充_學 院 計算機學院 專 業 軟件工程年級班別 10級4班學 號 3110006379學生姓名 陳泳鑫指導教師 楊勁濤 答辯程序設計報告撰寫平時總成績2013 年 1 月 4 日一 課程設計目的與要求1、課程設計目的:在分析理解一個教學型編譯程序(如PL/0)的基礎上,對其詞法分析程序、語法分析程序和語義處理程序進行部分修改擴充。達到進一步了解程序編譯過程的基本原理和基本實現方法的目的。2、課程設計要求:基本內容(成績范圍:“中”、“及格”或“不及格”)(1)擴充賦值運算:*= 和 /=擴充語句(Pascal的FOR語句):FOR <變量>
2、:=<表達式> TO <表達式> DO <語句>FOR <變量>:=<表達式> DOWNTO <表達式> DO <語句> 其中,語句的循環變量的步長為2,語句的循環變量的步長為-2。(3)增加運算:+ 和 -。選做內容(成績評定范圍擴大到:“優”和“良”)(1)增加類型: 字符類型; 實數類型。(2)擴充函數: 有返回值和返回語句; 有參數函數。(3)增加一維數組類型(可增加指令)。(4)其他典型語言設施。二、結構設計方案1、 結構設計說明:PL/0的編譯程序以語法分析程序為核心,詞法分析程序和代碼生成程序都作
3、為一個獨立的過程,當語法分析需要讀單詞時就用詞法分析程序,而當語法分析正確需生成相應的目標代碼時,則調用代碼生成程序。此外,用表格管理程序建立變量,常量和過程標識符的說明與引用之間的信息聯系。用出錯處理程序對詞法和語法分析遇到的錯誤給出在源程序中出錯的位置和錯誤性質。2、 各功能模塊圖示:3. 各功能模塊作用表:1PL0主程序2Error出錯處理,打印出錯位置和錯誤編碼 3GetCh漏掉空格,讀取一個字符 4GetSym詞法分析,讀取一個單詞 5Gen生成目標代碼,并送入目標程序區 6TEST測試當前單詞符號是否合法 7ENTER登錄名字表 8POSITION查找標識符在名字表中的位置 9Co
4、nstDeclaration常量定義處理10VarDeclaration變量說明處理11ListCode列出目標代碼清單12FACTOR因子處理13TERM項處理14EXPRESSION表達式處理15CONDITION條件處理16STATEMENT語句部分處理17Block分程序分析處理過程18BASE通過靜態鏈求出數據區的基地址19Interpret對目標代碼的解釋執行程序3. 符號名字表結構:struct tablestruct char nameal; /*名字*/ enum object kind; /*類型:const,var,array or procedure*/ int val
5、; /*數值,僅const使用*/ int level; /*所處層,僅const不使用*/ int adr; /*地址,僅const不使用*/ int size; /*需要分配的數據區空間,僅procedure使用*/;4. 保留關鍵字枚舉結構:enum symbolnul,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,r
6、eadsym,dosym,callsym,constsym,varsym,procsym, elsesym, forsym, tosym,downtosym, returnsym, pluseql, minuseql, plusplus,minusminus, ;5.名字表中標識符枚舉類型:enum object constant,/*常量*/ variable,/*變量*/ procedur,/*過程*/;6. 運行時存儲組織和管理對于源程序的每一個過程(包括主程序),在被調用時,首先在數據段中開辟三個空間,存放靜態鏈SL、動態鏈DL和返回地址RA。靜態鏈記錄了定義該過程的直接外過程(或主程
7、序)運行時最新數據段的基地址。動態鏈記錄調用該過程前正在運行的過程的數據段基址。返回地址記錄了調用該過程時程序運行的斷點位置。對于主程序來說,SL、DL和RA的值均置為0。靜態鏈的功能是在一個子過程要引用它的直接或間接父過程(這里的父過程是按定義過程時的嵌套情況來定的,而不是按執行時的調用順序定的)的變量時,可以通過靜態鏈,跳過個數為層差的數據段,找到包含要引用的變量所在的數據段基址,然后通過偏移地址訪問它。在過程返回時,解釋程序通過返回地址恢復指令指針的值到調用前的地址,通過當前段基址恢復數據段分配指針,通過動態鏈恢復局部段基址指針。實現子過程的返回。對于主程序來說,解釋程序會遇到返回地址為
8、0的情況,這時就認為程序運行結束。解釋程序過程中的base函數的功能,就是用于沿著靜態鏈,向前查找相差指定層數的局部數據段基址。這在使用sto、lod、stoArr、lodArr等訪問局部變量的指令中會經常用到。類PCODE代碼解釋執行的部分通過循環和簡單的case判斷不同的指令,做出相應的動作。當遇到主程序中的返回指令時,指令指針會指到0位置,把這樣一個條件作為終至循環的條件,保證程序運行可以正常的結束。7. 擴充賦值運算:+= 和 -= 設計:對于+=、-=、*=和/=賦值運算符,在程序中出現的情況只有如下一種,文法的EBNF 表示為:賦值語句:= <標識符> += | -=
9、<表達式>(1)擴充的語法描述見結構設計中的 PL/0 分程序和主要語句的語法描述中的描述圖;(2)分析區別賦值運算符采用:讀標識符后再讀一個字符,后根據讀到的字符轉去不同的賦值語句執行。(3)中間代碼生成情況:+=運算符,其他賦值運算符架構是一樣的,只是執行加法改為相應的算數運算。讀到+=運算符單詞求+=運算符后的表達式expressiondo(nxtlev,ptx,lev);取+=左部的標識符的值到棧頂gendo(lod,lev-tablei.level,tablei.adr);執行加法gendo(opr,lev-tablei.level,2);保存賦值后的結果gendo(st
10、o,lev-tablei.level,tablei.adr);else if(sym=pluseql)/檢測到+符號i=position(id,*ptx); /把類x+=3的x的地址取出來gendo(lod,lev-tablei.level,tablei.adr); /*找到變量地址并將其值入棧*/getsymdo;if(sym=semicolon)getsymdo;memcpy(nxtlev,fsys,sizeof(bool)* symnum);expressiondo(nxtlev,ptx,lev);gendo(opr,0,2);if(i!=0)gendo(sto,lev-tablei.l
11、evel,tablei.adr);else if(sym=minuseql)/檢測到-符號i=position(id,*ptx); /把類x-=3的x的地址取出來gendo(lod,lev-tablei.level,tablei.adr); /*找到變量地址并將其值入棧*/getsymdo;if(sym=semicolon)getsymdo;memcpy(nxtlev,fsys,sizeof(bool)* symnum);expressiondo(nxtlev,ptx,lev);gendo(opr,0,3);if(i!=0)gendo(sto,lev-tablei.level,tablei.a
12、dr); 8.擴充語句(Pascal的FOR語句):FOR <變量>:=<表達式> TO <表達式> DO <語句>FOR <變量>:=<表達式> DOWNTO <表達式> DO <語句> 其中,語句的循環變量的步長為2,語句的循環變量的步長為-2For i:= E1 to E2 do S1 循環語句ALGOL等價于: i:= E1; goto OVER;AGAIN :i:= i+2OVER : if i<E2 then Begin S1;goto again end;注意程序中基礎用到循環控
13、制變量i,因此 entry(i)必須被保存下來,而Pascal這樣的語言中,循環變量在循環外也是可見的,本次擴充約定循環步長為 2或者-2。具體需要在程序staement()添加for的句法判斷:else if(sym=forsym) /檢測到for語句getsymdo;if(sym=ident)i=position(id,*ptx);if(i=0) error(11);elseif(tablei.kind!=variable) /賦值語句中,賦值號左部標識符屬性應是變量error(12);i=0;elsegetsymdo;if(sym!=becomes) error(13); /賦值語句左部
14、標識符后應是賦值號:=else getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlevtosym=true; /后跟符to和downtonxtlevdowntosym=true;expressiondo(nxtlev,ptx,lev); /處理賦值語句右部的表達式E1gendo(sto,lev-tablei.level,tablei.adr); /保存初值switch(sym)case tosym: /步長為的向上增加getsymdo;cx1=cx; /保存循環開始點/將循環判斷變量取出放到棧頂gendo(lod,lev-tablei.
15、level,tablei.adr);memcpy(nxtlev,fsys,sizeof(bool)*symnum); /處理表達式E2nxtlevdosym=true; /后跟符doexpressiondo(nxtlev,ptx,lev);gendo(opr,0,13); /生成比較指令,i是否小于等于E2的值cx2=cx; /保存循環結束點/生成條件跳轉指令,跳出循環,跳出的地址未知gendo(jpc,0,0);if(sym=dosym) /處理循環體Sgetsymdo;statement(fsys,ptx,lev); /循環體處理/增加循環變量步長為/將循環變量取出放在棧頂gendo(lo
16、d,lev-tablei.level,tablei.adr);gendo(lit,0,1); /將步長取到棧頂gendo(opr,0,2); /循環變量加步長/將棧頂的值存入循環變量gendo(sto,lev-tablei.level,tablei.adr); gendo(jmp,0,cx1); /無條件跳轉到循環開始點codecx2.a=cx;elseerror(29); /for語句中少了dobreak;case downtosym: /步長為的向下減少getsymdo;cx1=cx; /保存循環開始點/將循環判斷變量取出放到棧頂gendo(lod,lev-tablei.level,tab
17、lei.adr);memcpy(nxtlev,fsys,sizeof(bool)*symnum); /處理表達式E2nxtlevdosym=true; /后跟符doexpressiondo(nxtlev,ptx,lev);gendo(opr,0,11); /生成比較指令,i是否大于等于E2的值cx2=cx; /保存循環結束點/生成條件跳轉指令,跳出循環,跳出的地址未知gendo(jpc,0,0); if(sym=dosym) /處理循環體Sgetsymdo;statement(fsys,ptx,lev); /循環體處理 /增加循環變量步長為/將循環變量取出放在棧頂gendo(lod,lev-t
18、ablei.level,tablei.adr);gendo(lit,0,1); /將步長取到棧頂gendo(opr,0,3); /循環變量加步長/將棧頂的值存入循環變量gendo(sto,lev-tablei.level,tablei.adr);gendo(jmp,0,cx1); /無條件跳轉到循環開始點codecx2.a=cx;else error(29);/for語句中少了dobreak;else error(19); /for語句后跟賦值語句,賦值語句左部是變量,缺少變量11. 增加運算:+ 和 - :對于+和-運算符,擴充時要注意存在+,-有兩個情況:1、作為語句的時候;2、作為表達式
19、中的因子的時候.(1) 作為語句的時候,有四種情況:A+ +A A- -A文法的 EBNF 表示形式為:<自增自減語句>:=<標識符> + | - | + | - <標識符>(2) 作為因子的時候,有兩種情況a+和 a-作為因子,比如:b:=a+*a-;語句+a 和-a 作為因子,比如:b:= -a+2*+a;語句文法的 EBNF 表示形式為:<表達式>:=. + | - <標識符>|<標識符> + | - .其中的.表示前后都可以有其他的項或因子(1)作為語句 + - 符號分為以下兩種情況考慮:情況1對于自增自減符號置后
20、的只需要在判斷+= -=后面添加句法分析即可:/*后置自增符號 a+ a-類型添加代碼*/else if(sym=plusplus)/檢測到后置+符號gendo(lit,0,1);gendo(lod,lev-tablei.level,tablei.adr); /*找到變量地址并將其值入棧*/gendo(opr,0,2); /執行加操作,if(i!=0) gendo(sto,lev-tablei.level,tablei.adr);getsymdo;else if(sym=minusminus)/檢測到后置-符號gendo(lod,lev-tablei.level,tablei.adr); /*
21、找到變量地址并將其值入棧*/gendo(lit,0,1);gendo(opr,0,3); /執行減操作,if(i!=0) gendo(sto,lev-tablei.level,tablei.adr);getsymdo;情況2對于+ -前置的需要添加因子開始符號:facbegsysplusplus=true; /*增加符號+開始因子plusplus*/facbegsysminusminus=true; /*增加符號-開始因子minusminus*/*前置自增符號 +a - -a類型添加代碼*/if(sym=plusplus)getsymdo;if(sym=ident) /后面跟的是變量i=pos
22、ition(id,*ptx);if(i=0)error(11);elseif(tablei.kind!=variable) /+后沒跟變量,出錯error(12);i=0;else /+后跟變量,處理生成中間代碼if(tablei.kind=variable)gendo(lod,lev-tablei.level,tablei.adr);/先取值到棧頂gendo(lit,0,1); /將值為入棧gendo(opr,0,2); /加法,即+1,棧頂加次棧頂gendo(sto,lev-tablei.level,tablei.adr);/出棧取值到內存getsymdo;else if(sym=minu
23、sminus)getsymdo;if(sym=ident) /后面跟的是變量i=position(id,*ptx);if(i=0)error(11);elseif(tablei.kind!=variable) /-后沒跟變量,出錯error(12);i=0;else /-后跟變量,處理生成中間代碼if(tablei.kind=variable) /后跟變量gendo(lod,lev-tablei.level,tablei.adr);/先取值到棧頂gendo(lit,0,1); /將值為入棧gendo(opr,0,3); /加法,即-1,棧頂減次棧頂gendo(sto,lev-tablei.le
24、vel,tablei.adr);/出棧取值到內存getsymdo;(2)作為因子的時候也有兩種情形考慮: 添加int factor(bool*fsys,int *ptx,int lev)函數如下:/*如果因子可能出現b:=a+或b:=a-類型的處理*/if(sym=plusplus)gendo(lit,lev-tablei.level,1); /將值為入棧gendo(opr,lev-tablei.level,2); /加法,即+1,棧頂加次棧頂gendo(sto,lev-tablei.level,tablei.adr); /出棧取值到內存gendo(lod,lev-tablei.level,t
25、ablei.adr); /取值到棧頂gendo(lit,0,1);gendo(opr,0,3); /棧頂值減getsymdo;else if(sym=minusminus)gendo(lit,lev-tablei.level,1); /將值為入棧gendo(opr,lev-tablei.level,3); /減法,即-1,棧頂減次棧頂gendo(sto,lev-tablei.level,tablei.adr); /出棧取值到內存gendo(lod,lev-tablei.level,tablei.adr);gendo(lit,0,1);gendo(opr,0,2); /棧頂值加getsymdo;
26、/*/*如果因子是表達式的時候,則有可能是包含+a或者-a,如b:=+a或b:=-a */ else if(sym=plusplus)getsymdo;if(sym=ident)getsymdo;i=position(id,*ptx);if(i=0)error(11);elseif(tablei.kind=variable) /變量 /先加后再用agendo(lod,lev-tablei.level,tablei.adr);/先取值到棧頂gendo(lit,0,1);/將值為入棧gendo(opr,0,2);/加法,即+1,棧頂加次棧頂gendo(sto,lev-tablei.level,ta
27、blei.adr);/出棧取值到內存gendo(lod,lev-tablei.level,tablei.adr); /取值到棧頂else if(sym=minusminus)getsymdo;if(sym=ident)getsymdo;i=position(id,*ptx);if(i=0)error(11);elseif(tablei.kind=variable) /變量 /先減后再用agendo(lod,lev-tablei.level,tablei.adr);/先取值到棧頂gendo(lit,0,1); /將值為入棧gendo(opr,0,3); /減法,即-1,棧頂減次棧頂gendo(sto,lev-tablei.level,tablei.adr);/出棧取值到內存gendo(lod,lev-tablei.level,tablei.adr); /取值到棧頂testdo(fsys,facbegsys,23); /*因子后有非法符號*/四. 程序測試1. 擴充賦值運算:*= 和 /=測試文件 “test1”: 運行結果:結果分析: a = 5 ,b = 48 , a*=3 結果為15正確,b/=6結果為8正確,擴充成功!2. 擴充語句(Pascal的FOR語句):測試
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《胸腔閉式引流的急救與護理》課件
- 畫代銷合同協議
- 商品定金合同范本
- 常見無人機故障與應對試題及答案
- 高速公路路面施工工藝流程:專業課件演示
- 《稅收減免數據錄入》課件
- 繁育員職業資格考試專項試題及答案
- 《存在主義戲劇》課件
- 融水紅水鄉初級中學-主題班會-神州二十再出發,逐夢太空新征程航天教育【課件】
- 2024年農業植保員考證總結試題及答案
- 臨時用電設備布線要求培訓課件
- 北師大版七年級數學下冊舉一反三 專題1.5 整式的混合運算與化簡求值專項訓練(30道)(舉一反三)(原卷版+解析)
- 產學研協同創新機制
- 視頻監控維保項目投標方案(技術標)
- 礦山生態修復施工組織設計
- 星巴克消費者數據分析報告
- 實時數據采集系統方案
- 清熱解毒藥品行業市場研究報告
- PMC-651T配電變壓器保護測控裝置使用說明書V1.2
- 中國紅色革命故事英文版文章
- 《體育保健學》課件-第三章 運動性病癥
評論
0/150
提交評論