完整word版)PL0源代碼(C語言版)(總33頁_第1頁
完整word版)PL0源代碼(C語言版)(總33頁_第2頁
完整word版)PL0源代碼(C語言版)(總33頁_第3頁
完整word版)PL0源代碼(C語言版)(總33頁_第4頁
完整word版)PL0源代碼(C語言版)(總33頁_第5頁
已閱讀5頁,還剩28頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、 /*PL/0 編譯系統(tǒng)C版本頭文件 pl0.h*/# define norw 13 /a number of reserved word /*關(guān)鍵字個(gè)數(shù)*/ # define txmax 100 /length of identifier table /*名字表容量*/# define nmax 14 /max number of digits in numbers /*number的最大位數(shù)*/# define al 10 /length of identifier /*符號(hào)的最大長度*/# define amax 2047 /maximum address /*地址上界*/# defin

2、e levmax 3 /max depth of block nesting /*最大允許過程嵌套聲明層數(shù)0,lexmax*/# define cxmax 200 /size of code array /*最多的虛擬機(jī)代碼數(shù)*/*符號(hào)*/enum symbol nul, ident, number, plus, minus, times, slash, oddsym, eql, neq, /slash斜線 lss, leq, gtr, geq, lparen, /leq :less than or equal to; gtr: great than;lparen:left parenthes

3、isrparen, comma, semicolon,period, becomes,/comma逗號(hào) semicolon分號(hào) period句號(hào) becomes賦值號(hào) beginsym, endsym, ifsym, thensym, whilesym,writesym, readsym, dosym, callsym, constsym,varsym, procsym,;#define symnum 32/*-*/enum object /object為三種標(biāo)識(shí)符的類型 constant, variable, procedur,;/*-*/enum fct /fct類型分別標(biāo)識(shí)類PCODE的

4、各條指令lit, opr, lod, sto, cal, inte, jmp, jpc, /書本P23 ;#define fctnum 8/*-*/struct instruction /指令 enum fct f; /功能碼 int l; /層次差 int a; /P23;FILE * fas; /輸出名字表 FILE * fa; /輸出虛擬機(jī)代碼 FILE * fa1; /輸出源文件及其各行對(duì)應(yīng)的首地址 FILE * fa2; /輸出結(jié)果 bool tableswitch; /顯示名字表與否 bool listswitch; /顯示虛擬機(jī)代碼與否 char ch; /獲取字符的緩沖區(qū),ge

5、tch使用 enum symbol sym; /當(dāng)前符號(hào) char idal+1; /當(dāng)前ident,多出一個(gè)字節(jié)用于存放0 int num; /當(dāng)前number int cc,ll; /getch使用的計(jì)數(shù)器,cc表示當(dāng)前字符(ch)的位置 int cx; /虛擬機(jī)代碼指針,取值范圍0,cxmax-1char line81; /讀取行緩沖區(qū) char aal+1; /臨時(shí)符號(hào),多出的一個(gè)字節(jié)用于存放0 struct instruction codecxmax; /存放虛擬機(jī)代碼的數(shù)組 char wordnorwal; /保留字enum symbol wsymnorw; /保留字對(duì)應(yīng)的符號(hào)值

6、enum symbol ssym256; /單字符的符號(hào)值 char mnemonicfctnum5; /虛擬機(jī)代碼指令名稱 bool declbegsyssymnum; /表示聲明開始的符號(hào)集合 ,declaring begin symbol setbool statbegsyssymnum; /表示語句開始的符號(hào)集 , statementbool facbegsyssymnum; /表示因子開始的符號(hào)集合 ,factor/*-*/struct tablestruct char nameal; /*名字*/ enum object kind; /*類型:const,var,array or

7、procedure*/ int val; /*數(shù)值,僅const使用*/ int level; /*所處層,僅const不使用*/ int adr; /*地址,僅const不使用*/ int size; /*需要分配的數(shù)據(jù)區(qū)空間,僅procedure使用*/;struct tablestruct tabletxmax; /*名字表*/FILE * fin; /fin文本文件用于指向輸入的源程序文件FILE* fout; /fout文本文件用于指向輸出的文件char fnameal;int err; /*錯(cuò)誤計(jì)數(shù)器*/*當(dāng)函數(shù)中會(huì)發(fā)生fatal error時(shí),返回1告知調(diào)用它的函數(shù),最終退出程序

8、*/#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 expressiondo(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

9、(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=constdeclaration(a,b,c)return -1#define vardeclarationdo(a,b,c) if(-1=vardeclaration(a,b,c)return -1void error

10、(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*sr,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

11、 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*fsys,int*ptx,int lev);void listcode(int cx0);int vardeclaration(int* ptx,int lev, int* pdx);int constdeclarat

12、ion(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);/A.2 C 版 本/*編譯和運(yùn)行環(huán)境:*1Visual C+6.0,VisualC+.NET and Visual C+.NET 2003*WinNT, Win 200, WinXP and Win2003 *2 gcc version 3.3.2 20031022(Red Hat Linux 3.3.2-1

13、)*Redhat Fedora core 1*Intel 32 platform*使用方法:*運(yùn)行后輸入PL/0 源程序文件名*回答是否輸出虛擬機(jī)代碼*回答是否輸出名字表*fa.tmp 輸出虛擬機(jī)代碼*fa1.tmp 輸出源文件及其各行對(duì)應(yīng)的首地址*fa2.tmp 輸出結(jié)果 *fas.tmp 輸出名字表*/#include#includepl0.h#includestring.h/*解釋執(zhí)行時(shí)使用的棧*/#define stacksize 500int main()bool nxtlevsymnum;printf(Input pl/0 file ?);scanf(%s,fname); /*輸入

14、文件名*/fin=fopen(fname,r); /返回值:文件順利打開后,指向該流的文件指針就會(huì)被返回。如果文件打開失敗則返回NULL,并把錯(cuò)誤代碼存在errno 中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=y|fname0=Y);fa1=fopen(fa1.tmp,w);fp

15、rintf(fa1,Iput pl/0 file ?);fprintf(fa1,%sn, fname);init(); /*初始化*/err=0; /錯(cuò)誤計(jì)數(shù)器置0 cc=cx=ll=0;ch= ;if(-1!=getsym()fa=fopen(fa.tmp,w);fas=fopen(fas.tmp,w);addset(nxtlev,declbegsys,statbegsys,symnum);nxtlevperiod=true; if(-1=block(0,0,nxtlev)/*調(diào)用編譯程序*/fclose(fa);fclose(fa1);fclose(fas);fclose(fin);pri

16、ntf(n);return 0;fclose(fa);fclose(fa1);fclose(fas);if(sym!=period)error(9);if(err=0)fa2=fopen(fa2.tmp, w);interpret();fclose(fa2);elseprintf(Errors in pl/0 program);fclose(fin);elseprintf(Cant open file! n);printf(n);return 0;/*初始化*/void init()int i;for(i=0;i=255;i+) ssymi=nul; /ssym:?jiǎn)巫址姆?hào)值 ssym+=p

17、lus;ssym-=minus;ssym*=times;ssym/=slash;ssym(=lparen;ssym)=rparen;ssym=eql;ssym,=comma;ssym.=period;ssym#=neq;ssym;=semicolon;/*設(shè)置保留字名字,按照字母順序,便于折半查找*/strcpy(&(word00),begin);strcpy(&(word10),call);strcpy(&(word20),const);strcpy(&(word30),do);strcpy(&(word40),end);strcpy(&(word50),if);strcpy(&(word6

18、0),odd);strcpy(&(word70),procedure);strcpy(&(word80),read);strcpy(&(word90),then);strcpy(&(word100),var);strcpy(&(word110),while);strcpy(&(word120),write);/*設(shè)置保留字符號(hào)*/wsym0=beginsym;wsym1=callsym;wsym2=constsym;wsym3=dosym;wsym4=endsym;wsym5=ifsym;wsym6=oddsym;wsym7=procsym;wsym8=readsym;wsym9=thensy

