PL0编译程序的实现

合集下载

第二章PLO编译程序的实现

第二章PLO编译程序的实现

W.Backus与丹麦的Peter Naur来命名的,它从语法上描 述程序设计语言的元语言。采用BNF就可说明哪些符号 序列是对于某给定语言在语法上有效的程序
12
BNF引入的符号:
< > 用左右尖括号括起来的中文字表示语法构造成分,
或称语法单位,为非终结符
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
图 2.2(b) PL/0的解释执行结构
24
PL/O编译程序(包括主程序)是由18个嵌套及并列的过程 或函数组成:
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
25
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
26
PL/O编译程序的过程与函数定义层次结构图
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
界符:
如‘,’、‘.’ 、‘;’ 、‘(’ 、‘)’等
33
词法分析程序GETSYM所要完成的任务:
滤空格、识别保留字 识别标识符、拼数
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
拼复合词、输出源程序
34
取字符过程GETCH:
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
43
(2)过程体的处理: 程序的主体是由语句构成的
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
处理完过程的说明后就处理由语句组成的过程体,从语法 上对语句逐句分析 当语法正确时就生成相应语句功能的目标代码
图 2.6 取字符过程GETCH
35
§2.4 PL/O编译程序的语法语义分析
语法分析的任务:识别单词符号序列是否符合给定的语法
盛 威 网 : 专 业 的 计 算 机 学 习 网 站

标准实验报告(PL0编译程序)

标准实验报告(PL0编译程序)

[标准实验报告]南昌航空大学实验报告年月日课程名称:编译原理实验名称:扩充的PL/0编译程序班级:姓名:同组人:指导教师评定:签名:一、实验目的进一步熟悉编译程序的整体框架,给出整个编译程序的流程结构,用C 或vc++语言编写程序;并将编制的编译程序进行调试、实现PL/0编译程序。

二、实验要求(1)根据所选的程序设计语言,修改并调试。

(2)举出例子程序,在程序中进行编译。

(3)用此编译程序对有关语句进行编译,并输出目标指令。

(4)书写出合格的实验报告。

三、实验步骤1.输入文件中变量的声明形如:var a,b,c; 以var保留字开始,不同变量以”,”分隔,最后以”;”结束。

2.read语句格式为read(a)或者read(a,b);3.write语句格式为write(a),括号里面没有字符串常量,注意与书后的形如write(‘a=’,a)是不相同的。

4.的声明形如:”procedure proname;”不含参数表。

5.一维数组形如:变量类型array 数组名[数组下标]。

6.条件语句形如:if <条件>then<语句> {;else,语句>}7.扩充的记录型数据类型形如:for 循环语句及带参数的过程。

