編譯原理課程設計-pl_0編譯器及其擴充_第1頁
已閱讀1頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、<p><b>  一、課程設計要求</b></p><p>  設計題目:PL/0編譯器及其擴充。</p><p>  設計內(nèi)容:對PL/0語言進行擴充的內(nèi)容為:</p><p>  1、增加運算符定義,如++、--、+=、-=等;</p><p>  2、擴充語句定義,如else,for, switch…c

2、ase,continue等;</p><p>  3、增加數(shù)據(jù)類型,在現(xiàn)有整型、邏輯型基礎上增加實型,數(shù)組類型,記錄類型或結(jié)構體類型等;</p><p>  4、增加函數(shù)調(diào)用功能,進一步擴充帶參數(shù),返回值的函數(shù)功能;</p><p>  5、增加類,補充封裝、繼承、多態(tài)等面向?qū)ο筇匦裕蛇x)。</p><p><b>  二、實驗環(huán)

3、境與工具</b></p><p>  計算機及操作系統(tǒng):PC機,Windows2000,WindowsXP</p><p><b>  程序設計語言:C</b></p><p>  教學型編譯程序:PL/0 </p><p><b>  源語言:C語言</b></p>&l

4、t;p>  實現(xiàn)工具:Visual C++ 6.0</p><p>  運行平臺:Windows 7</p><p>  三、結(jié)構設計說明與功能塊描述</p><p><b>  1.結(jié)構設計說明</b></p><p> ?。?)PL/0 語言編譯器</p><p>  PL/0語言可看成

5、是PASCAL語言的子集,它的編譯程序是一個編譯解釋執(zhí)行系統(tǒng)。PL/0的目標程序為假想棧式計算機的匯編語言,與具體計算機無關。</p><p>  PL/0 的編譯程序采用一趟掃描方式,以語法分析程序為核心,詞法分析程序和代碼生成程序都作為一個獨立的過程,當語法分析需要讀單詞時就用詞法分析程序,而當語法分析正確需生成相應的目標代碼時,則調(diào)用代碼生成程序。此外,用表格管理程序建立變量,常量和過程標識符的說明與引用之

6、間的信息聯(lián)系。用出錯處理程序?qū)υ~法和語法分析遇到的錯誤給出在源程序中出錯的位置和錯誤性質(zhì)。</p><p>  PL/0編譯程序的結(jié)構圖</p><p><b>  各功能模塊描述</b></p><p>  PL/0編譯程序的總體流程圖</p><p><b>  三、主要成分描述</b><

7、/p><p><b>  1、符號表</b></p><p>  為了組成一條指令,編譯程序必須知道其操作碼及其參數(shù)(數(shù)或地址)。這些值是由編譯程序本身聯(lián)系到相應標識符上去的。這種聯(lián)系是在處理常數(shù)、變量和過程說明完成的。為此,標識符表應包含每一標識符所聯(lián)系的屬性;如果標識符被說明為常數(shù),其屬性值為常數(shù)值;如果標識符被說明成變量,其屬性就是由層次和修正量(偏移量)組成的地址

8、;如果標識符被說明為過程,其屬性就是過程的入口地址及層次。常數(shù)的值由程序正文提供,編譯的任務就是確定存放該值的地址。我們選擇順序分配變量和代碼的方法;每遇到一個變量說明,就將數(shù)據(jù)單元的下標加一(PL/0 機中,每個變量占一個存貯單元)。開始編譯一個過程時,要對數(shù)據(jù)單元的下標dx 賦初值,表示新開辟一個數(shù)據(jù)區(qū)。dx 的初值為3,因為每個數(shù)據(jù)區(qū)包含三個內(nèi)部變量RA,DL 和SL。</p><p>  2、運行時存儲組

9、織和管理</p><p>  對于源程序的每一個過程(包括主程序),在被調(diào)用時,首先在數(shù)據(jù)段中開辟三個空間,存放靜態(tài)鏈SL、動態(tài)鏈DL和返回地址RA。靜態(tài)鏈記錄了定義該過程的直接外過程(或主程序)運行時最新數(shù)據(jù)段的基地址。動態(tài)鏈記錄調(diào)用該過程前正在運行的過程的數(shù)據(jù)段基址。返回地址記錄了調(diào)用該過程時程序運行的斷點位置。對于主程序來說,SL、DL和RA的值均置為0。靜態(tài)鏈的功能是在一個子過程要引用它的直接或間接父過程