19、m;wsym10=varsym;wsym11=whilesym;wsym12=writesym;/*設(shè)置指令名稱*/strcpy(&(mnemoniclit0),lit);strcpy(&(mnemonicopr0),opr);strcpy(&(mnemoniclod0),lod);strcpy(&(mnemonicsto0),sto);strcpy(&(mnemoniccal0),cal);strcpy(&(mnemonicinte0),int);strcpy(&(mnemonicjmp0),jmp);strcpy(&(mnemonicjpc0),jpc);/*設(shè)置符號(hào)集*/for(i=0;

20、isymnum;i+)declbegsysi=false;statbegsysi=false;facbegsysi=false;/*設(shè)置聲明開始符號(hào)集*/declbegsysconstsym=true;declbegsysvarsym=true;declbegsysprocsym=true;/*設(shè)置語句開始符號(hào)集*/statbegsysbeginsym=true;statbegsyscallsym=true;statbegsysifsym=true;statbegsyswhilesym=true;/*設(shè)置因子開始符號(hào)集*/facbegsysident=true;facbegsysnumber=

21、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;in;i+) sri=s1i|s2i; return 0;int subset(bool* sr,bool* s1,bool* s2,int n) int i; for(i=0;in;i+) sri=s1i&(!s2i); return 0; int mulset(bool* sr,bool* s1,bool* s2

22、,int n) int i; for(i=0;i=a&ch=z) k=0;doif(k=a&ch=0&ch=9);ak=0;strcpy(id,a);i=0;j=norw-1;dok=(i+j)/2;if(strcmp(id,wordk)=0)i=k+1;while(ij)sym=wsymk;elsesym=ident;elseif(ch=0&ch=0&chnmax)error(30);elseif(ch=:) /*檢測(cè)賦值符號(hào)*/getchdo;if(ch=)sym=becomes;getchdo;elsesym=nul; /*不能識(shí)別的符號(hào)*/elseif(ch=) /*檢測(cè)大于或大于等于

23、符號(hào)*/getchdo;if(ch=)sym=geq;getchdo;else sym=gtr;elsesym=ssymch;/* 當(dāng)符號(hào)不滿足上述條件時(shí),全部按照單字符號(hào)處理*/getchdo;/richardif(sym!=period)getchdo;/end richardreturn 0;/*生成虛擬機(jī)代碼*x:instruction.f;*y:instruction.l;*z:instruction.a;*/int gen(enum fct x,int y,int z)if(cx=cxmax)printf(Program too long); /*程序過長*/return -1;c

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