四、参考源代码#include<stdio.h>/*#include"plo.h"*/#include"string.h"#define stacksize 500typedef enum{false,true}bool;enum object{procedur , constant ,variable};#define norw 13#define txmax 100#define nmax 14#define al 10#define levmax 3#define cxmax 200#define amax 2047#define symnum 32enum 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, constsym,varsym, procsym,};enum fct {lit, opr, lod,sto, cal, inte,jmp, jpc,};#define fctnum 8struct instruction{enum fct f;int l;int a;};FILE* fas;FILE* fa;FILE* fal;FILE* fa2;bool listswitch;bool tableswitch;char ch;enum symbol sym;char id[al+1];int num;int cc,ll;int cx;char line[81];char a [al+1];int num ;int cc,ll;int cx;char line [81];char a [al+1];struct instruction code [cxmax]; char word [norw][al];struct instruction code [cxmax]; char word [norw][al];enum symbol wsym [norw]; enum symbol ssym [256]; char mnemonic [fctnum][5]; bool declbegsys [symnum]; bool statbegsys [symnum]; bool facbegsys [symnum]; bool facstatbegsys[symnum]; struct tablestruct{char name [al];enum object kind ;int val;int level;int adr;int size;};struct tablestruct table [txmax]; FILE * fin;FILE * fout;char fname [al];int err;#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 -1 void error(int n);int getsym();int getch();void init();int gen(enum fct x,int y,int z);int test(bool *sl,bool *s2,int n);int inset (int e,bool *s);int addset (bool* sr,bool* sl,bool *s2,int n);int subset (bool* sr,bool* sl,bool *s2,int n);int mulset (bool* sr,bool* sl,bool *s2,int n);int block (int lev,int tx,bool* fsys);void interpret();int factor (bool* fays,int * ptx,int lev);int term (bool* fays,int * ptx,int lev);int condition (bool* fays,int * ptx,int lev);int expression (bool* fays,int * ptx,int lev);int statement (bool* fays,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);int main(){bool nxtlev[symnum];printf("input pl/o file?");scanf("%s",fname);fin=fopen(fname,"r");if(fin){printf("list objeck code? (Y/N)");scanf("%s",fname);/*listwitch=(fname[0]=='y'||fname[0]=='Y');*/ printf("list symbol table? (Y/N)");scanf("%s",fname);tableswitch=(fname[0]=='y'||fname[0]=='Y'); fal=fopen("fal.tmp","w");fprintf(fal,"input pl/o file?");fprintf(fal,"%s",fname);init();err=0;cc=cx=ll=0;ch='';if(-1 !=getsym()){ fa=fopen("fa.tmp","w");fas=fopen("fas.tmp","w");addset(nxtlev,declbegsys,statbegsys,symnum); nxtlev[period]=true;if(-1==block(0,0,nxtlev)){fclose(fa);fclose(fal);fclose(fas);fclose(fin);printf("\n");return 0;}fclose(fa);fclose(fal);fclose(fas);if(sym!=period){error(9);}if(err==0){fa2=fopen("fa2.tmp","w");interpret();fclose(fa2);}else{printf("error in pl/o program"); }}fclose(fin);}else{printf("can't open file! \n");}printf("\n");return 0;}/*chushihua*/void init(){ int i;for (i=0;i<=255;i++){ssym[i]=nul;}ssym['+']=plus;ssym['-']=minus;ssym['*']=times;ssym['/']=slash;ssym['(']=lparen;ssym[')']=rparen;ssym['=']=eql;ssym[',']=comma;ssym['.']=period;ssym['#']=neq;ssym[';']=semicolon;strcpy(&(word[0][0]),"begin"); strcpy(&(word[1][0]),"call"); strcpy(&(word[2][0]),"const"); strcpy(&(word[3][0]),"do");strcpy(&(word[4][0]),"end");strcpy(&(word[5][0]),"if");strcpy(&(word[6][0]),"odd"); strcpy(&(word[7][0]),"procedure"); strcpy(&(word[8][0]),"read"); strcpy(&(word[9][0]),"then"); strcpy(&(word[10][0]),"var"); strcpy(&(word[11][0]),"while"); strcpy(&(word[12][0]),"write");wsym[0]=beginsym;wsym[1]=callsym;wsym[2]=constsym;wsym[3]=dosym;wsym[4]=endsym;wsym[5]=ifsym;wsym[6]=oddsym;wsym[7]=procsym;wsym[8]=readsym;wsym[9]=thensym;wsym[10]=varsym;wsym[11]=whilesym;wsym[12]=writesym;strcpy(&(mnemonic[lit][0]),"lit"); strcpy(&(mnemonic[opr][0]),"opr"); strcpy(&(mnemonic[lod][0]),"lod"); strcpy(&(mnemonic[sto][0]),"sto"); strcpy(&(mnemonic[cal][0]),"cal"); strcpy(&(mnemonic[inte][0]),"inte"); strcpy(&(mnemonic[jmp][0]),"jmp"); strcpy(&(mnemonic[jpc][0]),"jpc");for(i=0;i<symnum;i++){declbegsys[i]=false;statbegsys[i]=false;facbegsys[i]=false;}declbegsys[constsym]=true;declbegsys[varsym]=true;declbegsys[procsym]=true;statbegsys[beginsym]=true;statbegsys[callsym]=true;statbegsys[ifsym]=true;statbegsys[whilesym]=true;facstatbegsys[ident]=true; facstatbegsys[number]=true; facstatbegsys[lparen]=true;}int inset(int e,bool*s){return s[e];}int addset(bool* sr,bool * s1,bool* s2,int n) {int i ;for(i=0;i<n;i++){sr[i]=s1[i]||s2[i];}return 0;}int subset(bool* sr,bool * s1,bool* s2,int n) {int i ;for(i=0;i<n;i++){sr[i]=s1[i]&&(!s2[i]);}return 0;}int mulset(bool* sr,bool * s1,bool* s2,int n) {int i ;for(i=0;i<n;i++){sr[i]=s1[i]&&(s2[i]);}return 0;}void error(int n){char space[81];memset(space,32,81);space[cc-1]=0;printf("*****%s!%d\n",space,n);fprintf(fal,"********%s!%d\n",space,n); err++;}int getch(){if(cc==ll){if(feof(fin)){printf("program,incomplete");return -1;}ll=0;cc=0;printf("%d",cx);fprintf(fal,"%d",cx);ch='';while(ch!=10){if(EOF==fscanf(fin,"%c",&ch)){line[ll]=0;break;}printf("%c",ch);fprintf(fal,"%c",ch);line[ll]=ch;++ll;}printf("\n");fprintf(fal,"\n");}ch=line[cc];cc++;return 0;}/*****************************8 */int getsym(){int i,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');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;}}else{if(ch=='>'){getchdo;if(ch=='='){sym=geq;getchdo;}else{sym=gtr;}}else{sym=ssym[ch];if(sym!=period){getchdo;}}}}}}return 0;}int gen(enum fct x,int y,int z){if(cx>=cxmax){printf("program too ling ");return -1;}code[cx].f=x;code[cx].l=y;code[cx].a=z;cx++;return 0;}int test(bool * s1,bool * s2,int n){if(! inset(sym,s1)){error(n);while((! inset(sym,s1))&&(! inset(sym,s2))) {getsymdo;}}return 0;}int block(int lev,int tx,bool* fsys){int i;int dx;int txo;int cxo;bool nxtlev[symnum];dx=3;txo=tx;table[tx].adr=cx;gendo(jmp,0,0);if(lev>levmax){error(32);}do{if(sym==constsym){getsymdo;do{constdeclarationdo(&tx,lev,&dx);while(sym==comma){getsymdo;constdeclarationdo(&tx,lev,&dx);}if (sym==semicolon) {getsymdo;}else{error(5);}}while(sym==ident);}if(sym==varsym) {getsymdo;do{vardeclarationdo(&tx,lev,&dx); while(sym==comma) {getsymdo; vardeclarationdo(&tx,lev,&dx); }if(sym==semicolon) {getsymdo;}else{error(5);}}while(sym==ident);}while(sym==procsym) {getsymdo;if(sym==ident){enter(procedur,&tx,lev,&dx); getsymdo;}else{error(4);}if(sym==semicolon) {getsymdo;}else{error(5);}memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[semicolon]=true;if(-1==block(lev+1,tx,nxtlev)){return -1;}if(sym==semicolon){getsymdo;memcpy(nxtlev,statbegsys,sizeof(bool) * symnum); nxtlev[ident]=true;nxtlev[procsym]=true;testdo(nxtlev,fsys,6);}else{error(5);}}memcpy(nxtlev,statbegsys,sizeof(bool) * symnum); nxtlev[ident]=true;nxtlev[period]=true;testdo(nxtlev,declbegsys,7);}while(inset(sym,declbegsys));code[table[txo].adr].a=cx;table[txo].adr=cx;table[txo].size=dx;cxo=cx;gendo(inte,0,dx);if(tableswitch){printf("TABLE:\n");if(txo+1>tx){printf("NULL\n");}for(i=txo+1;i<=tx;i++){switch(table[i].kind){case constant:printf("%d const %s",i,table[i].name);printf("val=%d\n",table[i].val);fprintf(fas,"%d const %s",i,table[i].name);fprintf(fas,"val=%d\n",table[i].val);break;case variable:printf("%d var %s",i,table[i].name);printf("lev=%d addr=%d\n",table[i].level,table[i].adr);fprintf(fas,"%d var %s",i,table[i].name);fprintf(fas,"lev=%d addr=%d\n",table[i].level,table[i].adr);break;case procedur:printf("%d proc %s",i,table[i].name);printf("lev=%d addr=%d size=%d\n",table[i].level,table[i].adr,table[i].size); fprintf(fas,"%d proc %s",i,table[i].name);fprintf(fas,"lev=%d addr=%d size=%d\n",table[i].level,table[i].adr,table[i].size); break;}}printf("\n");}memcpy(nxtlev,fsys,sizeof(bool) * symnum);nxtlev[semicolon]=true;nxtlev[endsym]=true;statementdo(nxtlev,&tx,lev);gendo(opr,0,0);memset(nxtlev,0,sizeof(bool) * symnum);testdo(fsys,nxtlev,8);listcode(cxo);return 0;}void enter(enum object k , int * ptx , int lev , int * pdx){(*ptx)++;strcpy(table[(*ptx)].name,id);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;}}int position(char*idt,int tx){int i;strcpy(table[0].name,idt);i=tx;while(strcmp(table[i].name,idt)!=0){i--;}return i;}int constdecalration(int *ptx,int lev,int *pdx) {if(sym==ident){getsymdo;if(sym==eql||sym==becomes){if(sym==becomes)error(1);getsymdo;if(sym==number){enter(constant,ptx,lev,pdx);getsymdo;}else{error(2);}}else{error(3);}}else{error(4);}return 0;}int constdeclaration(int * ptx,int lev,int * pdx){if (sym==ident){getsymdo;if (sym==eql||sym==becomes){if (sym==becomes){error(1);}getsymdo;if (sym ==number){enter(constant,ptx,lev,pdx);getsymdo;}else{error(2);}}else{error(3);}}else{error(4);}return 0;}int vardeclaration(int* ptx,int lev,int* pdx){if (sym==ident){enter(variable,ptx,lev,pdx);getsymdo;}else{error(4);}return 0;}void listcode(int cx0){int i;if (listswitch){for (i=cx0;i<cx;i++){printf("%d %d %d %d\n",i,mnemonic[code[i].f],code[i].l,code[i].a);fprintf(fa,"%d %s %d %d\n",i,mnemonic[code[i].f],code[i].l,code[i].a);}}}int statement(bool* fsys,int* ptx,int lev){int i,cxl,cx2;bool nxtlev[symnum];if (sym==ident){i=position(id,*ptx);if (i==0){error(11);}else{if(table[i].kind !=variable){error(12);i=0;}else{getsymdo;if(sym==becomes){getsymdo;}else{error(13);}memcpy(nxtlev,fsys,sizeof(bool)*symnum);expressiondo(nxtlev,ptx,lev);if(i!=0){gendo(sto,lev-table[i].level,table[i].adr);}}}/*if(i==0)*/}else{if(sym==readsym){getsymdo;if(sym!=lparen){error(34);}else{do{getsymdo;if(sym==ident){i=position(id,*ptx);}else{i=0;}if(i==0){error(35);}else{gendo(opr,0,16);gendo(sto,lev-table[i].level,table[i].adr) ;}getsymdo;}while(sym==comma);}if(sym!=rparen){error(33);while(! inset(sym,fsys)){getsymdo;}}else{getsymdo;}}else{if(sym==writesym){getsymdo;if(sym==lparen){do{getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[rparen]=true;nxtlev[comma]=true;expressiondo(nxtlev,ptx,lev);gendo(opr,0,14);}while(sym==comma);if(sym!=rparen){error(33);}else{getsymdo;}}gendo(opr,0,15);}else{if(sym==callsym){getsymdo;if(sym!=ident){error(14);}else{i=position(id,*ptx);if(i==0){error(11);}else{if(table[i].kind==procedur){gendo(cal,lev-table[i].level,table[i].adr);}else{error(15);}}getsymdo;}}else{if(sym==ifsym){getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[thensym]=true;nxtlev[dosym]=true;conditiondo(nxtlev,ptx,lev);if(sym==thensym){getsymdo;}else{error(16);}cxl=cx;gendo(jpc,0,0);statementdo(fsys,ptx,lev);code[cxl].a=cx;}else{if(sym==beginsym){getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[semicolon]=true;nxtlev[endsym]=true;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);}}else{if(sym==whilesym){cxl=cx;getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[dosym]=true;conditiondo(nxtlev,ptx,lev);cx2=cx;gendo(jpc,0,0);if(sym==dosym){getsymdo;}else{error(18);}statementdo(fsys,ptx,lev);gendo(jmp,0,cxl);code[cx2].a=cx;}else{testdo(fsys,nxtlev,19);}}}}}}}return 0;}int expression(bool * fsys,int * ptx,int lev){enum symbol addop;bool nxtlev[symnum];if(sym==plus||sym==minus){addop=sym;getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[plus]=true;nxtlev[minus]=true;termdo(nxtlev,ptx,lev);if(addop==minus){gendo(opr,0,1);}}else{memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[plus]=true;nxtlev[minus]=true;termdo(nxtlev,ptx,lev);}while(sym==plus||sym==minus){addop=sym;getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[plus]=true;nxtlev[minus]=true;termdo(nxtlev,ptx,lev);if(addop==plus){gendo(opr,0,2);}else{gendo(opr,0,3);}}return 0;}int term(bool*fsys,int*ptx,int lev){enum symbol mulop;bool nxtlev[symnum];memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[times]=true;nxtlev[slash]=true;factordo(nxtlev,ptx,lev);while(sym==times||sym==slash){mulop=sym;getsymdo;factordo(nxtlev,ptx,lev);if(mulop==times){gendo(opr,0,4);}else{gendo(opr,0,5);}}return 0;}int factor(bool*fsys,int*ptx,int lev){int i;bool nxtlev[symnum];testdo(facbegsys,fsys,24);while(inset(sym,facbegsys)){if(sym==ident){i=position(id,*ptx);if(i==0){error(11);}else{switch(table[i].kind){case constant:gendo(lit,0,table[i].val);break;case variable:gendo(lod,lev-table[i].level,table[i].adr);break;case procedur:error(21);break;}}getsymdo;}else{if(sym==number){if(num>amax){error(31);num=0;}gendo(lit,0,num);getsymdo;}else{if(sym==lparen){getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[rparen]=true;expressiondo(nxtlev,ptx,lev);if(sym==rparen){getsymdo;}else{error(22);}}testdo(fsys,facbegsys,23);}}}return 0;}int condition(bool*fsys,int*ptx,int lev){enum symbol relop;bool nxtlev[symnum];if(sym==oddsym){getsymdo;expressiondo(fsys,ptx,lev);gendo(opr,0,6);}else{memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[eql]=true;nxtlev[neq]=true;nxtlev[lss]=true;nxtlev[leq]=true;nxtlev[gtr]=true;nxtlev[geq]=true;expressiondo(nxtlev,ptx,lev);if(sym!=eql&&sym!=neq&&sym!=lss&&sym!=leq&&sym!=gtr&&s ym!=geq){error(20);}else{relop=sym;getsymdo;expressiondo(fsys,ptx,lev);switch(relop){case eql:gendo(opr,0,8);break;case neq:gendo(opr,0,9);break;case lss:gendo(opr,0,10);break;case geq:gendo(opr,0,11);break;case gtr:gendo(opr,0,12);break;case leq:gendo(opr,0,13);break;}}}return 0;}void interpret(){int p,b,t;struct instruction i;int s[stacksize];printf("start pl0\n");t=0;b=0;p=0;s[0]=s[1]=s[2]=0;do{i=code[p];p++;switch(i.f){case lit:s[t]=i.a;t++;break;case opr:switch(i.a){case 0:t=b;p=s[t+2];b=s[t+1]; break;case 1:s[t-1]=-s[t-1]; break;case 2:t--;s[t-1]=s[t-1]+s[t]; break;case 3:t--;s[t-1]=s[t-1]-s[t]; break;case 4:t--;s[t-1]=s[t-1]*s[t]; break;case 5:t--;s[t-1]=s[t-1]/s[t]; break;case 6:t--;s[t-1]=s[t-1]%2; break;case 8:t--;s[t-1]=(s[t-1]==s[t]); break;case 9:t--;s[t-1]=(s[t-1]!=s[t]); break;case 10:t--;s[t-1]=(s[t-1]<s[t]); break;case 11:t--;s[t-1]=(s[t-1]>=s[t]); break;case 12:t--;s[t-1]=(s[t-1]>s[t]); break;case 13:t--;s[t-1]=(s[t-1]<=s[t]); break;case 14:printf("%d",s[t-1]); fprintf(fa2,"%d",s[t-1]); t--;break;case 15:printf("\n");fprintf(fa2,"\n"); break;case 16:printf("?");fprintf(fa2,"?");scanf("%d",&(s[t])); fprintf(fa2,"%d\n",s[t]);t++;break;}break;case lod:s[t]=s[base(i.l,s,b)+i.a];t++;break;case sto:t--;s[t]=s[base(i.l,s,b)+i.a]=s[t]; break;case cal:s[t]=base(i.l,s,b);s[t+1]=b;s[t+2]=p;b=t;p=i.a;break;case inte:t+=i.a;break;case jmp:p=i.a;break;case jpc:t--;if(s[t]==0)p=i.a;break;}}while(p!=0);}int base(int l,int *s,int b) {int b1;b1=b;while(l>0){b1=s[b1];l--;}return b1;}五、实验结果1.输入PL/0源程序const a=10;var b,c;procedure pbeginc:=b+aend;beginread (b);while b#0 dobegincall p;write(2*c);read(b)endend.2. 输入分别输入b值的结果当b=2;输出结果为24当b=3;输出结果为26当b=1;出结果为22当b=0;结束程序六、实验体会通过该实验,本人学会了应用C语言调试和扩充PL/0编译程序的能力,此实验完成了PL/0词法分析、语法分析、语义分析、代码生成和代码优化等功能,并在此基础上实现了PL/0语言的扩充能力,从实际的应用中深刻领悟了编译程序的原理,更加深刻的学习了理论知识。

