編譯原理課程設(shè)計(jì)---pl0編輯器擴(kuò)充_第1頁(yè)
已閱讀1頁(yè),還剩16頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、<p><b>  編譯原理課程設(shè)計(jì)</b></p><p>  題 目 __ _PL0編輯器擴(kuò)充__ __</p><p>  學(xué) 院 計(jì)算機(jī)學(xué)院 </p><p>  專(zhuān) 業(yè) 軟件工程 </p><p>  2013 年 1 月 4

2、日</p><p><b>  課程設(shè)計(jì)目的與要求</b></p><p><b>  1、課程設(shè)計(jì)目的:</b></p><p>  在分析理解一個(gè)教學(xué)型編譯程序(如PL/0)的基礎(chǔ)上,對(duì)其詞法分析程序、語(yǔ)法分析程序和語(yǔ)義處理程序進(jìn)行部分修改擴(kuò)充。達(dá)到進(jìn)一步了解程序編譯過(guò)程的基本原理和基本實(shí)現(xiàn)方法的目的。</p&g

3、t;<p><b>  2、課程設(shè)計(jì)要求:</b></p><p>  基本內(nèi)容(成績(jī)范圍:“中”、“及格”或“不及格”)</p><p> ?。?)擴(kuò)充賦值運(yùn)算:*= 和 /=</p><p>  擴(kuò)充語(yǔ)句(Pascal的FOR語(yǔ)句):</p><p>  ①FOR <變量>:=<表達(dá)式

4、> TO <表達(dá)式> DO <語(yǔ)句></p><p> ?、贔OR <變量>:=<表達(dá)式> DOWNTO <表達(dá)式> DO <語(yǔ)句></p><p>  其中,語(yǔ)句①的循環(huán)變量的步長(zhǎng)為2,</p><p>  語(yǔ)句②的循環(huán)變量的步長(zhǎng)為-2。</p><p>  (3

5、)增加運(yùn)算:++ 和 --。</p><p>  選做內(nèi)容(成績(jī)?cè)u(píng)定范圍擴(kuò)大到:“優(yōu)”和“良”)</p><p> ?。?)增加類(lèi)型:① 字符類(lèi)型; ② 實(shí)數(shù)類(lèi)型。</p><p> ?。?)擴(kuò)充函數(shù):① 有返回值和返回語(yǔ)句;② 有參數(shù)函數(shù)。</p><p>  (3)增加一維數(shù)組類(lèi)型(可增加指令)。</p>

6、<p> ?。?)其他典型語(yǔ)言設(shè)施。</p><p><b>  二、結(jié)構(gòu)設(shè)計(jì)方案 </b></p><p><b>  結(jié)構(gòu)設(shè)計(jì)說(shuō)明:</b></p><p>  PL/0的編譯程序以語(yǔ)法分析程序?yàn)楹诵?,詞法分析程序和代碼生成程序都作為一個(gè)獨(dú)立的過(guò)程,當(dāng)語(yǔ)法分析需要讀單詞時(shí)就用詞法分析程序,而當(dāng)語(yǔ)法分析正確需生

7、成相應(yīng)的目標(biāo)代碼時(shí),則調(diào)用代碼生成程序。此外,用表格管理程序建立變量,常量和過(guò)程標(biāo)識(shí)符的說(shuō)明與引用之間的信息聯(lián)系。用出錯(cuò)處理程序?qū)υ~法和語(yǔ)法分析遇到的錯(cuò)誤給出在源程序中出錯(cuò)的位置和錯(cuò)誤性質(zhì)。</p><p><b>  各功能模塊圖示:</b></p><p>  3. 各功能模塊作用表:</p><p>  3. 符號(hào)名字表結(jié)構(gòu):</p