25、測(cè)不通過時(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 cx0; /*保留初始cx*/ bool nxtlevsymnum; /*在下級(jí)函數(shù)的參數(shù)中,符號(hào)集合均為值參,但由于使用數(shù)

26、組 實(shí)現(xiàn),傳遞進(jìn)來的是指針,為防止下級(jí)函數(shù)改變上級(jí)函數(shù)的 集合,開辟新的空間傳遞給下級(jí)函數(shù)*/ dx=3; tx0=tx; /*記錄本層名字的初始位置*/ tabletx.adr=cx; gendo(jmp,0,0); if(lev levmax) error(32); do if(sym=constsym) /*收到常量聲明符號(hào),開始處理常量聲明*/ getsymdo;do constdeclarationdo(&tx,lev,&dx); /*dx的值會(huì)被constdeclaration改變,使用 指針*/ while(sym=comma) getsymdo; constdeclaratio

27、ndo(&tx,lev,&dx); if(sym=semicolon) getsymdo;elseerror(5); /*漏掉了逗號(hào)或者分號(hào)*/while(sym=ident);if(sym=varsym)/*收到變量聲名符號(hào),開始處理變量聲名*/getsymdo;dovardeclarationdo(&tx,lev,&dx);while(sym=comma)getsymdo;vardeclarationdo(&tx,lev,&dx);if(sym=semicolon)getsymdo;elseerror(5);while(sym=ident);while(sym=procsym)/*收到過程

28、聲名符號(hào),開始處理過程聲名*/getsymdo;if(sym=ident)enter(procedur,&tx,lev,&dx);/*記錄過程名字*/getsymdo;elseerror(4);/*procedure后應(yīng)為標(biāo)識(shí)符*/if(sym=semicolon)getsymdo;elseerror(5);/*漏掉了分號(hào)*/memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevsemicolon=true;if(-1=block(lev+1,tx,nxtlev)return -1;/*遞歸調(diào)用*/ if(sym=semicolon) getsymdo;

29、memcpy(nxtlev,statbegsys,sizeof(bool)*symnum); nxtlevident=true; nxtlevprocsym=true; testdo(nxtlev,fsys,6); else error(5); /*漏掉了分號(hào)*/ memcpy(nxtlev,statbegsys,sizeof(bool)*symnum); nxtlevident=true; nxtlevperiod=true; testdo(nxtlev,declbegsys,7); while(inset(sym,declbegsys); /*直到?jīng)]有聲明符號(hào)*/ codetabletx0

30、.adr.a=cx; /*開始生成當(dāng)前過程代碼*/ tabletx0.adr=cx; /*當(dāng)前過程代碼地址*/ tabletx0.size=dx; /*聲明部分中每增加一條聲明都會(huì)給dx增加1,聲明部分已經(jīng)結(jié)束,dx就是當(dāng)前過程數(shù)據(jù)的size*/ cx0=cx; gendo(inte,0,dx); /*生成分配內(nèi)存代碼*/ if(tableswitch) /*輸出名字表*/ printf(TABLE:n); if(tx0+1tx) printf(NULLn); for(i=tx0+1;iamax)error(31);num=0;table(*ptx).val=num;break;case va

31、riable: /*變量名字*/table(*ptx).level=lev;table(*ptx).adr=(*pdx);(*pdx)+;break; /*過程名字*/case procedur:table(*ptx).level=lev;break;/* *查找名字的位置 *找到則返回在名字表中的位置,否則返回0 * *idt: 要查找的名字 *tx::當(dāng)前名字表尾指針 */int position(char * idt,int tx)int i;strcpy(,idt);i=tx;while(strcmp(,idt)!=0)i-;return i;/* *常量聲明處理 */int constdeclaration(int * ptx,int lev,int * pdx)if(sym=ident)getsymdo;if(sym=eql |sym=becomes)if(sym=becomes)error(1); /*把=

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論