編譯器的代碼生成._第1頁(yè)
編譯器的代碼生成._第2頁(yè)
編譯器的代碼生成._第3頁(yè)
編譯器的代碼生成._第4頁(yè)
編譯器的代碼生成._第5頁(yè)
已閱讀5頁(yè),還剩47頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、佛山科學(xué)技術(shù)學(xué)院 實(shí) 驗(yàn) 報(bào) 告課程名稱 編譯原理 實(shí)驗(yàn)項(xiàng)目 編譯器的代碼生成 專業(yè)班級(jí) 計(jì)算機(jī)1班 姓 名 學(xué) 號(hào) 指導(dǎo)教師 黃營(yíng) 成 績(jī) 日 期 2014/6/7 一、實(shí)驗(yàn)?zāi)康模?掌握PL語(yǔ)言編譯器的中間代碼生成的程序分析與實(shí)現(xiàn)方法,并能對(duì)錯(cuò)誤進(jìn)行分析與處理二、實(shí)驗(yàn)內(nèi)容; 為了使我們的編譯程序保持適當(dāng)簡(jiǎn)單的水平,不致陷入與本課程無(wú)關(guān)的實(shí)際機(jī)器的特有性質(zhì)的考慮中去,我們假想有臺(tái)適合PL程序運(yùn)行的計(jì)算機(jī),我們稱之為PL處理機(jī)。PL處理機(jī)順序解釋生成的目標(biāo)代碼。三、實(shí)驗(yàn)原理;PL處理機(jī)的指令集根據(jù)PL語(yǔ)言的要求而設(shè)計(jì),它包括以下的指令:(1)LIT /* 將常數(shù)置于棧頂 */(2)LOD /*

2、將變量值置于棧頂 */(3)STO /* 將棧頂?shù)闹蒂x與某變量 */(4)CAL /* 用于過(guò)程調(diào)用的指令 */(5)INT /* 在數(shù)據(jù)棧中分配存貯空間 */(6)JMP, JPC /* 用于if, while語(yǔ)句的條件或無(wú)條件控制轉(zhuǎn)移指令 */(7)OPR /* 一組算術(shù)或邏輯運(yùn)算指令 */上述指令的格式由三部分組成:FLA其中,f, l, a的含義見(jiàn)下表:FLaINT常 量LIT常 量LOD層次差數(shù)據(jù)地址STO層次差數(shù)據(jù)地址CAL層次差程序地址JMP程序地址JPC程序地址OPR運(yùn)算類別表1 PL 處理機(jī)指令四、實(shí)驗(yàn)步驟; PL的編譯程序?yàn)槊恳粭lPL源程序的可執(zhí)行語(yǔ)句生成后綴式目標(biāo)代碼。另

3、一方面,發(fā)現(xiàn)錯(cuò)誤,并給出合適的診斷信息且繼續(xù)編譯下去從而發(fā)現(xiàn)更多的錯(cuò)誤,對(duì)于編譯程序而言是完全必要的。結(jié)合關(guān)鍵字規(guī)則、鎮(zhèn)定規(guī)則,采用策略:先用一些明顯的關(guān)鍵符號(hào)給它賦初值,然后隨著分析子目標(biāo)的層次深入,逐步補(bǔ)充別的合法符號(hào)。5、 程序代碼PL0.h:/*PL/0 編譯系統(tǒng)C版本頭文件 pl0.h*/*typedef enumfalse,true,bool;*/# define norw 20 /*關(guān)鍵字個(gè)數(shù)*/# define txmax 100 /*名字表容量*/# define nmax 14 /*number的最大位數(shù)*/# define al 10 /*符號(hào)的最大長(zhǎng)度*/# defin

4、e amax 2047 /*地址上界*/# define levmax 3 /*最大允許過(guò)程嵌套聲明層數(shù)0,lexmax*/# define cxmax 200 /*最多的虛擬機(jī)代碼數(shù)*/*符號(hào)*/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,readsym

5、, dosym, callsym, constsym,varsym, procsym, elsesym, forsym, tosym,downtosym,returnsym,pluseql, minuseql,plusplus,minusminus,repeatsym,dowhilesym,;#define symnum 43/*-*/enum object constant, variable, procedur,;/*-*/enum fctlit, opr, lod, sto, cal, inte, jmp, jpc,;#define fctnum 8/*-*/struct instruc