8、><p>  struct tablestruct</p><p><b>  {</b></p><p>  char name[al]; /*名字*/</p><p>  enum object kind; /*類(lèi)型:const,var,array or procedure*/</p>&

9、lt;p>  int val; /*數(shù)值,僅const使用*/</p><p>  int level; /*所處層,僅const不使用*/</p><p>  int adr; /*地址,僅const不使用*/</p><p>  int size; /*需要分配的數(shù)據(jù)

10、區(qū)空間,僅procedure使用*/</p><p><b>  };</b></p><p>  4. 保留關(guān)鍵字枚舉結(jié)構(gòu):</p><p>  enum symbol{</p><p>  nul, ident, number, plus,minus,</p><p>  t

11、imes, slash, oddsym, eql, neq,</p><p>  lss, leq, gtr, geq,lparen,</p><p>  rparen, comma, semicolon, period, becomes,</p><p>  beginsym, endsym,if

12、sym, thensym, whilesym,</p><p>  writesym, readsym, dosym, callsym, constsym,</p><p>  varsym, procsym, elsesym, forsym, tosym,</p><p>  downtosym, returnsym,

13、 pluseql, minuseql, plusplus,</p><p>  minusminus, </p><p><b>  };</b></p><p>  5.名字表中標(biāo)識(shí)符枚舉類(lèi)型:</p><p>

14、  enum object{</p><p>  constant, /*常量*/</p><p>  variable, /*變量*/</p><p>  procedur, /*過(guò)程*/</p><p><b>  };</b></p><p>

15、  6. 運(yùn)行時(shí)存儲(chǔ)組織和管理</p><p>  對(duì)于源程序的每一個(gè)過(guò)程(包括主程序),在被調(diào)用時(shí),首先在數(shù)據(jù)段中開(kāi)辟三個(gè)空間,存放靜態(tài)鏈SL、動(dòng)態(tài)鏈DL和返回地址RA。靜態(tài)鏈記錄了定義該過(guò)程的直接外過(guò)程(或主程序)運(yùn)行時(shí)最新數(shù)據(jù)段的基地址。動(dòng)態(tài)鏈記錄調(diào)用該過(guò)程前正在運(yùn)行的過(guò)程的數(shù)據(jù)段基址。返回地址記錄了調(diào)用該過(guò)程時(shí)程序運(yùn)行的斷點(diǎn)位置。對(duì)于主程序來(lái)說(shuō),SL、DL和RA的值均置為0。靜態(tài)鏈的功能是在一個(gè)子過(guò)程要引

16、用它的直接或間接父過(guò)程(這里的父過(guò)程是按定義過(guò)程時(shí)的嵌套情況來(lái)定的,而不是按執(zhí)行時(shí)的調(diào)用順序定的)的變量時(shí),可以通過(guò)靜態(tài)鏈,跳過(guò)個(gè)數(shù)為層差的數(shù)據(jù)段,找到包含要引用的變量所在的數(shù)據(jù)段基址,然后通過(guò)偏移地址訪問(wèn)它?! ≡谶^(guò)程返回時(shí),解釋程序通過(guò)返回地址恢復(fù)指令指針的值到調(diào)用前的地址,通過(guò)當(dāng)前段基址恢復(fù)數(shù)據(jù)段分配指針,通過(guò)動(dòng)態(tài)鏈恢復(fù)局部段基址指針。實(shí)現(xiàn)子過(guò)程的返回。對(duì)于主程序來(lái)說(shuō),解釋程序會(huì)遇到返回地址為0的情況,這時(shí)就認(rèn)為程序運(yùn)行結(jié)束。

17、  解釋程序過(guò)程中的base函數(shù)的功能,就是用于沿著靜態(tài)鏈,向前查找相差指定層數(shù)的局部數(shù)據(jù)段基址。這在使用sto、lod、stoArr、lodArr等訪問(wèn)局部變量的指令中會(huì)經(jīng)常用到。  類(lèi)PCO</p><p>  7. 擴(kuò)充賦值運(yùn)算:+= 和 -= 設(shè)計(jì):</p><p>  對(duì)于+=、-=、*=和/=賦值運(yùn)算符,在程序中出現(xiàn)的情況只有如下一種,文法的EBNF 表示為:</p&g