第二章PL0编译程序的实现

第二章PL0编译程序的实现
是整个编译过程的核心。
PL/0编译程序的总体设计
词法分析程序和代码生成程序都作为一个过 程,当语法分析需要读单词时就调用词法分 析程序,而当语法、语义分析正确,需要生 成相应的目标代码时,则调用代码生成程序
表格管理程序实现变量,常量和过程标识符 的信息的登录与查找。
出错处理程序,对词法和语法、语义分析遇 到的错误给出在源程序中出错的位置和与错 误 性质有关的编号,并进行错误恢复。
read(b);
end
end.
2.1.2 PL/0语言文法的EBNF表示
BNF(BACKUS-NAUR FORM)是根据美国 的John W.Backus与丹麦的Peter Naur来 命名的,它从语法上描述程序设计语言的元 语言(metalanguage)。
采用BNF就可说明哪些符号序列是对于某给 定语言在语法上有效的程序。
自顶向下的语法分析<程序>
<分程序>
.
VAR A; BEGIN READ(A) END.
<变量说明部分> <语句>
VAR <标识符> ; <复合语句> BEGIN <语句> END
A <读语句>
READ ( <标识符> )
A
递归子程序法
递归子程序法:对应每个非终结符语法单元,
编一个独立的处理过程(或子程序)。 语法分析从读入第一个单词开始由非终结符
非终结符(non-terminal symbol)—在描述 过程中定义的,代表某一类语法单位的集合 的,需要继续定义的符号。
终结符(terminal symbol)—最终定义的不能 用更小的语法单位替换的符号。