10、(這里的父過程是按定義過程時的嵌套情況來定的,而不是按執(zhí)行時的調(diào)用順序定的)的變量時,可以通過靜態(tài)鏈,跳過個數(shù)為層差的數(shù)據(jù)段,找到包含要引用的變量所在的數(shù)據(jù)段基址,然后通過偏移地址訪問它。</p><p>  在過程返回時,解釋程序通過返回地址恢復指令指針的值到調(diào)用前的地址,通過當前段基址恢復數(shù)據(jù)段分配指針,通過動態(tài)鏈恢復局部段基址指針。實現(xiàn)子過程的返回。對于主程序來說,解釋程序會遇到返回地址為0的情況,這時就認

11、為程序運行結(jié)束。</p><p>  解釋程序過程中的base函數(shù)的功能,就是用于沿著靜態(tài)鏈,向前查找相差指定層數(shù)的局部數(shù)據(jù)段基址。這在使用sto、lod、stoArr、lodArr等訪問局部變量的指令中會經(jīng)常用。</p><p>  類P-CODE代碼解釋執(zhí)行的部分通過循環(huán)和簡單的case判斷不同的指令,做出相應的動作。當遇到主程序中的返回指令時,指令指針會指到0位置,把這樣一個條件作為

12、終至循環(huán)的條件,保證程序運行可以正常的結(jié)束。</p><p><b>  3、語法分析方法</b></p><p>  語法分析的任務是識別由詞法分析給出的單詞符號序列在結(jié)構上是否符合給定的文法規(guī)則.PL/0編譯程序的語法分析采用了自頂向下的遞歸子程序法.粗略地說:就是對應每個非終結(jié)符語法單元,編一個獨立的處理過程(或子程序).語法分析研究從讀入第一個單詞開始由非終結(jié)

13、符程序即開始符出發(fā),沿語法描述圖箭頭所指出的方向進行分析.當遇到非終結(jié)符時,則調(diào)用相應的處理過程,從語法描述圖看也就進入了一個語法單元,再沿當前所進入的語法描述圖的箭頭方向進行分析,當遇到描述圖中是終結(jié)符時,則判斷當前讀入的單詞是否與圖中的終結(jié)符相匹配,若匹配,則執(zhí)行相應的語義程序(就是翻譯程序).再讀取下一個單詞繼續(xù)分析.遇到分支點時將當前的單詞與分支點上的多個終結(jié)符逐個相比較,若都不匹配時可能是進入下一非終結(jié)符語法單位或是出錯.&l

14、t;/p><p>  如果一個PL/0語言程序的單詞序列在整修語法分析中,都能逐個得到匹配,直到程序結(jié)束’.’,這時就說所輸入的程序是正確的.對于正確的語法分析做相應的語義翻譯,最終得出目標程序。</p><p><b>  4、中間代碼表示</b></p><p>  中間代碼表示格式如下:</p><p>  其中f代表

15、功能碼,L表示層次差,也就是變量或過程被引用的分程序與說明該變量或過程 的分程序之間的層次差.a的含意對不同的指令有所區(qū)別,見下面對每條指令解釋說明.</p><p><b>  四、測試用例</b></p><p>  增加 注釋; 注釋由/和/包含;</p><p>  2.賦值運算: *=,/=</p><p>&

16、lt;b>  代碼如下:</b></p><p><b>  var x,y;</b></p><p><b>  begin</b></p><p><b>  x:=5;</b></p><p><b>  y:=10;</b><

17、;/p><p><b>  x*=y;</b></p><p><b>  y/=x;</b></p><p><b>  write(x);</b></p><p><b>  write(y);</b></p><p><b&

18、gt;  End.</b></p><p><b>  運行結(jié)果:</b></p><p><b>  開發(fā)過程</b></p><p><b>  .h</b></p><p>  # define norw 19 /*關鍵字個數(shù)*

19、/ //關鍵字個數(shù)數(shù)由初始值13增加至19</p><p>  # define txmax 100 /*名字表容量*/</p><p>  # define nmax 14 /*number的最大位數(shù)*/</p><p>  # define al 10 /*符號的最大

20、長度*/</p><p>  # define amax 2047 /*地址上界*/</p><p>  # define levmax 3 /*最大允許過程嵌套聲明層數(shù)[0,lexmax]*/</p><p>  # define cxmax 200 /*最多的虛擬機代碼數(shù)*/&

21、lt;/p><p><b>  /*符號*/</b></p><p>  //運算符 *=,/=</p><p>  enum symbol{</p><p>  nul, ident, number, plus, minus,</p><p>  times, sl

22、ash, oddsym, eql, neq,</p><p>  lss, leq, gtr, geq, lparen,</p><p>  rparen, comma, semicolon,period, becomes,</p><p>  beginsym, endsym, ifsym, then