18、t;<p>  賦值語(yǔ)句::= <標(biāo)識(shí)符> [ += | -= ] <表達(dá)式></p><p> ?。?)擴(kuò)充的語(yǔ)法描述見(jiàn)結(jié)構(gòu)設(shè)計(jì)中的 PL/0 分程序和主要語(yǔ)句的語(yǔ)法描述中的描述圖;</p><p>  (2)分析區(qū)別賦值運(yùn)算符采用:讀標(biāo)識(shí)符后再讀一個(gè)字符,后根據(jù)讀到的字符轉(zhuǎn)去不同的賦值語(yǔ)句執(zhí)行。</p><p> ?。?

19、)中間代碼生成情況:+=運(yùn)算符,其他賦值運(yùn)算符架構(gòu)是一樣的,只是執(zhí)行加法改為相應(yīng)的算數(shù)運(yùn)算。</p><p>  else if(sym==pluseql) //檢測(cè)到+=符號(hào)</p><p><b>  {</b></p><p>  i=position(id,*ptx);

20、 //把類(lèi)x+=3的x的地址取出來(lái)</p><p>  gendo(lod,lev-table[i].level,table[i].adr); /*找到變量地址并將其值入棧*/</p><p><b>  getsymdo;</b></p><p>  if(sym==semicolon)</p>

21、;<p><b>  {</b></p><p><b>  getsymdo;</b></p><p><b>  }</b></p><p>  memcpy(nxtlev,fsys,sizeof(bool)* symnum);</p><p>  expre

22、ssiondo(nxtlev,ptx,lev);</p><p>  gendo(opr,0,2);</p><p><b>  if(i!=0)</b></p><p><b>  {</b></p><p>  gendo(sto,lev-table[i].level,table[i].adr)

23、;</p><p><b>  }</b></p><p><b>  }</b></p><p>  else if(sym==minuseql) //檢測(cè)到-=符號(hào)</p><p><b>  {</b></p&

24、gt;<p>  i=position(id,*ptx); //把類(lèi)x-=3的x的地址取出來(lái)</p><p>  gendo(lod,lev-table[i].level,table[i].adr); /*找到變量地址并將其值入棧*/</p><p><b>  getsymdo;</b>&l

25、t;/p><p>  if(sym==semicolon)</p><p><b>  {</b></p><p><b>  getsymdo;</b></p><p><b>  }</b></p><p>  memcpy(nxtlev,fsys,si

26、zeof(bool)* symnum);</p><p>  expressiondo(nxtlev,ptx,lev);</p><p>  gendo(opr,0,3);</p><p><b>  if(i!=0)</b></p><p><b>  {</b></p><p

27、>  gendo(sto,lev-table[i].level,table[i].adr);</p><p><b>  }</b></p><p><b>  }</b></p><p>  8.擴(kuò)充語(yǔ)句(Pascal的FOR語(yǔ)句):</p><p> ?、貴OR <變量&g

28、t;:=<表達(dá)式> TO <表達(dá)式> DO <語(yǔ)句></p><p> ?、贔OR <變量>:=<表達(dá)式> DOWNTO <表達(dá)式> DO <語(yǔ)句></p><p>  其中,語(yǔ)句①的循環(huán)變量的步長(zhǎng)為2,</p><p>  語(yǔ)句②的循環(huán)變量的步長(zhǎng)為-2</p><

29、;p>  For i:= E1 to E2 do S1 循環(huán)語(yǔ)句ALGOL等價(jià)于:</p><p><b>  i:= E1;</b></p><p>  goto OVER;</p><p>  AGAIN :i:= i+2</p><p>  OVER : if i<E2 then </p>

30、;<p><b>  Begin S1;</b></p><p>  goto again end;</p><p>  注意程序中基礎(chǔ)用到循環(huán)控制變量i,因此 entry(i)必須被保存下來(lái),而Pascal這樣的語(yǔ)言中,循環(huán)變量在循環(huán)外也是可見(jiàn)的,本次擴(kuò)充約定循環(huán)步長(zhǎng)為 2或者-2。具體需要在程序staement()添加for的句法判斷:</p&

31、gt;<p>  else if(sym==forsym) //檢測(cè)到for語(yǔ)句</p><p><b>  {</b></p><p><b>  getsymdo;</b></p><p>  if(sym==ident)</p><p><b>  {<