第二章PL0编译程序的实现

第二章PL0编译程序的实现

PL/0程序示例
CONST A=10; (* 常量说明部分 *) VAR B,C; (* 变量说明部分 *) PROCEDURE P; (* 过程说明部分 *) VAR D;(* P的局部变量说明部分 *) PROCEDURE Q; (* P的局部过程说明部分 *) VAR X; BEGIN 说明部分 READ(X); D:=X; Q过程体 WHILE X#0 DO CALL P; END; BEGIN WRITE(D); p过程体 CALL Q; END; BEGIN CALL P; 主程序体 END.
程序
分程序
.
内的文字表示语法成分(非终结符) 或 内的文字表示单词符号 (终结符)
非终结符:可由其它文法符号定义。 终结符:语法成分的最小单位,不能由其 它文法符号定义。
PL/0语言的EBNF(巴科斯-瑙尔范式)表示
● 构成EBNF的元素:非终结符,终结符,开始符,规 则。 EBNF 的表示符号说明: < >:用左右尖括号括起来的内容为非终结符 ∷= :读做‘定义为’ ,∷=的左部由右部定义 → :读做‘定义为’ , → 的左部由右部定义 | :读做‘或’ ,表示右部候选内容 { } :表示花括号内的内容可重复任意次或限定 次数 [ ] :表示方括号内的内容为任选项 ( ) :表示圆括号内的内容优先
说明部分
PL/0程序示例
CONST A=10; (* 常量说明部分 *) VAR B,C; (* 变量说明部分 *) BEGIN READ(B); C:=B; WHILE B#0 DO BEGIN 程序体 C:=C+B; B:=B-1; END; WRITE(C); END. 说明部分
PL/0程序示例
pl/0程序--递规调用

第2章 PL0编译程序的实现

第2章 PL0编译程序的实现

2
PL/0语言的语法描述图
程序 分程序
分程序
.
常量说明部分
变量说明部分 过程说明部分 语句
3
PL/0语言的语法描述图
分程序
常量说明部分 变量说明部分 过程说明部分 语句
4
5
例子

因子

a 10 a b*10 a a+10 a+b*10 -a+2*(x+10)-10*(b-10)





<分程序>::=[<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句>
9
由语法描述图转化到BNF范式
常量定义
<常量说明部分>::=CONST<常量定义>{,<常量定义>}; <常量定义>::=<标识符>=<无符号整数> <无符号整数>::=<数字>{<数字>}
10
回家作业

1 编写一个PL0语言的程序,要求:
a) 声明2个常数,c1为2,c2为10 b) 声明3个变量,num1、count和sum c) 第一条语句是赋值语句,将c1赋给num1 d) 第二条语句是条件语句,如果num1>0,则执行第三条语句, 否则将num1减1 e) 第三条语句是赋值语句,将0赋给sum e) 第四条语句是循环语句,循环变量count从1到c2,每次将 count值加到sum中
回家作业
2 编写一个PL0语言的程序,要求: a) 包含一个过程procedure 过程名 字为GetSum, 功能是计算累加和 const c1=0,c2=10; var count,sum; procedure GetSum; begin sum:=sum+count end begin sum:=0; count=c1; while count<=c2 do begin count:=count+1; call GetSum; end; end.

PL0编译程序的实现(精)

PL0编译程序的实现(精)

( 0) ( 1) ( 2) ( 3) ( 4) ( 5) ( 6) ( 7) ( 8) ( 9) (10) (11) (12) (13) (14) (15) (16) (17) (18) (19) (20) (21) (22) (23) (24)
jmp jmp int lod lit opr sto opr int opr sto lod lit opr jpc cal lit lod opr opr opr opr sto jmp opr
PL/0编译程序功能的框架 PL/0源程序 PL/0编译程序
类 pcode代码
类 pcode解释程序 输入 输出
第2 章
PL/0编译程序的实现
步骤1. 源语言PL/0与目标代码类pcode 之间的映射 步骤2. PL/0编译程序的总体设计 步骤3. PL/0编译程序词法分析的设计与实现 步骤4. PL/0编译程序语法语义分析的设计与实现 步骤5. PL/0编译程序代码生成的实现 *步骤6. PL/0编译程序错误处理的实现 步骤7. 类pcode代码解释器的设计与实现
步骤1 PL/0程序到类pcode代码的映射
目标代码类pcode是一种假想栈式计算机的汇编 语言。 指令格式 f l a
f
l a
功能码
层次差 (标识符的引用层减去它的定义层) 根据不同的指令有所区别
假想栈式计算机的运行栈 T是栈顶指针 B是基地址:分配给一个过程数据空间的开始位置 T
B
2 1 0
步骤3
PL/0编译程序词法分析的 设计与实现
词法分析如何把单词传递给语法分析 单词定义(见教材288页) type symbol=(nul,ident,number,plus,…, varsym,procsym); ( 定义纯量/枚举类型,类似C的enum) sym:symbol; id:alfa; (type alfa=packed array[1..al] of char) al=10; num:integer;

第二章PL编译程序的实现

第二章PL编译程序的实现

BNF与EBNF表示的符号说明 BNF引入的符号: <> 用左右尖括号括起来的语法成分为非 终结符 ∷= 该符号的左部由右部定义 | ‘或’ EBNF引入的符号: { } 表示花括号内的语法成分可重复 [ ] 表示方括号内的语法成分为任选项 ( ) 表示圆括号内的成分优先
Hale Waihona Puke 例子:用EBNF描述: 整数: <整数>∷=[+|-]<数字>{<数字>} <数字>∷=0|1|2|3|4|5|6|7|8|9 不允许以0开头的整数 <整数>∷=[+|-]<非零数字>{<数字>}|0 <非零数字>∷=1|2|3|4|5|6|7|8|9 <数字>∷=0|1|2|3|4|5|6|7|8|9
ADR: DX ADR: DX+1 ADR: DX+2 ADR:
SIZE:4
NAME:G Kind :VARIBALE … …
LEVEL:LEV+1 …
ADR: DX …
过程体的语义分析
当遇到标识符的引用时,就查符号表,看 是否有过正确定义,若已有,则从表中 取相应的属性,供代码生成使用,若无 则报错,当语义正确时,就生成相应的 目标代码
INT 0 a 在运行栈中为调用的过程开辟a个单元的数 据区 JMP 0 a 无条件跳转至a地址 JPC 0 a 条件跳转,当栈顶布尔值为非真则跳转至a 地址,否则顺序执行
OPR 0 0 OPR 0 1 OPR 0 2 OPR 0 3 OPR 0 4 OPR 0 5 OPR 0 6 OPR 0 7 OPR 0 8 OPR 0 9
PL/0语言文法的EBNF表示为: <程序 > ::= <分程序 >.