23、sym, whilesym,</p><p>  writesym, readsym, dosym, callsym, constsym,</p><p>  varsym, procsym, timeseql, slasheql</p><p><b>  };</b></p><p>  #define s

24、ymnum 42 //符號數(shù)初始值由32增加至42</p><p><b>  .cpp</b></p><p>  strcpy(&(word[0][0]),"begin");</p><p>  strcpy(&(word[1][0]),"call");</p>&

25、lt;p>  strcpy(&(word[3][0]),"const");</p><p>  strcpy(&(word[4][0]),"do");</p><p>  strcpy(&(word[7][0]),"end");</p><p>  strcpy(&(w

26、ord[9][0]),"if");</p><p>  strcpy(&(word[10][0]),"odd");</p><p>  strcpy(&(word[11][0]),"procedure");</p><p>  strcpy(&(word[12][0]),"

27、read");</p><p>  strcpy(&(word[14][0]),"then");</p><p>  strcpy(&(word[16][0]),"var");</p><p>  strcpy(&(word[17][0]),"while");</p&

28、gt;<p>  strcpy(&(word[18][0]),"write");</p><p>  /*設置保留字符號*/</p><p>  wsym[0]=beginsym;</p><p>  wsym[1]=callsym;</p><p>  wsym[3]=constsym;</p

29、><p>  wsym[4]=dosym;</p><p>  wsym[7]=endsym;</p><p>  wsym[9]=ifsym;</p><p>  wsym[10]=oddsym;</p><p>  wsym[11]=procsym;</p><p>  wsym[12]=rea

30、dsym;</p><p>  wsym[14]=thensym;</p><p>  wsym[16]=varsym;</p><p>  wsym[17]=whilesym;</p><p>  wsym[18]=writesym;</p><p>  擴充賦值運算*=和/=</p><p>

31、;  在int statement(bool* fsys,int * ptx,int lev)中增加:        else if(sym==timeseql) // *=運算 </p><p><b>  {</b></p><p><b

32、>  getsymdo;</b></p><p>  memcpy(nxtlev,fsys,sizeof(bool)* symnum);</p><p>  gendo(lod,lev-table[i].level,table[i].adr);</p><p>  expressiondo(nxtlev,ptx,lev);</p>&

33、lt;p><b>  if(i!=0)</b></p><p><b>  {</b></p><p>  gendo(opr,0,4);</p><p>  gendo(sto,lev-table[i].level,table[i].adr);</p><p><b>  }<

34、;/b></p><p><b>  }</b></p><p>  else if(sym==slasheql) // /=運算 </p><p><b>  {</b></p><p><b>  getsymdo;</b></p><p> 

35、 memcpy(nxtlev,fsys,sizeof(bool)* symnum);</p><p>  gendo(lod,lev-table[i].level,table[i].adr);</p><p>  expressiondo(nxtlev,ptx,lev);</p><p><b>  if(i!=0)</b></p>

36、<p><b>  {</b></p><p>  gendo(opr,0,5);</p><p>  gendo(sto,lev-table[i].level,table[i].adr);</p><p><b>  }</b></p><p><b>  }</b&

37、gt;</p><p><b>  完成情況</b></p><p>  1、增加 注釋; 注釋由/和/包含</p><p>  2、*=,/=兩種賦值運算</p><p><b>  七、總結(jié)</b></p><p>  1、PL0代碼的框架有很大的局限性,用它來擴展高級語

38、言的某些語句的完整功能很麻煩,就例如各種基本類型之間的轉(zhuǎn)換,一個棧貌似不能精確地達到目標,多個不同數(shù)據(jù)類型的棧在PL0結(jié)構中又不能很好地轉(zhuǎn)換類型,多種數(shù)據(jù)類型間運算很不方便。</p><p>  2、在答辯的過程中,老師提問了以下幾個問題:</p><p> ?。?)在擴充賦值運算*=、/=時,一共用了幾個測試用例?</p><p>  一共用了1個測試用例。<

39、;/p><p> ?。?)在擴充賦值運算*=、/=時,分別在源代碼哪些地方進行了擴充?</p><p>  本次擴充是在statement函數(shù)中進行擴充,還在頭文件的enum symbol中增加了timeseql, slasheql。</p><p>  3、通過這個編譯原理PL/0編譯器的擴充,終于可以把課本的理論知識與實際問題結(jié)合起來。一開始由于對編譯原理的掌握還不

溫馨提示

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

評論

0/150

提交評論