32、/b></p><p>  i=position(id,*ptx);</p><p>  if(i==0) error(11);</p><p><b>  else</b></p><p><b>  {</b></p><p>  if(table[i].kind!

33、=variable) //賦值語(yǔ)句中,賦值號(hào)左部標(biāo)識(shí)符屬性應(yīng)是變量</p><p><b>  {</b></p><p>  error(12);i=0;</p><p><b>  }</b></p><p><b>  else</b></p><p&

34、gt;<b>  {</b></p><p><b>  getsymdo;</b></p><p>  if(sym!=becomes) error(13); //賦值語(yǔ)句左部標(biāo)識(shí)符后應(yīng)是賦值號(hào):=</p><p>  else getsymdo;</p><p>  me

35、mcpy(nxtlev,fsys,sizeof(bool)*symnum); </p><p>  nxtlev[tosym]=true; //后跟符to和downto</p><p>  nxtlev[downtosym]=true;</p><p>  expressiondo(nxtlev,ptx,lev);

36、 //處理賦值語(yǔ)句右部的表達(dá)式E1</p><p>  gendo(sto,lev-table[i].level,table[i].adr); //保存初值</p><p>  switch(sym)</p><p><b>  {</b></p><p>  case tosym: //步長(zhǎng)

37、為的向上增加</p><p><b>  getsymdo;</b></p><p>  cx1=cx; //保存循環(huán)開(kāi)始點(diǎn)</p><p>  //將循環(huán)判斷變量取出放到棧頂</p><p>  gendo(lod,lev-table[i].level,table[i].adr);

38、 memcpy(nxtlev,fsys,sizeof(bool)*symnum); //處理表達(dá)式E2</p><p>  nxtlev[dosym]=true; //后跟符do</p><p>  expressiondo(nxtlev,ptx,lev);</p><p>  gendo

39、(opr,0,13); //生成比較指令,i是否小于等于E2的值</p><p>  cx2=cx; //保存循環(huán)結(jié)束點(diǎn)</p><p>  //生成條件跳轉(zhuǎn)指令,跳出循環(huán),跳出的地址未知</p><p>  gendo(jpc,0,0);</p><p>  if

40、(sym==dosym) //處理循環(huán)體S</p><p><b>  {</b></p><p><b>  getsymdo;</b></p><p>  statement(fsys,ptx,lev); //循環(huán)體處理</p><p>  //增加循環(huán)變量步長(zhǎng)為&

41、lt;/p><p>  //將循環(huán)變量取出放在棧頂</p><p>  gendo(lod,lev-table[i].level,table[i].adr); gendo(lit,0,1); //將步長(zhǎng)取到棧頂</p><p>  gendo(opr,0,2);

42、 //循環(huán)變量加步長(zhǎng)</p><p>  //將棧頂?shù)闹荡嫒胙h(huán)變量</p><p>  gendo(sto,lev-table[i].level,table[i].adr); </p><p>  gendo(jmp,0,cx1); //無(wú)條件跳轉(zhuǎn)到循環(huán)開(kāi)始點(diǎn)</p><p&

43、gt;  code[cx2].a=cx;</p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  error(29); //for語(yǔ)句中少了do</p>&

44、lt;p><b>  }</b></p><p><b>  break;</b></p><p>  case downtosym: //步長(zhǎng)為的向下減少</p><p><b>  getsymdo;</b></p><p>  cx1=cx;

45、 //保存循環(huán)開(kāi)始點(diǎn)</p><p>  //將循環(huán)判斷變量取出放到棧頂</p><p>  gendo(lod,lev-table[i].level,table[i].adr); memcpy(nxtlev,fsys,sizeof(bool)*symnum); //處理表達(dá)式E2</p>

46、;<p>  nxtlev[dosym]=true; //后跟符do</p><p>  expressiondo(nxtlev,ptx,lev);</p><p>  gendo(opr,0,11); //生成比較指令,i是否大于等于E2的值</p><p>  cx2=cx;

47、 //保存循環(huán)結(jié)束點(diǎn)</p><p>  //生成條件跳轉(zhuǎn)指令,跳出循環(huán),跳出的地址未知</p><p>  gendo(jpc,0,0); </p><p>  if(sym==dosym) //處理循環(huán)體S</p><p><b>  {</b></p><p&g

48、t;<b>  getsymdo;</b></p><p>  statement(fsys,ptx,lev); //循環(huán)體處理</p><p>  //增加循環(huán)變量步長(zhǎng)為</p><p>  //將循環(huán)變量取出放在棧頂</p><p>  gendo(lod,lev-table[i].level,table[i].

49、adr); gendo(lit,0,1); //將步長(zhǎng)取到棧頂</p><p>  gendo(opr,0,3); //循環(huán)變量加步長(zhǎng)</p><p>  //將棧頂?shù)闹荡嫒胙h(huán)變量</p><p>  gendo(sto,lev