一个PASCAL语言子集(PL0)编译器的设计与实现

一个PASCAL语言子集(PL0)编译器的设计与实现

编译原理课程设计报告班级:姓名:2007-12目录1.设计任务2.原理框图3.函数说明4.程序代码5.程序测试6.试验体会7.参考资料一.设计任务课程设计的教学基本要求1.巩固和加深对编译原理的理解,提高综合运用本课程所学知识的能力。

2.培养独立思考,深入研究,分析问题、解决问题的能力。

3.能够按要求编写课程设计报告书,能正确阐述设计和实验结果,正确绘制系统和程序框图。

4.通过课程设计,培养严肃认真的工作作风。

●课程设计题目一个PASCAL语言子集(PL/0)编译器的设计与实现●PL/0语言的BNF描述(扩充的巴克斯范式表示法)<prog> → program <id>;<block><block> → [<condecl>][<vardecl>][<proc>{;<proc>}]<body><condecl> → const <const>{,<const>}<const> → <id>:=<integer><vardecl> → var <id>{,<id>}<proc> → procedure <id>[(<id>{,<id>})];<block><body> → begin <statement>{;<statement>}end<statement> → <id> := <exp>|if <lexp> then <statement>[else <statement>]|while <lexp> do <statement>|call <id>[(<exp>{,<exp>})]|<body>|read (<id>{,<id>})|write (<exp>{,<exp>})<lexp> → <exp> <lop> <exp>|odd <exp><exp> → [+|-]<term>{<aop><term>}<term> → <factor>{<mop><factor>}<factor>→<id>|<integer>|(<exp>)<lop> → =|<>|<|<=|>|>=<aop> → +|-<mop> → *|/<id> → l{l|d} (注:l表示字母)<integer> → d{d}注释:<prog>:程序;<block>:块、程序体;<condecl>:常量说明;<const>:常量;<vardecl>:变量说明;<proc>:分程序;<body>:复合语句;<statement>:语句;<exp>:表达式;<lexp>:条件;<term>:项;<factor>:因子;<aop>:加法运算符;<mop>:乘法运算符;<lop>:关系运算符。

第二章 PL0编译程序的实现

第二章 PL0编译程序的实现

编译原理
◇ 建议用一个PL/0源程序的例子为导引作为 阅读PL/0语言编译程序文本的入门,然后再逐步 全面读懂。 ◇ 通过对PL/0语言编译程序某些指定功能的 扩充,加深对编译程序构造步骤和实现技术的理 解,并能在实践中应用。 【教学方式】 以学生自学为主。
编译原理
【难 重 点】 重点: ◇ 弄清源语言(PL/0)目标语言(类 pcode)实现 语言(pascal) 这3个语言之间的关系和作用。 ◇ 掌握用语法图和扩充的巴科斯-瑙尔范式 (EBNF)对一个高级程序设计语言的形式描述。 ◇ 了解PL/0语言编译程序的语法分析技术采用 的是自顶向下递归子程序法。 ◇ 掌握PL/0语言编译程序的整体结构和实现步 骤,并弄清词法分析、语法分析、语义分析、代码 生成及符号表管理每个过程的功能和相互联系。
编译原理
第2章 PL/0编译程序的实现
【学习目标】 本章目的:以PL/0语言编译程序为实例,学习编 译程序实现的基本步骤和相关技术,对编译程序的构 造和实现得到一些感性认识和建立起整体概念,为后 面的原理学习打下基础。 ◇ 了解用语法图和扩充的巴科斯-瑙尔范式 (EBNF)对 PL/0语言的形式描述。 ◇ 了解PL/0语言编译程序构造和实现的基本技 术和步骤。 ◇ 了解PL/0语言编译程序的目标程序在运行时 数据空间的组织管理。
返回目录
Байду номын сангаас
编译原理
【学习指南】 ◇ 要求读者阅读PL/0语言编译程序文本,了 解一个编译程序构造的必要步骤和实现技术。一个 编译程序的实现比较复杂,读懂一个典型的程序从 设计思想到实现技术也有一定难度,特别是入门开 始需要耐心。一但读懂,不仅了解编译程序的实现 方法和技术,还可学到许多编程技巧和好的编程风 格。 ◇ 阅读PL/0语言编译程序文本时,应从整体 结构开始逐步细化,弄清楚每个过程的功能和实现 方法及过程之间的相互关系。

第2章__PL0编译程序的实现

第2章__PL0编译程序的实现

词法分析程序
语法分析程序
表 格 管 理 程 序 语义分析程序 中间代码生成程序 出 错 处 理 程 序
代码优化程序
目标代码生成程序
注意
上述编译过程的阶段划分只是一种典型的分法, 事实上并不是所有的编译程序都分成这样几个 阶段的。 有些编译程序对优化没有什么要求,优化阶段 就可省去。在某些情况下,为了加快编译速度, 中间代码产生阶段也可以去掉。有些最简单的 编译程序是在语法分析的同时产生目标代码。 但是,多数实用编译程序的工作过程大致都像 上面所说的那六个阶段。
其它
编译程序的另外两个重要的工作是表格管理和 出错处理。 编译过程中源程序的各种信息被保留在种种不 同的表格里,编译各阶段的工作都涉及到构造、 查找或更新有关的表格,因此需要有表格管理 的工作;如果编译过程中发现源程序有错误, 编译程序应报告错误的性质和错误发生的地点, 并且将错误所造成的影响限制在尽可能小的范 围内,使得源程序的其余部分能继续被编译下 去,有些编译程序还能自动校正错误,这些工 作称之为出错处理。
CONST A=10; (* 常量说明部分 *) VAR B,C; (* 变量说明部分 *) PROCEDURE P; (* 过程说明部分 *) VAR D;(* P的局部变量说明部分 *) PROCEDURE Q; (* P的局部过程说明部分 *) VAR X; BEGIN READ(X); D:=X; Q过程体 WHILE X#0 DO CALL P; END; BEGIN WRITE(D); p过程体 CALL Q; END; BEGIN CALL P; 主程序体 END.
〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}
<过程说明部分>::=<过程首部><分程序>{; <过程说明部分>} <过程首部>::=PROCEDURE<标识符>;

第2章 PL-0编译程序的实现

第2章  PL-0编译程序的实现

