![PL0源代碼(C語言版).doc_第1頁](http://file1.renrendoc.com/fileroot_temp2/2020-3/14/f3bef52b-beca-46b5-a8a0-b2a099d01ad5/f3bef52b-beca-46b5-a8a0-b2a099d01ad51.gif)
![PL0源代碼(C語言版).doc_第2頁](http://file1.renrendoc.com/fileroot_temp2/2020-3/14/f3bef52b-beca-46b5-a8a0-b2a099d01ad5/f3bef52b-beca-46b5-a8a0-b2a099d01ad52.gif)
![PL0源代碼(C語言版).doc_第3頁](http://file1.renrendoc.com/fileroot_temp2/2020-3/14/f3bef52b-beca-46b5-a8a0-b2a099d01ad5/f3bef52b-beca-46b5-a8a0-b2a099d01ad53.gif)
![PL0源代碼(C語言版).doc_第4頁](http://file1.renrendoc.com/fileroot_temp2/2020-3/14/f3bef52b-beca-46b5-a8a0-b2a099d01ad5/f3bef52b-beca-46b5-a8a0-b2a099d01ad54.gif)
![PL0源代碼(C語言版).doc_第5頁](http://file1.renrendoc.com/fileroot_temp2/2020-3/14/f3bef52b-beca-46b5-a8a0-b2a099d01ad5/f3bef52b-beca-46b5-a8a0-b2a099d01ad55.gif)
已閱讀5頁,還剩28頁未讀, 繼續(xù)免費閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
/*PL/0 編譯系統(tǒng)C版本頭文件 pl0.h*/# define norw 13 /a number of reserved word /*關(guān)鍵字個數(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 /*符號的最大長度*/# define amax 2047 /maximum address /*地址上界*/# define levmax 3 /max depth of block nesting /*最大允許過程嵌套聲明層數(shù)0,lexmax*/# define cxmax 200 /size of code array /*最多的虛擬機代碼數(shù)*/*符號*/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 parenthesisrparen, comma, semicolon,period, becomes,/comma逗號 semicolon分號 period句號 becomes賦值號 beginsym, endsym, ifsym, thensym, whilesym,writesym, readsym, dosym, callsym, constsym,varsym, procsym,;#define symnum 32/*-*/enum object /object為三種標(biāo)識符的類型 constant, variable, procedur,;/*-*/enum fct /fct類型分別標(biāo)識類PCODE的各條指令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; /輸出虛擬機代碼 FILE * fa1; /輸出源文件及其各行對應(yīng)的首地址 FILE * fa2; /輸出結(jié)果 bool tableswitch; /顯示名字表與否 bool listswitch; /顯示虛擬機代碼與否 char ch; /獲取字符的緩沖區(qū),getch使用 enum symbol sym; /當(dāng)前符號 char idal+1; /當(dāng)前ident,多出一個字節(jié)用于存放0 int num; /當(dāng)前number int cc,ll; /getch使用的計數(shù)器,cc表示當(dāng)前字符(ch)的位置 int cx; /虛擬機代碼指針,取值范圍0,cxmax-1char 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; /表示聲明開始的符號集合 ,declaring begin symbol setbool statbegsyssymnum; /表示語句開始的符號集 , statementbool facbegsyssymnum; /表示因子開始的符號集合 ,factor/*-*/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; /*名字表*/FILE * fin; /fin文本文件用于指向輸入的源程序文件FILE* fout; /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) 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=constdeclaration(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,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*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);/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.tmp 輸出名字表*/#include#includepl0.h#includestring.h/*解釋執(zhí)行時使用的棧*/#define stacksize 500int main()bool nxtlevsymnum;printf(Input pl/0 file ?);scanf(%s,fname); /*輸入文件名*/fin=fopen(fname,r); /返回值:文件順利打開后,指向該流的文件指針就會被返回。如果文件打開失敗則返回NULL,并把錯誤代碼存在errno 中if(fin)printf(List object code ?(Y/N); /*是否輸出虛擬機代碼*/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);fprintf(fa1,Iput pl/0 file ?);fprintf(fa1,%sn, fname);init(); /*初始化*/err=0; /錯誤計數(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);printf(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:單字符的符號值 ssym+=plus;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(&(word60),odd);strcpy(&(word70),procedure);strcpy(&(word80),read);strcpy(&(word90),then);strcpy(&(word100),var);strcpy(&(word110),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);strcpy(&(mnemonicopr0),opr);strcpy(&(mnemoniclod0),lod);strcpy(&(mnemonicsto0),sto);strcpy(&(mnemoniccal0),cal);strcpy(&(mnemonicinte0),int);strcpy(&(mnemonicjmp0),jmp);strcpy(&(mnemonicjpc0),jpc);/*設(shè)置符號集*/for(i=0;isymnum;i+)declbegsysi=false;statbegsysi=false;facbegsysi=false;/*設(shè)置聲明開始符號集*/declbegsysconstsym=true;declbegsysvarsym=true;declbegsysprocsym=true;/*設(shè)置語句開始符號集*/statbegsysbeginsym=true;statbegsyscallsym=true;statbegsysifsym=true;statbegsyswhilesym=true;/*設(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;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,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=:) /*檢測賦值符號*/getchdo;if(ch=)sym=becomes;getchdo;elsesym=nul; /*不能識別的符號*/elseif(ch=) /*檢測大于或大于等于符號*/getchdo;if(ch=)sym=geq;getchdo;else sym=gtr;elsesym=ssymch;/* 當(dāng)符號不滿足上述條件時,全部按照單字符號處理*/getchdo;/richardif(sym!=period)getchdo;/end richardreturn 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)前符號是否合法*在某一部分(如一條語句,一個表達式)將要結(jié)束時時我們希望下一個符號屬于某集合*(該部分的后跟符號) test 負責(zé)這項檢測,并且負責(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,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; /*記錄本層名字的初始位置*/ 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) getsymdo;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;if(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,statbegsys,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; /*開始生成當(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+1tx) printf(NULLn); for(i=tx0+1;iamax)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;/* *查找名字的位置 *找到則返回在名字表中的位置,否則返回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等.壓縮文件請下載最新的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)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度車間租賃安全協(xié)議書(含安全生產(chǎn)責(zé)任險)
- 二零二五年度茶業(yè)投資合作框架協(xié)議
- 2025年度解除婚約協(xié)議書(情感修復(fù)與法律支持)
- 二零二五年度油茶種植基地承包與生態(tài)修復(fù)協(xié)議
- 2025年度食堂食品安全風(fēng)險評估與監(jiān)督執(zhí)行協(xié)議
- 施工現(xiàn)場施工防生物污染制度
- 施工日志填寫中的施工材料消耗記錄方法
- 個人商鋪抵押借款合同范本
- 云服務(wù)器托管服務(wù)合同(三)
- 二手廠房買賣合同
- 2025年度高端商務(wù)車輛聘用司機勞動合同模板(專業(yè)版)4篇
- 2025長江航道工程局招聘101人歷年高頻重點提升(共500題)附帶答案詳解
- 2025年黑龍江哈爾濱市面向社會招聘社區(qū)工作者1598人歷年高頻重點提升(共500題)附帶答案詳解
- 執(zhí)行總經(jīng)理崗位職責(zé)
- 《妊娠期惡心嘔吐及妊娠劇吐管理指南(2024年)》解讀
- 《黑神話:悟空》跨文化傳播策略與路徑研究
- 《古希臘文明》課件
- 居家養(yǎng)老上門服務(wù)投標(biāo)文件
- 長沙市公安局交通警察支隊招聘普通雇員筆試真題2023
- 2025年高考語文作文滿分范文6篇
- 零售業(yè)連鎖加盟合同
評論
0/150
提交評論