50、-table[i].level,table[i].adr); gendo(jmp,0,cx1); //無(wú)條件跳轉(zhuǎn)到循環(huán)開(kāi)始點(diǎn)</p><p>  code[cx2].a=cx;</p><p><b>  }</b></p><p><b>  else </b>

51、</p><p><b>  {</b></p><p>  error(29);//for語(yǔ)句中少了do</p><p><b>  }</b></p><p><b>  break;</b></p><p><b>  }</b&g

52、t;</p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  else </b></p><p><b>  {</b>

53、;</p><p>  error(19); //for語(yǔ)句后跟賦值語(yǔ)句,賦值語(yǔ)句左部是變量,缺少變量</p><p><b>  }</b></p><p><b>  }</b></p><p>  11. 增加運(yùn)算:++ 和 -- :</p><p> 

54、 對(duì)于++和--運(yùn)算符,擴(kuò)充時(shí)要注意存在++,--有兩個(gè)情況:1、作為語(yǔ)句的時(shí)候;2、作為表達(dá)式中的因子的時(shí)候.</p><p>  (1) 作為語(yǔ)句的時(shí)候,有四種情況:</p><p>  A++ ++A A-- --A</p><p>  文法的 EBNF 表示形式為:</p><p>  <自增自減語(yǔ)句>::=&l

55、t;標(biāo)識(shí)符>[ ++ | -- ] | [ ++ | -- ]<標(biāo)識(shí)符></p><p>  (2) 作為因子的時(shí)候,有兩種情況</p><p>  a++和 a--作為因子,比如:b:=a++*a--;語(yǔ)句</p><p>  ++a 和--a 作為因子,比如:b:= --a+2*++a;語(yǔ)句</p><p>  文法的

56、EBNF 表示形式為:</p><p>  <表達(dá)式>::=...[ ++ | -- ]<標(biāo)識(shí)符>|<標(biāo)識(shí)符>[ ++ | -- ]...</p><p>  其中的...表示前后都可以有其他的項(xiàng)或因子</p><p>  (1)作為語(yǔ)句 ++ -- 符號(hào)分為以下兩種情況考慮:</p><p>  情況1對(duì)

57、于自增自減符號(hào)置后的只需要在判斷+= -=后面添加句法分析即可:</p><p>  /*************后置自增符號(hào) a++ a--類(lèi)型添加代碼****************************/</p><p>  else if(sym==plusplus) //檢測(cè)到后置++符號(hào)</p><p>&

58、lt;b>  {</b></p><p>  gendo(lit,0,1);</p><p>  gendo(lod,lev-table[i].level,table[i].adr); /*找到變量地址并將其值入棧*/</p><p>  gendo(opr,0,2); //執(zhí)行加操作,</p>

59、<p><b>  if(i!=0)</b></p><p><b>  {</b></p><p>  gendo(sto,lev-table[i].level,table[i].adr);</p><p><b>  }</b></p><p><b&g

60、t;  getsymdo;</b></p><p><b>  }</b></p><p>  else if(sym==minusminus) //檢測(cè)到后置--符號(hào)</p><p><b>  {</b></p><p>  gendo

61、(lod,lev-table[i].level,table[i].adr); /*找到變量地址并將其值入棧*/</p><p>  gendo(lit,0,1);</p><p>  gendo(opr,0,3); //執(zhí)行減操作,</p><p><b>  if(i!=0)</b>&

62、lt;/p><p><b>  {</b></p><p>  gendo(sto,lev-table[i].level,table[i].adr);</p><p><b>  }</b></p><p>  getsymdo;</p><p><b>  

63、}</b></p><p>  情況2對(duì)于++ --前置的需要添加因子開(kāi)始符號(hào):</p><p>  facbegsys[plusplus]=true; /***增加符號(hào)++開(kāi)始因子plusplus***/</p><p>  facbegsys[minusminus]=true; /***增加符號(hào)--開(kāi)始因子minusminu

64、s***/</p><p>  /***************前置自增符號(hào) ++a - -a類(lèi)型添加代碼****************************/</p><p>  if(sym==plusplus)</p><p><b>  {</b></p><p><b>  getsymdo;&l

65、t;/b></p><p>  if(sym==ident) //后面跟的是變量</p><p><b>  {</b></p><p>  i=position(id,*ptx);</p><p><b>  if

66、(i==0)</b></p><p><b>  {</b></p><p>  error(11);</p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b

67、></p><p>  if(table[i].kind!=variable) //++后沒(méi)跟變量,出錯(cuò)</p><p><b>  {</b></p><p>  error(12);</p><p><b>  i=0;</b></p&

68、gt;<p><b>  }</b></p><p>  else //++后跟變量,處理生成中間代碼</p><p><b>  {</b></p><p>  if(table[i].kind==variable)&l

69、t;/p><p><b>  {</b></p><p>  gendo(lod,lev-table[i].level,table[i].adr);//先取值到棧頂</p><p>  gendo(lit,0,1); //將值為入棧</p><p>  gendo(opr

70、,0,2); //加法,即+1,棧頂加次棧頂</p><p>  gendo(sto,lev-table[i].level,table[i].adr);//出棧取值到內(nèi)存</p><p><b>  getsymdo;</b></p><p><b>  }</b>&l

71、t;/p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  else if(sym==minusminus)<

72、;/p><p><b>  {</b></p><p><b>  getsymdo;</b></p><p>  if(sym==ident) //后面跟的是變量</p><p><b>  {</

73、b></p><p>  i=position(id,*ptx);</p><p><b>  if(i==0)</b></p><p><b>  {</b></p><p>  error(11);</p><p><b>  }</b><

74、;/p><p><b>  else</b></p><p><b>  {</b></p><p>  if(table[i].kind!=variable) //--后沒(méi)跟變量,出錯(cuò)</p><p><b>  {</b></

75、p><p>  error(12);</p><p><b>  i=0;</b></p><p><b>  }</b></p><p>  else //--后跟變量,處理生成中間代碼</p>&l

76、t;p><b>  {</b></p><p>  if(table[i].kind==variable) //后跟變量</p><p><b>  {</b></p><p>  gendo(lod,lev-table[i].level,table[i].adr);//先取值到

77、棧頂</p><p>  gendo(lit,0,1); //將值為入棧</p><p>  gendo(opr,0,3); //加法,即-1,棧頂減次棧頂</p><p>  gendo(sto,lev-table[i].level,table[i].adr

78、);//出棧取值到內(nèi)存</p><p><b>  getsymdo;</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>

79、;  }</b></p><p><b>  }</b></p><p> ?。?)作為因子的時(shí)候也有兩種情形考慮:</p><p>  添加int factor(bool*fsys,int *ptx,int lev)函數(shù)如下:</p><p>  /********************如果因子可能出現(xiàn)b

80、:=a++或b:=a--類(lèi)型的處理******************/if(sym==plusplus)</p><p><b>  {</b></p><p>  gendo(lit,lev-table[i].level,1); //將值為入棧</p><p>  gendo(opr,lev-table[i].le

81、vel,2); //加法,即+1,棧頂加次棧頂</p><p>  gendo(sto,lev-table[i].level,table[i].adr); //出棧取值到內(nèi)存</p><p>  gendo(lod,lev-table[i].level,table[i].adr); //取值到棧頂</p><p>  gendo(lit,0,1

