




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、/A.2 C 版 本/*編譯和運行環(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)*Redhat Fedora core 1*Intel 32 platform*使用方法:*運行后輸入PL/0 源程序文件名*回答是否輸出虛擬機代碼*回答是否輸出名字表*fa.tmp 輸出虛擬機代碼*fa1.tmp 輸出源文件及其各行對應(yīng)的首地址*fa2.tmp 輸出結(jié)果 *fas.t
2、mp 輸出名字表*/#include<stdio.h>/*PL/0 編譯系統(tǒng)C版本頭文件 pl0.h*/#include"string.h"/*解釋執(zhí)行時使用的棧*/#define stacksize 500/typedef enum / false,/ true/bool;# define norw 13 /*關(guān)鍵字個數(shù)*/# define txmax 100 /*名字表容量*/# define nmax 14 /*number的最大位數(shù)*/# define al 10 /*符號的最大長度*/# define amax 2047 /*地址上界*/# defin
3、e levmax 3 /*最大允許過程嵌套聲明層數(shù)0,lexmax*/# define cxmax 200 /*最多的虛擬機代碼數(shù)*/*符號*/enum symbol nul, 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, dosym, callsym, consts
4、ym,varsym, procsym,;#define symnum 32/*-名字表中的類型-*/enum object constant, variable, procedur,;/*-虛擬機代碼-*/enum fctlit, opr, lod, sto, cal, inte, jmp, jpc,;#define fctnum 8/*-虛擬機代碼結(jié)構(gòu)-*/struct instruction enum fct f; /*虛擬機代碼指令*/ int l; /*引用層與聲明層的層次差*/ int a; /*根據(jù)f的不同而不同*/;FILE * fas; /*輸出名字表*/FILE * fa;
5、/*輸出虛擬機代碼*/FILE * fa1; /*輸出源文件及其各行對應(yīng)的首地址*/FILE * fa2; /*輸出結(jié)果*/bool listswitch; /*顯示虛擬機代碼與否*/bool tableswitch; /*顯示名字表與否*/char ch; /*獲得字符的緩沖區(qū),getch使用*/ enum symbol sym; /*當(dāng)前的符號*/char idal+1; /*ident,多出的一個字節(jié)用于存放0*/int num; /*當(dāng)前number*/int cc,ll; /*getch使用的計數(shù)器,cc表示當(dāng)前字符(ch)的位置*/int cx; /*虛擬機代碼指針,取值范圍0,c
6、xmax-1*/char line81; /*讀取行緩沖區(qū)*/char aal+1; /*臨時符號,多出的一個字節(jié)用于存放0*/struct instruction codecxmax; /*存放虛擬機代碼的數(shù)組*/char wordnorwal; /*保留字*/ enum symbol wsymnorw; /*保留字對應(yīng)的符號值*/enum symbol ssym256; /*單字符的符號值*/char mnemonicfctnum5; /*虛擬機代碼指令名稱*/bool declbegsyssymnum; /*表示聲明開始的符號集合*/bool statbegsyssymnum; /*表示
7、語句開始的符號集合*/bool facbegsyssymnum; /*表示因子開始的符號集合*/*-名字表結(jié)構(gòu)-*/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 tabletxmax;
8、/*名字表*/FILE * fin;FILE* fout;char fnameal;int err; /*錯誤計數(shù)器*/*當(dāng)函數(shù)中會發(fā)生fatal error時,返回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 expressiondo(a,b,c)
9、 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=constdeclar
10、ation(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*sr,bool*s1
11、,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*fsys,int*p
12、tx,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);int main() bool nxtlevsymnum; printf("Input pl/0 fil
13、e ?"); scanf("%s",&fname); /*輸入文件名*/ fin=fopen(fname,"r"); if(fin) printf("List object code ?(Y/N)"); /*是否輸出虛擬機代碼*/ scanf("%s",fname); listswitch=(fname0='y'|fname0='Y'); printf("List symbol table ? (Y/N)"); /*是否輸出名字表*/ scanf
14、("%s",fname); tableswitch=(fname0='y'|fname0='Y'); fa1=fopen("fal.tmp","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.tmp",&qu
15、ot;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);printf("n");return 0;fclose(fa);fclose(fa1);fclose(fas);if(sym!=period)error(9);if(err=0
16、)fa2=fopen("fa2.tmp", "w");interpret();fclose(fa2);elseprintf("Errors in pl/0 program");fclose(fin); else printf("Can't open file! n"); printf("n"); return 0; /* *初始化 */ void init() int i;ssym'/'=slash;ssym'('=lparen;ssym')
17、9;=rparen;ssym'='=eql;ssym','=comma;ssym'.'=period;ssym'#'=neq;ssym''=semicolon;/*設(shè)置保留字名字,按照字母順序,便于折半查找*/strcpy(&(word00),"begin");strcpy(&(word10),"call");strcpy(&(word20),"const");strcpy(&(word30),"do")
18、;strcpy(&(word40),"end");strcpy(&(word50),"if");strcpy(&(word60),"odd");strcpy(&(word70),"procedure");strcpy(&(word80),"read");strcpy(&(word90),"then");strcpy(&(word100),"var");strcpy(&(word110),&qu
19、ot;while");strcpy(&(word120),"write");/*設(shè)置保留字符號*/wsym0=beginsym;wsym1=callsym;wsym2=constsym;wsym3=dosym;wsym4=endsym;wsym5=ifsym;wsym6=oddsym;wsym7=procsym;wsym8=readsym;wsym9=thensym;wsym10=varsym;wsym11=whilesym;wsym12=writesym;/*設(shè)置指令名稱*/strcpy(&(mnemoniclit0),"lit&quo
20、t;);strcpy(&(mnemonicopr0),"opr");strcpy(&(mnemoniclod0),"lod");strcpy(&(mnemonicsto0),"sto");strcpy(&(mnemoniccal0),"cal");strcpy(&(mnemonicinte0),"inte");strcpy(&(mnemonicjmp0),"jmp");strcpy(&(mnemonicjpc0),&qu
21、ot;jpc");/*設(shè)置符號集*/for(i=0;i<symnum;i+) declbegsysi=false; statbegsysi=false; facbegsysi=false; /*設(shè)置聲明開始符號集*/ declbegsysconstsym=true; declbegsysvarsym=true; declbegsysprocsym=true; /*設(shè)置語句開始符號集*/ statbegsysbeginsym=true; statbegsyscallsym=true; statbegsysifsym=true; statbegsyswhilesym=true; /
22、*設(shè)置因子開始符號集*/ facbegsysident=true; facbegsysnumber=true; facbegsyslparen=true; /* *用數(shù)組實現(xià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* s2,int n) int i; for(i=0;i<n;i+) sri=
23、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;/* *出錯處理,打印出錯位置和錯誤編碼 */void error(int n) char space81;memset(space,32,81);spacecc-1=0;/出錯時當(dāng)前符號已經(jīng)讀完,所以cc-1printf("*%s!%dn",space,n);err+;/* * 漏掉空格,讀取一個字符 * *
24、每次讀一行,存入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) /fscanf(fin,"%c",&ch) if(EOF=fscanf(fin,"
25、%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; /*詞法分析,獲取一個符號 */int getsym()int i,j,k;while( ch=' '|ch=10|ch=9) getchdo ;if(ch>='a'&&c
26、h<='z') k=0;do if(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;do k=(i+j)/2;if(strcmp(id,wordk)<=0)j=k-1;if(strcmp(id,wordk)>=0)i=k+1;while(i<=j);if(i-1>j)sym=wsymk
27、;elsesym=ident;elseif(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=become
28、s; getchdo; else sym=nul; /*不能識別的符號*/ else if(ch='<') /*檢測小于或小于等于符號*/ getchdo; if(ch='=') sym=leq; getchdo; else sym=lss; else if(ch='>') /*檢測大于或大于等于符號*/ getchdo; if(ch='=') sym=geq; getchdo; else sym=gtr; else sym=ssymch;/* 當(dāng)符號不滿足上述條件時,全部按照單字符號處理*/ /getchdo; /r
29、ichard if(sym!=period) getchdo; /end richard return 0;/*生成虛擬機代碼*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; codecx.f=x;codecx.l=y;codecx.a=z;cx+;return 0;/*測試當(dāng)前符號是否合法*在某一部分(如一條語句,一個表達(dá)式)
30、將要結(jié)束時時我們希望下一個符號屬于某集合*(該部分的后跟符號) test 負(fù)責(zé)這項檢測,并且負(fù)責(zé)當(dāng)檢測不通過時的補救措施*程序在需要檢測時指定當(dāng)前需要的符號集合和補救用的集合(如之前未完成部分的后跟*符號),以及不通過時的錯誤號*S1:我們需要的符號*s2:如果不是我們需要的,則需要一個補救用的集合*n:錯誤號*/int test(bool* s1,bool* s2,int n) if(! inset(sym,s1) error(n); /*當(dāng)檢測不通過時,不停獲取符號,直到它屬于需要的集合或補救的集合*/ while(! inset(sym,s1)&&(! inset(sym
31、,s2) getsymdo; return 0;/* *編譯程序主體 * *lev:當(dāng)前分程序所在層 *tx:名字表當(dāng)前尾指針 *fsys:當(dāng)前模塊后跟符號集合 */int block(int lev,int tx,bool* fsys) int i; int dx; /*名字分配到的相對地址*/ int tx0; /*保留初始tx*/ int cx0; /*保留初始cx*/ bool nxtlevsymnum; /*在下級函數(shù)的參數(shù)中,符號集合均為值參,但由于使用數(shù)組 實現(xiàn),傳遞進來的是指針,為防止下級函數(shù)改變上級函數(shù)的 集合,開辟新的空間傳遞給下級函數(shù)*/ dx=3; tx0=tx; /*
32、記錄本層名字的初始位置*/ tabletx.adr=cx; gendo(jmp,0,0); if(lev > levmax) error(32); do if(sym=constsym) /*收到常量聲明符號,開始處理常量聲明*/ getsymdo; do constdeclarationdo(&tx,lev,&dx); /*dx的值會被constdeclaration改變,使用 指針*/ while(sym=comma) getsymdo; constdeclarationdo(&tx,lev,&dx); if(sym=semicolon) getsym
33、do; elseerror(5); /*漏掉了逗號或者分號*/while(sym=ident);if(sym=varsym)/*收到變量聲名符號,開始處理變量聲名*/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)/*收到過程聲名符號,開始處理過程聲名*/getsymdo;i
34、f(sym=ident)enter(procedur,&tx,lev,&dx);/*記錄過程名字*/getsymdo;elseerror(4);/*procedure后應(yīng)為標(biāo)識符*/if(sym=semicolon)getsymdo;elseerror(5);/*漏掉了分號*/memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevsemicolon=true;if(-1=block(lev+1,tx,nxtlev)return -1;/*遞歸調(diào)用*/ if(sym=semicolon) getsymdo; memcpy(nxtlev,sta
35、tbegsys,sizeof(bool)*symnum); nxtlevident=true; nxtlevprocsym=true; testdo(nxtlev,fsys,6); else error(5); /*漏掉了分號*/ memcpy(nxtlev,statbegsys,sizeof(bool)*symnum); nxtlevident=true; nxtlevperiod=true; testdo(nxtlev,declbegsys,7); while(inset(sym,declbegsys); /*直到?jīng)]有聲明符號*/ codetabletx0.adr.a=cx; /*開始生成
36、當(dāng)前過程代碼*/ tabletx0.adr=cx; /*當(dāng)前過程代碼地址*/ tabletx0.size=dx; /*聲明部分中每增加一條聲明都會給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+1>tx) printf("NULLn"); for(i=tx0+1;i<=tx;i+) switch(tablei.kind) case consta
37、nt: printf("%d const %s",i,); printf("val=%dn",tablei.val); fprintf(fas,"%d const %s",i,); fprintf(fas,"val=%dn",tablei.val); break; case variable: printf("%d var%s",i,); printf("lev=%d addr=%dn",tablei.leve
38、l,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.adr,tablei.size); fprintf(fas,"%d
39、proc%s",i,); fprintf(fas,"lev=%d adr=%d size=%d n",tablei.level,tablei.adr,tablei.size); break; printf("n"); /*語句后跟符號為分號或end*/ memcpy(nxtlev,fsys,sizeof(bool)*symnum);/*每個后跟符號集和都包含上層后跟符號集和,以便補救*/ nxtlevsemicolon=true; nxtlevendsym=true; statementdo(nxtlev,&tx,
40、lev); gendo(opr,0,0); /*每個過程出口都要使用的釋放數(shù)據(jù)段命令*/ memset(nxtlev,0,sizeof(bool)*symnum); /*分程序沒有補救集合*/ test(fsys,nxtlev,8); /*檢測后跟符號正確性*/ listcode(cx0); /*輸出代碼*/ return 0;/*在名字表中加入一項*k:名字種類const,var or procedure*ptx:名字表尾指針的指針,為了可以改變名字表尾指針的數(shù)值*lev:名字所在的層次,以后所有的lev都是這樣*pdx:為當(dāng)前應(yīng)分配的變量的相對地址,分配后要增加1*/void enter
41、(enum object k,int *ptx,int lev, int *pdx) (*ptx)+; strcpy(table(*ptx).name,id); /*全局變量id中已存有當(dāng)前名字的名字*/ table(*ptx).kind=k; switch(k) case constant: /*常量名字*/ if (num>amax) error(31); num=0; table(*ptx).val=num; break; case variable: /*變量名字*/ table(*ptx).level=lev; table(*ptx).adr=(*pdx); (*pdx)+; break; /*過程名字*/ case procedur: table(*ptx).level=lev; break; /* *查找名字的位置 *找到則返回
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年輔警招聘考試綜合提升練習(xí)題及參考答案詳解
- 2022年2月馬鞍山市稅務(wù)系統(tǒng)遴選面試真題附解析
- 2022年2月鞍山市直遴選面試真題附解析
- 2022年2月銀川市稅務(wù)系統(tǒng)遴選面試真題附詳細(xì)解析
- 2022年11月三亞市直遴選面試真題帶詳解
- 2025年云南省交通運輸綜合行政執(zhí)法局文山支隊硯山大隊執(zhí)法輔助人員招聘(1人)筆試備考試題附答案詳解(培優(yōu)a卷)
- 2025年皖北煤電集團總醫(yī)院招聘護理筆試備考題庫附答案詳解(培優(yōu)a卷)
- 麗江云南麗江市交通運輸綜合行政執(zhí)法支隊執(zhí)法輔助人員招聘6人筆試歷年參考題庫及答案詳解(易錯題)
- 南陽投資可行性研究報告
- 3dsmax期末考試試題及答案
- 冀教版五年級數(shù)學(xué)下冊教學(xué)課件 第五單元 長方體和正方體的體積整理與復(fù)習(xí)
- 公車拍賣拍賣工作方案
- 2023年山東高考政治試卷附答案
- C語言課程設(shè)計-家庭財務(wù)管理系統(tǒng)
- 二升三應(yīng)用題100道
- 典當(dāng)管理手冊
- 患者安全和護理風(fēng)險管理
- 宮腔鏡相關(guān)知識考核試題及答案
- 七年級語文下冊知識梳理與能力訓(xùn)練 06 古代詩歌五首理解性默寫與練習(xí)
- 山東省濟寧市任城區(qū)2024屆八年級語文第二學(xué)期期末監(jiān)測試題含解析
- 生物材料學(xué)課件
評論
0/150
提交評論