6、tion enum fct f; int l; int a;FILE * fas;FILE * fa;FILE * fa1;FILE * fa2;bool tableswitch;bool listswitch;char ch;enum symbol sym;char idal+1;int num;int cc,ll;int cx;char line81;char aal+1;struct instruction codecxmax;char wordnorwal;enum symbol wsymnorw;enum symbol ssym256;char mnemonicfctnum5;boo

7、l declbegsyssymnum;bool statbegsyssymnum;bool facbegsyssymnum;/*-*/struct tablestruct char nameal; /*名字*/ enum object kind; /*類型:const,var,array or procedure*/ int val; /*數(shù)值,僅const使用*/ int level; /*所處層,僅const不使用*/ int adr; /*地址,僅const不使用*/ int size; /*需要分配的數(shù)據(jù)區(qū)空間,僅procedure使用*/;struct tablestruct tab

8、letxmax; /*名字表*/FILE * fin;FILE* fout;char fnameal;int err; /*錯(cuò)誤計(jì)數(shù)器*/*當(dāng)函數(shù)中會(huì)發(fā)生fatal error時(shí),返回1告知調(diào)用它的函數(shù),最終退出程序*/#define getsymdo if(-1=getsym()return -1#define getchdo if(-1=getch()return -1#define testdo(a,b,c) if(-1=test(a,b,c)return -1#define gendo(a,b,c) if(-1=gen(a,b,c)return -1#define expression

9、do(a,b,c) if(-1=expression(a,b,c)return -1#define factordo(a,b,c) if(-1=factor(a,b,c)return -1#define termdo(a,b,c) if(-1=term(a,b,c)return -1#define conditiondo(a,b,c) if(-1=condition(a,b,c)return -1#define statementdo(a,b,c) if(-1=statement(a,b,c)return -1#define constdeclarationdo(a,b,c) if(-1=co

10、nstdeclaration(a,b,c)return -1#define vardeclarationdo(a,b,c) if(-1=vardeclaration(a,b,c)return -1void error(int n);int getsym();int getch();void init();int gen(enum fct x,int y,int z);int test(bool*s1,bool*s2,int n);int inset(int e,bool*s);int addset(bool*sr,bool*s1,bool*s2,int n);int subset(bool*s

11、r,bool*s1,bool*s2,int n);int mulset(bool*sr,bool*s1,bool*s2,int n);int block(int lev,int tx,bool* fsys);void interpret();int factor(bool* fsys,int* ptx,int lev);int term(bool*fsys,int*ptx,int lev);int condition(bool*fsys,int*ptx,int lev);int expression(bool*fsys,int*ptx,int lev);int statement(bool*f

12、sys,int*ptx,int lev);void listcode(int cx0);int vardeclaration(int* ptx,int lev, int* pdx);int constdeclaration(int* ptx,int lev, int* pdx);int position(char* idt,int tx);void enter(enum object k,int* ptx,int lev,int* pdx);int base(int l,int* s,int b);PL0.cpp:/*使用方法:*運(yùn)行后輸入PL/0 源程序文件名*回答是否輸出虛擬機(jī)代碼*回答是

13、否輸出名字表*fa.tmp 輸出虛擬機(jī)代碼*fa1.tmp 輸出源文件及其各行對(duì)應(yīng)的首地址*fa2.tmp 輸出結(jié)果 *fas.tmp 輸出名字表*/#include<stdio.h>#include"pl0.h"#include"string.h"#include <cstdio>/*解釋執(zhí)行時(shí)使用的棧*/#define stacksize 500int main()int c;bool nxtlevsymnum;printf("Input pl/0 file ?");scanf("%s"