3、PL/0编译程序是用PASCAL语言编写, 可在任何配有PASCAL编译系统的计算机 上运行。
PL/0 Compiler 源文本
PASCAL Compiler
PL/0 Compiler 目标文本
PL/0 Compiler 目标文本
PL/0 目标程序
PL/0 源程序
2.2 PL/0编译程序的结构
第 2章 PL/0编译程序的实现
2.1 2.2 2.3 2.4 2.5
PL/0语言描述 PL/0编译程序的结构 PL/0编译程序的语法语义分析 PL/0编译程序的错误处理 类pcode代码解释器
本章目的:以PL/0为实例,学习编译 程序实现的基本步骤和相关技术
PL/0语言简介 PL/0是一个非常小的程序设计语言, 它是由Pascal的发明人Niklaus Wirth所定 义的。它是Pascal的一个子集,有嵌套的 过程,但过程不能有参数,没有函数,没 有分支语句,没有for 循环,条件语句不支 持else,只有一个整数数据类型。
程序
分程序
.
内的文字表示非终结符 或 内的文字或符号表示终结符
2.1.1 PL/0语言的语法描述图
语法描述图 下页
分程序
Const , ;
ident
=
number
Var
, ; ;
procedure
ident
ident
;
分程序
语句
语句
ident call begin
:=
表达式
ident
.
语句 语句
0 l l l 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a a a a a a a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

PL0编译程序的实现-教案

PL0编译程序的实现-教案
PL/0语言 目标程序 执行结果
10
11
12
ô ¯ Æ ¶ Ã õ µ Ö ³ Ö
编 译 程 序 总 体 流 程 图
ôÃ GETSYMÈ ¥ Ê µ Ó ¡ µ ´ ôÃ BLOCK¹ Ì µ Ó ù ³
±°¥ Ê µ Ç µ ´ Ç ñ ª ´ Ì ò á ÷ ø Ê ²Î Ô ³ Ð ½ Ê ² '.'£ ¿ Y ´ Ì ò Ð Ô ³ Ð Ö Ç ñ Ð í ó ¿ Ê ²Ó ´ Î £ N ôà â Í ù Ì INTERPRET µ Ó ½ Ê ¹ ³ â Í ´ Ð ¿ ê Ì ò ½ Ê Ö Ä ±³ Ð Y
23
表格管理
CONST A=35,B=49; VAR C,D,E; PROCEDURE P; VAR G
1 2
实例分析
层次/值 VAL:35 VAL:49 LEVEL:LEV LEVEL:LEV LEVEL:LEV LEVEL:LEV LEVE:LEV+1 …… 地址 存储空间
3
4 5 6 7
名字 NAME:A NAME:B NAME:C NAME:D NAME:E NAME:P NAME:G ……
变量 b
RA 0 DL 0 SL:静态链 DL:动态链 RA:返回地址 SL 0 0 运行栈 27
允许过程嵌套、递归语言的目标程序
ห้องสมุดไป่ตู้
运行时存储空间的组织与管理
• 活动记录的内容
– 连接数据:
• RA:返回地址 • DL:动态链 • SL:静态链
– 局部变量数据区 – 临时单元
• 活动记录存储区指示器
1
PL/0语言程序实例
• • • • • • • • • • Test1.pl0 Test2.pl0 Test3.pl0 Test4.pl0 Test5.pl0 Test6.pl0 Test7.pl0 Test8.pl0 Test9.pl0 Test.pl0 : 最简单的PL/0程序 : 用while语句求累加和 :含有“过程”子程序 :定义全局量、“过程”中的局部量 :用同一标识符定义全局量和局部量 : 递归调用计算n! :“过程”嵌套,全局量和局部量为同一标识符 :多个过程嵌套或并列 : 定义全局常量和变量、局部常量和变量 :I/O语句中使用多个变量

PL0编译程序的实现

PL0编译程序的实现
【学习目标】 本章目的:以PL/0语言编译程序为实例,学习编
译程序实现的基本步骤和相关技术,对编译程序的 构造和实现得到一些感性认识和建立起整体概念, 为后面的原理学习打下基础。
◇ 了解并掌握用语法图和扩充的巴科斯-瑙尔 范式(EBNF)对计算机语言的形式描述。
【难 重 点】 重点: ◇ 弄清源语言(PL/0)目标语言(类 pcode)实现
2. V集n合是N一on个-te非rm空in有als穷,集且合V,t称Vn作= 非。终结符号 3. S Vn ,称作开始符号Start Symbol 。 4. P是一个非空有穷集合,称为产生式集合
Production Rules ,每条产生式形为A,其22 中AV ,(V V )*。
例2.1 简单的算术表达式
17
Bakus-Naur范式(BNF)
18
Examples of BNF
19
Syntax Graph
20
2.2 语法定义
❖ 语法描述程序设计语言的层次结构,如C语言 的条件语句为
if_stmt if (expr) stmt else stmt if_stmt if (expr) stmt
string
string + string
string - string 2
9
5
string
string - string
9 string + string
5
2
对某个文法,如一个句子有两棵以上的分析树,称为
二义(歧义)文法。
29
2.2.3 Associativity of Operators
❖ 可以用括号来表明计算顺序,如 9-5+2 = (9-5)+2

cha2 PL0编译程序的实现(补充)

cha2 PL0编译程序的实现(补充)

写操作 调用返回
22
PL/0程序如下:
BEGIN b:=8; READ( c ); WHILE c>0 DO BEGIN WRITE(b); CALL s; b:=b+c; WRITE(b); READ( c ); END; CALL p END.
52 53 54 55 56 57 58 59 60 61 62 63 64 INT LIT STO OPR STO LOD LIT OPR JPC LOD OPR OPR CAL 0 0 0 0 0 0 0 0 0 0 0 0 0
7
8条伪代码的指令
OPR:关系或算数运算; L:0; A:具体运算(0~6,8~13),运算 对象取自S栈栈顶和次栈顶;
8
8条伪代码的指令
OPR,0,0 OPR,0,1 OPR,0,2 OPR,0,3 OPR,0,4 OPR,0,5 OPR,0,6

调用返回; 取“负”运算; 加法运算; 减法运算; 乘法运算; 除法运算; 取奇运算;
17
伪代码的生成顺序
(8)为主程序main产生目标代码程序块, 其入口地址为L: L:INT 0 A1(主程序main所需单元个数) …… OPR 0 0
18
伪代码的生成顺序
JMP 0 L JMP 0 L1 JMP 0 L2 JMP 0 L3 L3:过程P3目标程序代码 L2:过程P2目标程序代码 L1:过程P1目标程序代码 L:主程序main目标程序代码
21
PL/0程序如下:
BEGIN d:=a+b; WRITE(d); CALL q END; PROCEDURE s; BEGIN CALL p; b:=-10; WRITE(b) END;

PL000编译程序

PL000编译程序

第二章 编译程序的实现
26
2、PL/0语法规则的BNF表示
<写语句>::= WRITE(<表达式>{, <表达式>}) <写语句>举例: WRITE( a+b,b*c);
第二章 编译程序的实现
27
2、PL/0语法规则的BNF表示
<过程调用语句>::=CALL <标识符>; <过程调用语句>举例:
第二章 编译程序的实现
30
2、PL/0语法规则的BNF表示
<因子>::=
<标识符>|<常量>|(<表达式>)
PROCEDURE FACTOR P294~P295
第二章 编译程序的实现
31
2、PL/0语法规则的BNF表示
<项>::=
<因子>|<项> <乘法运算符><因子>
<乘法运算符>::=*|/
第二章 编译程序的实现 38
符号表的内容
标识符名:NAME
类型:KIND ①CONSTANT(常量)
②VARIABLE(变量) ③PROCEDURE(过程) 值或层次:VAL或LEVEL 地址:ADR 大小:SIZE
第二章 编译程序的实现 39
地址:ADR
地址:ADR 简单变量或常量:该量在数据区所占单元 的绝对地址或相对地址;
(PROGRAM PROGSYM),(mysource IDENT) , (CONST CONSTSYM) , (a IDENT) , (= EQL) , (10 NUMBER) , (; SEMICOLON) , (VAR VARSYM) , (b IDENT) , (, COMMA) , (c IDENT) , (; SEMICOLON) , (PROCEDURE PROCSYM) , …… (g IDENT) , (:= BECOMES) , (a IDENT) , (+ PLUS) , (e IDENT) , (; SEMICOLON) This is a assign Statement;(赋值语句) (f IDENT) , (:= BECOMES) , (g IDENT) , (; SEMICOLON) This is a assign Statement; (赋值语句) (WRITE WRITESYM) , (( LPAREN) , (g IDENT) , ( ) RPAREN) , (; SEMICOLON) This is a write Statement;(写语句) ……

