廣工編譯原理實驗報告_第1頁
廣工編譯原理實驗報告_第2頁
廣工編譯原理實驗報告_第3頁
廣工編譯原理實驗報告_第4頁
廣工編譯原理實驗報告_第5頁
已閱讀5頁,還剩12頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

PAGEPAGE2<<編譯原理>>課內(nèi)實驗報告項目名稱PL/0編譯器學(xué)院____計算機(jī)學(xué)院_______專業(yè)__年級班別________學(xué)號_學(xué)生姓名__________輔導(dǎo)教師_______成績______________目錄一、課內(nèi)實驗的內(nèi)容4二、實驗修改部分4三、概述11四、結(jié)構(gòu)設(shè)計說明11五、各功能模塊描述14六、主要成份描述14七、測試用例16八、開發(fā)過程和完成情況21一、課內(nèi)實驗的內(nèi)容對PL/0作以下修改擴(kuò)充:(1)增加單詞:保留字ELSE,F(xiàn)OR,STEP,RETURN運算符+=,-=,++,--,&,|,~(2)修改單詞:不等號#改為<>(3)增加條件語句的ELSE子句二、實驗修改部分:1、增加四個保留字和七個運算符,共十一個單詞。修改部分:#definesymnum43//保留字從32增加到43個2、增加五個保留字:ELSE,F(xiàn)OR,STEP,RETURNeq\o\ac(○,1)頭文件pl0.henumsymbol{新增加單詞:elsesym,forsym,stepsym,returnsym,pluseq/*+=*/,plusone/*++*/,plus/*+*/,minuseq/*-=*/,minusone/*--*/,minus/*-*/,and,or,not}eq\o\ac(○,2)頭文件pl0.h#definenorw24//關(guān)鍵字從13增加到24個eq\o\ac(○,3)PL0.cppinit();新增加:(增加后數(shù)組的內(nèi)容要再次根據(jù)字母順序重新排列) strcpy(&(word[0][0]),"begin"); strcpy(&(word[1][0]),"call"); strcpy(&(word[2][0]),"const"); strcpy(&(word[3][0]),"do"); strcpy(&(word[4][0]),"else");/*增加單詞:保留字else*/ strcpy(&(word[5][0]),"end"); strcpy(&(word[6][0]),"for");/*增加單詞:保留字for*/ strcpy(&(word[7][0]),"if");strcpy(&(word[8][0]),"odd"); strcpy(&(word[9][0]),"procedure"); strcpy(&(word[10][0]),"read"); strcpy(&(word[11][0]),"return");/*增加單詞:保留字return*/ strcpy(&(word[12][0]),"step");/*增加單詞:保留字step*/ strcpy(&(word[13][0]),"then"); strcpy(&(word[14][0]),"while"); strcpy(&(word[15][0]),"write"); wsym[0]=beginsym; wsym[1]=callsym; wsym[2]=constsym; wsym[3]=dosym; wsym[4]=elsesym;/*else*/ wsym[5]=endsym; wsym[6]=forsym; /*for*/ wsym[7]=ifsym; wsym[8]=oddsym; wsym[9]=procsym; wsym[10]=readsym;wsym[11]=returnsym;/*return*/ wsym[12]=stepsym;/*step*/ wsym[13]=thensym; wsym[14]=whilesym; wsym[15]=writesym;3、增加四個運算符:+=,-=,++,--,∧,∨,┓PL0.cppgetsym();增加對+,-,++,--,+=,-=的識別;Statement();增加對+,-,++,--,-=的語句的處理;eq\o\ac(○,1)Init()中改動: ssym[‘&’]=and; ssym[‘|’]=or;ssym[‘~’]=not;facbegsys[plusone]=true;//添加前自加運算facbegsys[minusone]=true;//添加前自減運算eq\o\ac(○,2)Getsym()增加的內(nèi)容:intgetsym(){ inti,j,k; while(ch==''||ch==10||ch==9) { getchdo; } if(ch>='a'&&ch<='z') { k=0; do{ if(k<al) { a[k]=ch; k++; } getchdo; }while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9'); a[k]=0; strcpy(id,a); i=0; j=norw-1; do{ k=(i+j)/2; if(strcmp(id,word[k])<=0) { j=k-1; } if(strcmp(id,word[k])>=0) { i=k+1; } }while(i<=j); if(i-1>j) { sym=wsym[k]; } else { sym=ident; } } else { if(ch>='0'&&ch<='9') { k=0; num=0; sym=number; do{ num=10*num+ch-'0'; k++; getchdo; }while(ch>='0'&&ch<='9');/*獲取數(shù)字的值*/ k--; if(k>nmax) { error(30); } } else { if(ch==':')/*檢測賦值符號*/ { getchdo; if(ch=='=') { sym=becomes; getchdo; } else { sym=nul;/*不能識別的符號*/ } } else { if(ch=='<')/*檢測小于或小于等于符號*/ { getchdo; if(ch=='=') { sym=leq; getchdo; } else { sym=lss; } } elseif(ch=='>')/*檢測大于或大于等于符號*/ { getchdo; if(ch=='=') { sym=geq; getchdo; } else { sym=gtr; } }/*這里之間為添加的內(nèi)容*/ elseif(ch=='+'){ /*檢測+,+=,++符號*/ getchdo; if(ch=='='){ sym=pluseq; getchdo; }elseif(ch=='+'){ sym=plusone; getchdo; }else{ sym=plus; } }elseif(ch=='-'){/*檢測-,-=,--符號*/ getchdo; if(ch=='=') { sym=minuseq; getchdo; } elseif(ch=='-') { sym=minusone; getchdo; } else { sym=minus; } }/*這里之間為添加的內(nèi)容*/else{ sym=ssym[ch];/*當(dāng)符號不滿足上述條件時,全部按照單字符號處理*/ //getchdo; //richard if(sym!=period) { getchdo; } //endrichard } } } }return0;}eq\o\ac(○,3)Statement()增加的內(nèi)容:(將本來“if(sym==becomes)……”部分的內(nèi)容修改為處理++,+=,--,-=),并在Statement()中定義變量intsym2; if(sym==becomes||sym==pluseq||sym==minuseq||sym==plusone||sym==minusone) {sym2=sym; getsymdo; gendo(lod,lev-table[i].level,table[i].adr); } else { error(13); } if(sym2==plusone||sym2==minusone)/*準(zhǔn)備按照a++、a--語句處理,與read類似*/ { if(i!=0) {if(sym2==plusone) { gendo(lit,0,1); gendo(opr,0,2); gendo(sto,lev-table[i].level,table[i].adr); } if(sym2==minusone) { gendo(lit,0,1); gendo(opr,0,3); gendo(sto,lev-table[i].level,table[i].adr); } } } else { memcpy(nxtlev,fsys,sizeof(bool)*symnum); expressiondo(nxtlev,ptx,lev); if(i!=0) { if(sym2==becomes) gendo(sto,lev-table[i].level,table[i].adr); if(sym2==pluseq) { gendo(opr,0,2); gendo(sto,lev-table[i].level,table[i].adr); } if(sym2==minuseq) { gendo(opr,0,3); gendo(sto,lev-table[i].level,table[i].adr); } } }//else } }}4、修改單詞:不等號#改為<>PL0.cppinit();移除:ssym['#']=neq;eq\o\ac(○,1)在getsym()里增加對<>的識別(在<或<=基礎(chǔ)上修改)。下面為在<基礎(chǔ)上修改,注意在if(ch==’<’)中修改,不包括elseif(ch=='>')那部分:if(ch=='<')/*檢測小于或小于等于符號*/ { getchdo; if(ch=='=') { sym=leq; getchdo; }/*在之間添加*/ elseif(ch=='>')//addneq { sym=neq; getchdo; } /*在之間添加*/ else { sym=lss; } }5、增加條件語句的ELSE子句PL0.cppeq\o\ac(○,1)在statement()里的“if...then”語句處理的基礎(chǔ)上添加對else子句的處理,使之能處理if……then……else……的語句。else { if(sym==ifsym)/*準(zhǔn)備按照if語句處理*/ { getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[thensym]=true; nxtlev[dosym]=true;/*后跟符號為then或do*/ conditiondo(nxtlev,ptx,lev);/*調(diào)用條件處理(邏輯運算)函數(shù)*/ if(sym==thensym) { getsymdo; } else { error(16);/*缺少then*/ } cx1=cx;/*保存當(dāng)前指令地址*/ gendo(jpc,0,0);/*生成條件跳轉(zhuǎn)指令,跳轉(zhuǎn)地址暫寫0*//*這里之間開始添加*/ memcpy(nxtlev,fsys,sizeof(bool)*symnum);//添加后跟符號 nxtlev[elsesym]=true; statementdo(nxtlev,ptx,lev);/*處理then后的語句*/ code[cx1].a=cx;/*經(jīng)statement處理后,cx為then后語句執(zhí)行完的位置,它正是前面未定的跳轉(zhuǎn)地址*/ if(sym==elsesym) { cx2=cx; getsymdo; gendo(jmp,0,0); code[cx1].a=cx; statementdo(fsys,ptx,lev); code[cx2].a=cx; } /*這里之間開始添加*/ } else { if(sym==beginsym)/*準(zhǔn)備按照復(fù)合語句處理*/ { getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[semicolon]=true; nxtlev[endsym]=true;/*后跟符號為分號或end*/ /*循環(huán)調(diào)用語句處理函數(shù),直到下一個符號不是語句開始符號或收到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或分號*/ } } eq\o\ac(○,2)寫出相關(guān)文法: G(S):S→ifSelseS|ifS|a eq\o\ac(○,3)Else語法圖: 三、概述源語言:PL/0語言目標(biāo)語言:假想棧式計算機(jī)的匯編語言實現(xiàn)工具:VC++6.0運行平臺:Windows7四、結(jié)構(gòu)設(shè)計說明1、PL/0編譯程序的結(jié)構(gòu)圖如下:由于PL/0編譯程序采用一趟掃描方法,所以語法語義分析過程block是整個編譯程序的核心。下面給出編譯程序的總體流程圖,以弄清block過程在整個編譯程序中的作用。在流程圖中可以看出,主程序置初值后先調(diào)整用讀單詞過程getsym取一個單詞,然后再調(diào)用語法分析過程block,直到遇源程序的結(jié)束符“.”為止。各功能模塊描述eq\o\ac(○,1)GetSym():詞法分析,從源文件中讀出若干有效字符,組成token串,識別它的類型為保留字/標(biāo)識符/數(shù)字或其它符號。eq\o\ac(○,2)GEN():目標(biāo)代碼生成過程,本過程用于把生成的目標(biāo)代碼寫入目標(biāo)代碼數(shù)組,供后面的解釋器解釋執(zhí)行.eq\o\ac(○,3)TEST():測試當(dāng)前單詞是否合法eq\o\ac(○,4)ENTER():在名字表中加入一項eq\o\ac(○,5)POSITION():查找名字的位置,找到則返回名字表中的位置,否則返回0eq\o\ac(○,6)ConstDeclaration():常量聲明處理eq\o\ac(○,7)VarDeclaration():變量聲明處理eq\o\ac(○,8)ListCode():輸出目標(biāo)代碼清單eq\o\ac(○,9)FACTOR():因子處理過程eq\o\ac(○,10)TERM():項處理過程eq\o\ac(○,11)EXPRESSION():表達(dá)式處理過程eq\o\ac(○,12)CONDITION():條件處理過程eq\o\ac(○,13)STATEMENT():語句處理過程eq\o\ac(○,14)Block():編譯程序主體,參數(shù):lev:這一次語法分析所在的層次,tx:符號表指針,eq\o\ac(○,15)fsys:用于出錯恢復(fù)的單詞集合eq\o\ac(○,16)BASE():通過過程基址求上一層過程的基址eq\o\ac(○,16)Interpret():解釋程序,PL/0編譯器產(chǎn)生的類PCODE目標(biāo)代碼解釋運行過程六、主要成份描述1.符號表在編譯程序中符號表用來存放語言程序中出現(xiàn)的有關(guān)標(biāo)識符的屬性信息,這些信息集中反映了標(biāo)識符的語義特征屬性.符號表的主要功能如下:eq\o\ac(○,1)、收集符號屬性eq\o\ac(○,2)、上下文語義合法性檢查的依據(jù)eq\o\ac(○,3)、作為目標(biāo)代碼生成階段地址分配的依據(jù).eq\o\ac(○,4)、符號表的數(shù)據(jù)結(jié)構(gòu):structtablestruct{charname[al];/*名字*/enumobjectkind;/*類型:const,var,arrayorprocedure*/intval;/*數(shù)值,僅const使用*/intlevel;/*所處層,僅const不使用*/intadr;/*地址,僅const不使用*/intsize;/*需要分配的數(shù)據(jù)區(qū)空間,僅procedure使用*/}; structtablestructtable[txmax];/*名字表*/2.運行時的存儲組織和管理當(dāng)源程序經(jīng)過語法分析,如果未發(fā)現(xiàn)錯誤時,由編譯程序調(diào)用解釋程序,對存放在CODE中的代碼CODE[0]開始進(jìn)行解釋執(zhí)行.當(dāng)廢棄結(jié)束后,記錄源程序中標(biāo)識符的TABLE表已沒有作用.因此存儲區(qū)只需以數(shù)組CODE存主的只讀目標(biāo)程序和運行機(jī)制時的數(shù)據(jù)區(qū)S,S是由解釋程序定義的一維整數(shù)型數(shù)組.解釋執(zhí)行時的數(shù)據(jù)空間S為棧式計算機(jī)的在座空間,遵循后進(jìn)先出規(guī)則,對每個過程(包括主程序)當(dāng)調(diào)用時,才分配數(shù)據(jù)空間,退出過程進(jìn),則所分配原則的數(shù)據(jù)空間被釋放.解釋程序還定義了4個寄存器:1、指令寄存器.存放當(dāng)前正在解釋的一條目標(biāo)指令2、程序地址寄存器.指向下一條要執(zhí)行的目標(biāo)程序的地址3、棧頂寄存器.4、基址寄存器.指向每個過程被調(diào)用時,在數(shù)據(jù)區(qū)S中給它分配原則的數(shù)據(jù)段起始地址,也稱基地址.為了實現(xiàn)過程被調(diào)用時給它分配數(shù)據(jù)段,過程運行結(jié)束后釋放數(shù)據(jù)段以及嵌套過程之間結(jié)標(biāo)志符引用的問題,當(dāng)過程被調(diào)用時,在棧頂分配三個聯(lián)系單元,這三個聯(lián)系單元存放的內(nèi)容分別為:SL靜態(tài)鏈,動態(tài)鏈DL,RA返回地址。 3.語法分析方法語法分析的任務(wù)是識別由詞法分析給出的單詞符號序列在結(jié)構(gòu)上是否符合給定的文法規(guī)則.PL/0編譯程序的語法分析采用了自頂向下的遞歸子程序法.粗略地說:就是對應(yīng)每個非終結(jié)符語法單元,編一個獨立的處理過程(或子程序).語法分析研究從讀入第一個單詞開始由非終結(jié)符’程序即開始符出發(fā),沿語法描述圖箭頭所指出的方向進(jìn)行分析.當(dāng)遇到非終結(jié)符時,則調(diào)用相應(yīng)的處理過程,從語法描述圖看也就進(jìn)入了一個語法單元,再沿當(dāng)前所進(jìn)入的語法描述圖的箭頭方向進(jìn)行分析,當(dāng)遇到描述圖中是終結(jié)符時,則判斷當(dāng)前讀入的單詞是否與圖中的終結(jié)符相匹配,若匹配,則執(zhí)行相應(yīng)的語義程序(就是翻譯程序).再讀取下一個單詞繼續(xù)分析.遇到分支點時將當(dāng)前的單詞與分支點上的多個終結(jié)符逐個相比較,若都不匹配時可能是進(jìn)入下一非終結(jié)符語法單位或是出錯.如果一個PL/0語言程序的單詞序列在整修語法分析中,都能逐個得到匹配,直到程序結(jié)束’.’,這時就說所輸入的程序是正確的.對于正確的語法分析做相應(yīng)的語義翻譯,最終得出目標(biāo)程序.4.中間代碼表示PL/0編譯程序所產(chǎn)生的目標(biāo)代碼是一個假想棧式計算機(jī)的匯編語言,可稱為類pcode指令代碼,它不依賴任何實際計算機(jī),其指令集極為簡單,指令格式如下:fLalit0a將常數(shù)值取到棧頂,a為常數(shù)值Lodla將變量值取到棧頂,a為偏移量,l為層差Stola將棧頂內(nèi)容送入某變量單元中,a為偏移量,l為層差Cala調(diào)用過程,a為過程地址,l為層差I(lǐng)nt0a在運行棧中為被調(diào)用的過程開辟a個單元的數(shù)據(jù)區(qū)jmp0a無條件跳轉(zhuǎn)至a地址Jpc0a條件

溫馨提示

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

評論

0/150

提交評論