14、,fname); /*輸入文件名*/fin=fopen(fname,"r");if(fin)printf("List object code ?(Y/N)"); /*是否輸出虛擬機(jī)代碼*/scanf("%s",fname);listswitch=(fname0='y'|fname0='Y');printf("List symbol table ? (Y/N)"); /*是否輸出名字表*/scanf("%s",fname);tableswitch=(fname0=&

15、#39;y'|fname0='Y');fa1=fopen("fa1.txt","w");fprintf(fa1,"Iput pl/0 file ?");fprintf(fa1,"%sn", fname);init(); /*初始化*/err=0;cc=cx=ll=0;ch=' ' if(-1!=getsym() fa=fopen("fa.txt","w");fas=fopen("fas.txt","w&qu

16、ot;);addset(nxtlev,declbegsys,statbegsys,symnum);nxtlevperiod=true;if(-1=block(0,0,nxtlev) /*調(diào)用編譯程序*/ fclose(fa);fclose(fa1);fclose(fas);fclose(fin);printf("n");return 0;fclose(fa);fclose(fa1);fclose(fas);if(sym!=period)error(9);fclose(fin);elseprintf("Can't open file! n");pr

17、intf("n");while ( (c = getchar() != 'n' && c != EOF ) ; / 清空輸入流clearerr(stdin); / 清除流的錯(cuò)誤標(biāo)記getchar(); / 等待用戶輸入回車(chē)return 0;/*初始化*/void init()int i;for(i=0;i<=255;i+)ssymi=nul;ssym'+'=plus;ssym'-'=minus;ssym'*'=times;ssym'/'=slash;ssym'(&#

18、39;=lparen;ssym')'=rparen;ssym'='=eql;ssym','=comma;ssym'.'=period;/ssym'#'=neq; / 注釋掉不等號(hào)ssym''=semicolon;/*設(shè)置保留字名字,按照字母順序,便于折半查找*/strcpy(&(word00),"begin");strcpy(&(word10),"call");strcpy(&(word20),"const");st

19、rcpy(&(word30),"do");strcpy(&(word40),"dowhile");/增加dowhile strcpy(&(word50),"downto"); /*增加downto*/ strcpy(&(word60),"else"); /*增加else*/ strcpy(&(word70),"end"); strcpy(&(word80),"for"); /*增加for*/ strcpy(&(word9

20、0),"if");strcpy(&(word100),"odd");strcpy(&(word110),"procedure");strcpy(&(word120),"read");strcpy(&(word130),"repeat");/增加repeat strcpy(&(word140),"return"); /*增加return*/strcpy(&(word150),"then"); strcpy(&a

21、mp;(word160),"to"); /*增加to*/ strcpy(&(word170),"var");strcpy(&(word180),"while");strcpy(&(word190),"write"); /*設(shè)置保留字符號(hào)*/wsym0=beginsym;wsym1=callsym;wsym2=constsym; wsym3=dosym;wsym4=dowhilesym;/*增加dowhilesym*/wsym5=downtosym; /*增加downtosym*/wsym6=

22、elsesym; /*增加elsesym*/wsym7=endsym;wsym8=forsym; /*增加forsym*/wsym9=ifsym;wsym10=oddsym;wsym11=procsym;wsym12=readsym;wsym13=repeatsym;/增加repeatsymwsym14=returnsym; /*增加returnsym*/ wsym15=thensym;wsym16=tosym; /*增加tosym*/wsym17=varsym;wsym18=whilesym;wsym19=writesym;/*設(shè)置指令名稱*/strcpy(&(mnemoniclit

23、0),"lit");strcpy(&(mnemonicopr0),"opr");strcpy(&(mnemoniclod0),"lod");strcpy(&(mnemonicsto0),"sto");strcpy(&(mnemoniccal0),"cal");strcpy(&(mnemonicinte0),"int");strcpy(&(mnemonicjmp0),"jmp");strcpy(&(mn

24、emonicjpc0),"jpc");/*設(shè)置符號(hào)集*/for(i=0;i<symnum;i+)declbegsysi=false;statbegsysi=false;facbegsysi=false;/*設(shè)置聲明開(kāi)始符號(hào)集*/declbegsysconstsym=true;declbegsysvarsym=true;declbegsysprocsym=true;/*設(shè)置語(yǔ)句開(kāi)始符號(hào)集*/statbegsysbeginsym=true;statbegsyscallsym=true;statbegsysifsym=true;statbegsyswhilesym=true

25、;statbegsysrepeatsym=true;/增加repeat為語(yǔ)句開(kāi)始符號(hào)/*設(shè)置因子開(kāi)始符號(hào)集*/facbegsysident=true;facbegsysnumber=true;facbegsyslparen=true; /* *用數(shù)組實(shí)現(xiàn)集合的集合運(yùn)算 */int inset(int e,bool* s) return se;int addset(bool* sr,bool* s1,bool* s2,int n) int i; for(i=0;i<n;i+) sri=s1i|s2i; return 0;int subset(bool* sr,bool* s1,bool*

26、s2,int n) int i; for(i=0;i<n;i+) sri=s1i&&(!s2i); return 0; int mulset(bool* sr,bool* s1,bool* s2,int n) int i; for(i=0;i<n;i+) sri=s1i&&s2i; return 0;/* *出錯(cuò)處理,打印出錯(cuò)位置和錯(cuò)誤編碼 */void error(int n) char space81;memset(space,32,81); printf("-%cn",ch);spacecc-1=0;/出錯(cuò)時(shí)當(dāng)前符號(hào)已經(jīng)讀完

27、,所以cc-1printf("*%s!%dn",space,n);err+;/* * 漏掉空格,讀取一個(gè)字符 * * 每次讀一行,存入line緩沖區(qū),line被getsym取空后再讀一行 * * 被函數(shù)getsym調(diào)用 */int getch()if(cc=ll) if(feof(fin)printf("program incomplete");return -1;ll=0;cc=0;printf("%d ",cx );fprintf(fa1,"%d ",cx);ch=' 'while(ch!=10

28、)/fscanf(fin,"%c",&ch) if(EOF=fscanf(fin,"%c",&ch)linell=0;break;printf("%c",ch);fprintf(fa1,"%c",ch);linell=ch;ll+;printf("n");fprintf(fa1,"n");ch=linecc;cc+;return 0; /*詞法分析,獲取一個(gè)符號(hào) */int getsym()int i,j,k;while( ch=' '|ch=

29、10|ch=9)getchdo;if(ch>='a'&&ch<='z') k=0;doif(k<al) ak=ch;k+;getchdo; while(ch>='a'&&ch<='z'|ch>='0'&&ch<='9');ak=0;strcpy(id,a);i=0;j=norw-1;dok=(i+j)/2;if(strcmp(id,wordk)<=0)j=k-1;if(strcmp(id,wordk)&g

30、t;=0)i=k+1;while(i<=j);if(i-1>j)sym=wsymk;elsesym=ident;elseif(ch>='0'&&ch<='9')k=0;num=0;sym=number;donum=10*num+ch-'0'k+;getchdo;while(ch>='0'&&ch<='9'); /*獲取數(shù)字的值*/k-;if(k>nmax)error(30);elseif(ch=':') /*檢測(cè)賦值符號(hào)*/g

31、etchdo;if(ch='=')sym=becomes;getchdo;elsesym=nul; /*不能識(shí)別的符號(hào)*/elseif(ch='<') /*檢測(cè)小于或小于等于符號(hào)*/getchdo;if(ch='=')sym=leq;getchdo;elseif(ch='>') /*將“#”變成"<>" */sym=neq;getchdo;else sym=lss;elseif(ch='>') /*檢測(cè)大于或大于等于符號(hào)*/getchdo;if(ch='=&

32、#39;)sym=geq;getchdo;else sym=gtr; if(ch='+') /*增加檢測(cè)"+="或"+" */ getchdo; if(ch='=') sym=pluseql; getchdo; else if(ch='+') sym=plusplus; getchdo; else sym=plus; else if(ch='-') /*增加檢測(cè)"-="或"-" */ getchdo; if(ch='=') sym=mi

33、nuseql; getchdo; else if(ch='-') sym=minusminus; getchdo; else sym=minus; else sym=ssymch;/* 當(dāng)符號(hào)不滿足上述條件時(shí),全部按照單字符號(hào)處理*/getchdo;/richardif(sym!=period)getchdo;/end richard return 0;/*生成虛擬機(jī)代碼*x:instruction.f;*y:instruction.l;*z:instruction.a;*/int gen(enum fct x,int y,int z)if(cx>=cxmax)print

34、f("Program too long"); /*程序過(guò)長(zhǎng)*/return -1;codecx.f=x;codecx.l=y;codecx.a=z;cx+;return 0;/*測(cè)試當(dāng)前符號(hào)是否合法*在某一部分(如一條語(yǔ)句,一個(gè)表達(dá)式)將要結(jié)束時(shí)時(shí)我們希望下一個(gè)符號(hào)屬于某集合*(該部分的后跟符號(hào)) test 負(fù)責(zé)這項(xiàng)檢測(cè),并且負(fù)責(zé)當(dāng)檢測(cè)不通過(guò)時(shí)的補(bǔ)救措施*程序在需要檢測(cè)時(shí)指定當(dāng)前需要的符號(hào)集合和補(bǔ)救用的集合(如之前未完成部分的后跟*符號(hào)),以及不通過(guò)時(shí)的錯(cuò)誤號(hào)*S1:我們需要的符號(hào)*s2:如果不是我們需要的,則需要一個(gè)補(bǔ)救用的集合*n:錯(cuò)誤號(hào)*/int test(bool*

35、 s1,bool* s2,int n) if(! inset(sym,s1) error(n);/*當(dāng)檢測(cè)不通過(guò)時(shí),不停獲取符號(hào),直到它屬于需要的集合或補(bǔ)救的集合*/while(! inset(sym,s1)&&(! inset(sym,s2)getsymdo; return 0;/* *編譯程序主體 * *lev:當(dāng)前分程序所在層 *tx:名字表當(dāng)前尾指針 *fsys:當(dāng)前模塊后跟符號(hào)集合 */int block(int lev,int tx,bool* fsys) int i; int dx; /*名字分配到的相對(duì)地址*/ int tx0; /*保留初始tx*/ int c

36、x0; /*保留初始cx*/ bool nxtlevsymnum; /*在下級(jí)函數(shù)的參數(shù)中,符號(hào)集合均為值參,但由于使用數(shù)組 實(shí)現(xiàn),傳遞進(jìn)來(lái)的是指針,為防止下級(jí)函數(shù)改變上級(jí)函數(shù)的 集合,開(kāi)辟新的空間傳遞給下級(jí)函數(shù)*/ dx=3; tx0=tx; /*記錄本層名字的初始位置*/ tabletx.adr=cx; gendo(jmp,0,0); if(lev > levmax) error(32); do/各種聲明語(yǔ)句處理 if(sym=constsym) /*收到常量聲明符號(hào),開(kāi)始處理常量聲明*/ getsymdo;do constdeclarationdo(&tx,lev,&

37、;dx); /*dx的值會(huì)被constdeclaration改變,使用 指針*/ while(sym=comma) getsymdo; constdeclarationdo(&tx,lev,&dx); if(sym=semicolon) getsymdo;elseerror(5); /*漏掉了逗號(hào)或者分號(hào)*/while(sym=ident);/end constif(sym=varsym)/*收到變量聲名符號(hào),開(kāi)始處理變量聲名*/getsymdo;dovardeclarationdo(&tx,lev,&dx);while(sym=comma)getsymdo;v

38、ardeclarationdo(&tx,lev,&dx);if(sym=semicolon)getsymdo;elseerror(5);while(sym=ident);/end varwhile(sym=procsym)/*收到過(guò)程聲名符號(hào),開(kāi)始處理過(guò)程聲名*/getsymdo;if(sym=ident)enter(procedur,&tx,lev,&dx);/*記錄過(guò)程名字*/getsymdo;elseerror(4);/*procedure后應(yīng)為標(biāo)識(shí)符*/if(sym=semicolon)getsymdo;elseerror(5);/*漏掉了分號(hào)*/mem

39、cpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevsemicolon=true;if(-1=block(lev+1,tx,nxtlev)return -1;/*遞歸調(diào)用*/ if(sym=semicolon) getsymdo; memcpy(nxtlev,statbegsys,sizeof(bool)*symnum); nxtlevident=true; nxtlevprocsym=true; testdo(nxtlev,fsys,6); else error(5); /*漏掉了分號(hào)*/ /end procsym while(inset(sym,declb

40、egsys); /*直到?jīng)]有聲明符號(hào)*/ memcpy(nxtlev,statbegsys,sizeof(bool)*symnum); nxtlevident=true; nxtlevperiod=true; testdo(nxtlev,declbegsys,7); codetabletx0.adr.a=cx; /*開(kāi)始生成當(dāng)前過(guò)程代碼*/ tabletx0.adr=cx; /*當(dāng)前過(guò)程代碼地址*/ tabletx0.size=dx; /*聲明部分中每增加一條聲明都會(huì)給dx增加1,聲明部分已經(jīng)結(jié)束,dx就是當(dāng)前過(guò)程數(shù)據(jù)的size*/ cx0=cx; gendo(inte,0,dx); /*生成

41、分配內(nèi)存代碼*/ if(tableswitch) /*輸出名字表*/ printf("TABLE:n"); if(tx0+1>tx) printf("NULLn"); for(i=tx0+1;i<=tx;i+) switch(tablei.kind) case constant:printf("%d const %s ",i,);printf("val=%dn",tablei.val);fprintf(fas,"%d const %s ",i,tablei.na

42、me);fprintf(fas,"val=%dn",tablei.val); break; case variable: printf("%d var %s ",i,); printf("lev=%d addr=%dn",tablei.level,tablei.adr); fprintf(fas,"%d var %s ",i,); fprintf(fas,"lev=%d addr=%dn",tablei.level,tablei.adr); break; case procedur: printf("%d proc %s ",i,); printf("lev=%d addr=%d size=%dn",tablei.level,tablei

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論