第2章 PL0编译程序

第2章 PL0编译程序

n. <表达式>::=[十|一]<项> {<加法运算符><项>} o. <项>::=<因子>{<乘法运算符><因子>} p.<因子>::=<标识符>|<无符号整数>|<表达式> q. <加法运算符>::=十|一
2007年9月12日星期二5时12分32秒
共147页, Page19
q. <加法运算符>::=十|一 r.<乘法运算符>::=*|/ s.<关系运算符>::==|#|<|<=|>|>= t.<条件语句}::=IF<条件>THEN<语句> u.<过程调用语句>::=call<标识符>
共147页, Page28
启动 置初值 PLO编译程序总体流程 Call getsym取单词
Call block
当前单词是否 为源程序结束符‘.’?
N
出错 打印错误
Y
源程序是否有错误‘.’?
Y
N Call Interpret 解译执行目标程序
结束
2007年9月12日星期二5时12分32秒 共147页, Page29
2007年9月12日星期二5时12分32秒 共147页, Page22
PL/0编译程序的结构
PL/0源程序 表 格 管 理 程 序 词法分析程序 语法分析程序 代码程序 出 错 处 理 程 序
共147页, Page23
目标程序
2007年9月12日星期二5时12分32秒
PL/0编译程序的子程序
PI/0编程序是用PASCAL语言书写,整个编译程序 (包括主程序) 是由18个嵌套及并列的过程或函数 组成.下面分别简要给出这些函数功能及它们的层 次结构。

第2章 PL0编译程序的实现(4学时)

第2章 PL0编译程序的实现(4学时)
13 13
表格管理举例
CONST A=35,B=49; VAR C,D,E; PROCEDURE P; VAR G
名字
TX0 NAME:A
类型
层次/值
地址
存储空间
NAME:B NAME:C NAME:D NAME:E NAME:P TX1 NAME:G ……
KIND:CONSTANT KIND:CONSTANT KIND:VARIABLE KIND:VARIABLE KIND:VARIABLE KIND:PROCEDUR KIND:VARIABLE ……
何为PL/0语言?
PL/0语言: PASCAL语言的子集,功 能简单,结构清晰,可 读性强,具备了一般高 级语言的必备部分。
PL/0程序示例: CONST A=10; VAR B,C; PROCEDURE P; VAR D; PROCEDURE Q; VAR X; BEGIN READ(X); D:=X; WHILE X#0 DO CALL P; END; BEGIN WRITE(D); CALL Q; END; BEGIN CALL P; END.
存储空间
SIZE:4
ADR:DX SIZE:4 SIZE:5 ADR:DX ADR:DX ADR:DX+1 SIZE:5 ADR:DX ADR:DX+1
15 15
2.5 PL/0编译程序的目标代码结构和代码生成
• 目标代码pcode是一种假想栈式计算机的汇编语言。
• 指令格式 功能码
f l
a
层次差 通常为“位移量” 根据不同的指令 有所不同
18
Const a=10; var b,c; procedure p; begin c:=b+a; end; begin read(b); call p; write(c); end.

PL0语言编译器的设计与实现

PL0语言编译器的设计与实现

PL0语⾔编译器的设计与实现⼀、设计任务1.1程序实现要求PL/0语⾔可以看成PASCAL语⾔的⼦集,它的编译程序是⼀个编译解释执⾏系统。

PL/0的⽬标程序为假想栈式计算机的汇编语⾔,与具体计算机⽆关。

PL/0的编译程序和⽬标程序的解释执⾏程序都是⽤JAVA语⾔书写的,因此PL/0语⾔可在配备JDK的任何机器上实现。

其编译过程采⽤⼀趟扫描⽅式,以语法分析程序为核⼼,词法分析和代码⽣成程序都作为⼀个独⽴的过程,当语法分析需要读单词时就调⽤词法分析程序,⽽当语法分析正确需要⽣成相应的⽬标代码时,则调⽤代码⽣成程序。

⽤表格管理程序建⽴变量、常量和过程标⽰符的说明与引⽤之间的信息联系。

⽤出错处理程序对词法和语法分析遇到的错误给出在源程序中出错的位置和错误性质。

当源程序编译正确时,PL/0编译程序⾃动调⽤解释执⾏程序,对⽬标代码进⾏解释执⾏,并按⽤户程序的要求输⼊数据和输出运⾏结果。

1.2 PL/0语⾔的BNF描述(扩充的巴克斯范式表⽰法)<prog> → program <id>;<block><block> → [<condecl>][<vardecl>][<proc>]<body><condecl> → const <const>{,<const>};<const> → <id>:=<integer><vardecl> → var <id>{,<id>};<proc> → procedure <id>([<id>{,<id>}]);<block>{;<proc>}<body> → begin <statement>{;<statement>}end<statement> → <id> := <exp>|if <lexp> then <statement>[else <statement>]|while <lexp> do <statement>|call <id>([<exp>{,<exp>}])|<body>|read (<id>{,<id>})|write (<exp>{,<exp>})<lexp> → <exp> <lop> <exp>|odd <exp><exp> → [+|-]<term>{<aop><term>}<term> → <factor>{<mop><factor>}<factor>→<id>|<integer>|(<exp>)<lop> → =|<>|<|<=|>|>=<aop> → +|-<mop> → *|/<id> → l{l|d} (注:l表⽰字母)<integer> → d{d}注释:<prog>:程序;<block>:块、程序体;<condecl>:常量说明;<const>:常量;<vardecl>:变量说明;<proc>:分程序; <body>:复合语句;<statement>:语句;<exp>:表达式;<lexp>:条件;<term>:项; <factor>:因⼦;<aop>:加法运算符;<mop>:乘法运算符; <lop>:关系运算符。

chPL编译程序的实现

chPL编译程序的实现
end;
begin read(n); call rec;
end. 8
计算 sum = 1! + 2 ! + ... + n!,
n从控制台读入
begin
{ 读入n }
var n, m, fact, sum;
read(n); sum := 0;
{ 递规计算 fact = m! }
while n > 0 do
24
通过三个全程量 SYM 、ID和NUM 将识别出的单词信息传递给 语法分析程序。
SYM:存放单词的类别
如:有程序段落为:
begin initial := 60;end
对应单词翻译后变为:
begin beginsym, initial ident,
‘:= ‘ becomes, 60 number, ‘;’ semicolon,
保留字表:( begin (* main * ) )
word[1]:=‘begin
‘;word[2]:=‘call ‘;
...
word[13]:=‘write
‘;
查到时找到相应的内部表示
Wsym[1]:=beginsym; wsym[2]:=callsym;