82、);</p><p>  gendo(opr,0,3); //棧頂值減</p><p><b>  getsymdo;</b></p><p><b>  }</b></p><p>  else if(sym==minusminus)<

83、/p><p><b>  {</b></p><p>  gendo(lit,lev-table[i].level,1); //將值為入棧</p><p>  gendo(opr,lev-table[i].level,3); //減法,即-1,棧頂減次棧頂</p><p>  ge

84、ndo(sto,lev-table[i].level,table[i].adr); //出棧取值到內(nèi)存</p><p>  gendo(lod,lev-table[i].level,table[i].adr);</p><p>  gendo(lit,0,1);</p><p>  gendo(opr,0,2);

85、 //棧頂值加</p><p><b>  getsymdo;</b></p><p>  } /********************************************************************************/</p><p>  /************如果因子是表達(dá)式的時(shí)候,則有可能是包

86、含++a或者--a,如b:=++a或b:=--a ********/</p><p>  else if(sym==plusplus)</p><p><b>  {</b></p><p><b>  getsymdo;</b></p><p>  if(sym==ident)</p>

87、<p><b>  {</b></p><p><b>  getsymdo;</b></p><p>  i=position(id,*ptx);</p><p><b>  if(i==0)</b></p><p><b>  {</b>

88、</p><p>  error(11);</p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  if(table[i].kind==variable) //變

89、量</p><p><b>  {</b></p><p><b>  //先加后再用a</b></p><p>  gendo(lod,lev-table[i].level,table[i].adr);//先取值到棧頂</p><p>  gendo(lit,0,1);//將值為入棧</p&

90、gt;<p>  gendo(opr,0,2);//加法,即+1,棧頂加次棧頂</p><p>  gendo(sto,lev-table[i].level,table[i].adr);//出棧取值到內(nèi)存</p><p>  gendo(lod,lev-table[i].level,table[i].adr); //取值到棧頂}</p><p&g

91、t;<b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  else if(sym==minusminus)</p><p><b>  {</b></p><p>

92、;<b>  getsymdo;</b></p><p>  if(sym==ident)</p><p><b>  {</b></p><p><b>  getsymdo;</b></p><p>  i=position(id,*ptx);</p><

93、;p><b>  if(i==0)</b></p><p><b>  {</b></p><p>  error(11);</p><p><b>  }</b></p><p><b>  else</b></p><p>

94、;<b>  {</b></p><p>  if(table[i].kind==variable) //變量</p><p><b>  {</b></p><p><b>  //先減后再用a</b></p><p>  gendo(lod,lev-table[i].le

95、vel,table[i].adr);//先取值到棧頂</p><p>  gendo(lit,0,1); //將值為入棧</p><p>  gendo(opr,0,3); //減法,即-1,棧頂減次棧頂</p><p>  gendo(sto,lev-table[i

96、].level,table[i].adr);//出棧取值到內(nèi)存</p><p>  gendo(lod,lev-table[i].level,table[i].adr); //取值到棧頂}</p><p><b>  }</b></p><p><b>  }</b></p><p>  

97、testdo(fsys,facbegsys,23); /*因子后有非法符號(hào)*/</p><p><b>  }</b></p><p><b>  程序測(cè)試</b></p><p>  擴(kuò)充賦值運(yùn)算:*= 和 /=</p><p>  測(cè)試文件 “test1”:<

98、/p><p><b>  運(yùn)行結(jié)果:</b></p><p><b>  結(jié)果分析:</b></p><p>  a = 5 ,b = 48 , a*=3 結(jié)果為15正確,b/=6結(jié)果為8正確,擴(kuò)充成功!</p><p>  擴(kuò)充語(yǔ)句(Pascal的FOR語(yǔ)句):</p><p>

99、;  測(cè)試文件“test2”:</p><p><b>  運(yùn)行結(jié)果:</b></p><p><b>  結(jié)果分析:</b></p><p>  For i=1 to 4 do “write(i)” 結(jié)果i= 1,3,</p><p>  For i=5 downto 1 do write(i)

100、 結(jié)果i= 5,3,1</p><p><b>  結(jié)果正確,</b></p><p>  For循環(huán)功能擴(kuò)充成功!</p><p>  增加運(yùn)算:++ 和 --。</p><p>  測(cè)試文件“test3”:</p><p><b>  運(yùn)行結(jié)果:</b></p>

101、;<p><b>  結(jié)果分析:</b></p><p>  a=5 ,b:=6, a--結(jié)果為4,b++結(jié)果為7,結(jié)果正確 </p><p>  ++ ,--功能符號(hào)測(cè)試通過(guò)!</p><p><b>  實(shí)驗(yàn)總結(jié)</b></p><p>  本次課程設(shè)計(jì)主要是在讀懂課

102、本附帶的PL/0 編譯器程序C語(yǔ)言版本后進(jìn)行擴(kuò)展和修改相關(guān)程序功能。</p><p>  通過(guò)課程設(shè)計(jì),我對(duì)編譯器的工作原理和實(shí)現(xiàn)機(jī)制有了實(shí)際的了解和認(rèn)識(shí),進(jìn)一步培養(yǎng)的編譯技術(shù)的設(shè)計(jì)思想,仔細(xì)閱讀 PL/0 的編譯程序C語(yǔ)言版本代碼,對(duì)詞法分析,句法分析在編程技巧和實(shí)際意義有了深刻的理解,從枯燥的理論學(xué)習(xí)到現(xiàn)在實(shí)際應(yīng)用過(guò)程對(duì)于我自身知識(shí)面的提升是巨大的。語(yǔ)法分析、句法分析在編譯原理中處于核心的地位,如何正確有效的

103、對(duì)它們分析提取決定了編譯后期工作方向,當(dāng)然中間代碼的如何有效的生成在編譯中也是個(gè)不小的難題,特別是其中堆棧的運(yùn)用,當(dāng)然在理論上對(duì)于它們的理解程度大小也是決定設(shè)計(jì)調(diào)試</p><p><b>  難度的高低。</b></p><p>  擴(kuò)展 += -= 符號(hào)相對(duì)比較簡(jiǎn)單,只需要在語(yǔ)句分析模塊接著賦值符號(hào)的判斷添加就可以,對(duì)于for循環(huán)也是類(lèi)似,只需要在語(yǔ)句分析模塊添加

104、對(duì)于for關(guān)鍵字的判斷,當(dāng)然要注意后繼符號(hào)to 還是 downto的判斷以決定步長(zhǎng)遞增還是遞減。完成了基本功能擴(kuò)展,我嘗試了++ --符號(hào)的添加,這兩個(gè)符號(hào)添加比較復(fù)雜,大體講有兩個(gè)用途情況,一個(gè)就是用在用戶(hù)標(biāo)識(shí)符,另一個(gè)就是在因子上也可能用到該功能,需要添加因子的功能判斷,具體來(lái)講這兩個(gè)符號(hào)又有兩種實(shí)現(xiàn)形式,分別是后置符號(hào)和前置符號(hào),后置符號(hào)類(lèi)似前面的+= -= 直接添加判斷即可,前置符號(hào)則除了要添加++ --的開(kāi)始因子符號(hào)集外,還得

105、在語(yǔ)句分析模塊添加功能處理!</p><p>  總的來(lái)說(shuō),經(jīng)歷了數(shù)次的調(diào)試,功能擴(kuò)展算是完成了,這次課程設(shè)計(jì)使我受益匪淺,除了更深了解了編譯技術(shù),還培養(yǎng)了發(fā)現(xiàn)問(wèn)題、分析問(wèn)題、解決問(wèn)題的能力!</p><p><b>  附錄:</b></p><p>  源語(yǔ)言:PL/0語(yǔ)言 </p><p>  目標(biāo)語(yǔ)言:類(lèi)PCOD

溫馨提示

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

評(píng)論

0/150

提交評(píng)論