wsym[13]:=writesym;
23
(18) opr 0 4 次栈顶与栈顶相乘(2*c)
(19) opr 0 14 栈顶值输出至屏幕 (20) opr 0 15 换行 (21) opr 0 16 从命令行读取值到栈顶 (22) sto 0 3 栈顶值送变量b中 (23) jmp 0 11 无条件转到循环入口(11) (24) opr 0 0 结束退栈
19
第2章 PL/0编译程序
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

{ } :花括号表示其内的语法成分可以重复。在不
加上下界时可重复0到任意次数,有上下界时为可
重复次数的限制。
6
如:{*}表示*重复任意次,{*}38表示*重复3-8次。 [ ] :方括号表示其内的成分为任选项。 ( ) :表示圆括号内的成分优先。
例:用EBNF描述<整数>文法的定义 : <整数>∷=[+|-]<数字>{<数字>} <数字>∷=0|1|2|3|4|5|6|7|8|9 或更好的写法 <整数>∷=[+|-]<非零数字>{<数字>} <非零数字>∷=1|2|3|4|5|6|7|8|9 <数字>∷=0|<非零数字>
识符〉}; 〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉} 〈过程说明部分〉∷=〈过程首部〉〈分程序〉
{;〈过程说明部分〉};
8
〈过程首部〉∷=PROCEDURE〈标识符〉
〈语句〉∷=〈赋值语句〉 |〈条件语句〉|
〈当型循环语句〉|〈过程调用语句〉|〈读语句〉|
〈写语句〉|〈复合语句〉|〈空〉
〈赋值语句〉∷=〈标识符〉∶=〈表达式〉
语言(pascal) 这3个语言之间的关系和作用。 ◇ 掌握用语法图和扩充的巴科斯-瑙尔范式
(EBNF)对一个高级程序设计语言的语法形式描述。 1
本节讲3个内容。 一、对PL/0语言编译程序的功能用“T”型图表 示,从而弄清源语言(PL/0)、目标语言(类 pcode)和 实现语言(pascal) 这3个语言之间的关系和作 用。 。
11
汉语句子可以是由主语后随谓语而成,构成谓 语的是动词和直接宾语,我们采用EBNF来表示汉 语句子的构成规则
〈句子〉∷=〈主语〉〈谓语〉 〈主语〉∷=〈代词〉|〈名词〉 〈代词〉∷= 我 | 你 | 他 〈名词〉∷= 王明 | 大学生 | 工人 | 英语 〈谓语〉∷=〈动词〉〈直接宾语〉 〈动词〉∷= 是 | 学习 〈直接宾语〉∷=〈代词〉|〈名词〉
〈读语句〉∷=READ'('〈标识符〉{,〈标识 符〉}')'
〈写语句〉∷=WRITE'('〈表达式〉{,〈表达 式〉}')'
〈字母〉∷=a|b|…|X|Y|Z 〈数字〉∷=0|1|2|…|8|9
10
三、3种方法的比较与总结:
1、用语法图描述语言的语法与EBNF描述相比较: 语法图描述: 直观,易读,易写。 EBNF表示:形式化强,易机器识别。
作业:P31第6题的2,3小题。 13
第二章 简单的一遍编译器
A Simple One Pass Compiler
14
本章主要内容
❖ 用C语言开发一个把中缀表达式转换为后缀 表达式的翻译程序,展示基本的编译技术
2、语法图或EBNF作为描述程序设计语言语法的工 具,那么,问题是能不能让机器掌握这些工具,从 而让机器自动检查哪些符号序列是所给语言的合理 程序。答案是: EBNF 方法的最大好处就是容易在 机器上实现。
3、下面我们用EBNF给出自然语言汉语的构成规则, 并且用这些规则检查一句话是不是正确的汉语:
【学习目标】 本章目的:以PL/0语言编译程序为实例,学习编
译程序实现的基本步骤和相关技术,对编译程序的 构造和实现得到一些感性认识和建立起整体概念, 为后面的原理学习打下基础。
◇ 了解并掌握用语法图和扩充的巴科斯-瑙尔 范式(EBNF)对计算机语言的形式描述。
【难 重 点】 重点: ◇ 弄清源语言(PL/0)目标语言(类 pcode)实现
〈复合语句〉∷=BEGIN〈语句〉{;〈语
句〉}END
〈条件〉∷=〈表达式〉 〈关系运算符〉
〈表达式〉|ODD〈表达式〉
〈表达式〉∷=[+|-]〈项〉{〈加法运算符〉
〈项〉}
〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}
〈因子〉∷=〈标识符〉|〈无符号整数〉|'('
〈表达式〉')'
9
〈加法运算符〉∷=+|〈乘法运算符〉∷=*|/ 〈关系运算符〉∷=#|=|<|<=|>|>= 〈条件语句〉∷=IF〈条件〉THEN〈语句〉 〈过程调用语句〉∷=CALL〈标识符〉 〈当型循环语句〉∷=WHILE〈条件〉DO〈语 句〉
7
PL/0语言文法的EBNF表示为: 〈程序〉∷=〈分程序〉. 〈分程序〉∷=[〈常量说明部分〉][〈变量说
明部分〉][〈过程说明部分〉]〈语句〉 〈常量说明部分〉∷=CONST〈常量定义〉 {,
〈常量定义〉}; 〈常量定义〉∷=〈标识符〉=〈无符号整数〉 〈无符号整数〉∷=〈数字〉{〈数字〉} 〈变量说明部分〉∷=VAR〈标识符〉{,〈标
麦的Peter Naur命名的。EBNF表示扩充的巴科斯-
瑙尔范式。
(EBNF) 给出程序设计语言的语法描述用了6个符
号,它们是:
〈 〉:用左右尖括号括起来的中文字表示语法构
造成分,或称语法单位,是非终结符。
∷= :该符号的左部由右部定义,可读作'定义为'。
| :表示'或',为左部可由多个右部定义。
2
二、程序设计语言的语法规则(词法和语法) 的描述方法有3种。
1、是用自然语言描述;
2、是用语法图描述;用语法图描述首先把语法 符号分为二种,终结符和非终结符。
所谓终结符,是构成语言的语法成分的最小单位, 终结符不能由其它文法符号定义。在语法图中用椭 圆和圆圈中的英文字表示终结符。
所谓非终结符,是可由其它文法符号定义语法成 分。在语法图中用长方形内的中文字表示非终结符。 箭头表示该语法成分由旦有了一组规则以后,我们可以按照如下方 式用它们去推导或产生句子。我们开始去找∷=左端 的带有〈句子〉的规则并把它表示成∷=右端的符号 串,重复做下去。例如我们导出句子“我是大学生” 是一句正确的汉语的过程是:
〈句子〉=》〈主语〉〈谓语〉 =》〈代词〉〈谓语〉 =》我〈谓语〉 =》 我〈动词〉〈直接宾语〉 =》我 是〈直接宾语〉 =》 我 是〈名词〉 =》我 是 大学生
3
用语法图描述语法规则的优点是直观、易读。
例如在 PL/0语言中程序是由非终结符‘分程序’ 和终结符“.”组成的串定义的。所以程序的语法图 可以用下图表示:
4
分程序的语法图如下:
5
3、 用扩充的巴科斯-瑙尔范式 (EBNF) 给出程序设
计语言的语法描述。巴科斯-瑙尔范式(BACKUS-
NAUR FORM)是根据美国的John W.Backus与丹
相关文档
最新文档