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;
步骤3
PL/0编译程序词法分析的 设计与实现
查到时找到关键字相应的内部表示 wsym[1]:=beginsym; wsym[2]:=callsym; … wsym[13]:=writesym; 字符对应的单词表: ssym[‘+’]:=plus; ssym[‘-’]:=minus; … ssym[‘;’]:=semicolon;
步骤2
PL/0编译程序的总体设计
PL/0源程序 词法分析程 序 语法语义分析程序
表格管理程序
出错处理程序
代码生成程序
目标程序
步骤2
PL/0编译程序的总体设计
其编译过程采用一趟扫描方式 以语法、语义分析程序为核心 词法分析程序和代码生成程序都作为一个独立 的过程,当语法分析需要读单词时就调用词法 分析程序,而当语法、语义分析正确,需要生 成相应的目标代码时,则调用代码生成程序。
第2 章
PL/0编译程序的实现
本章目的:以PL/0语言的编译程序为实例,学习 一个编译程序实现的基本步骤和相关技术
“PL/0语言的编译程序”是世界著名计算机科 学家N.Wirth先生编写的。由于PL/0语言功能简单 、 结构清晰、可读性强,又具备了一般高级语言 的必须部分,因而PL/0语言的编译程序能充分体 现一个高级语言编译程序实现的基本技术和步骤 ,是一个非常合适的编译程序教学模型。
步骤3
PL/0编译程序词法分析的 设计与实现
通过三个全程量 SYM 、ID和NUM 将识别出的单 词信息传递给语法分析程序。
SYM:存放单词的类别 如:begin
→
beginsym, initial
→
ident,
60 → number ID: 存放用户所定义的标识符的值 如: initial (在SYM中放ident,在ID中放initial) NUM:存放用户定义的数 如:60 (在SYM中放number,在NUM中放60)
RA DL SL
每个过程被调用时 分配一段数据空间, 变量的位置从3开 始(每个变量占用 一个单元)。运行结 束释放该数据空间
步骤1 PL/0程序到类pcode代码的映射
下面给出 PL/0程序到类pcode代码的映射。 (编译过程是按源程序顺序进行分析的) (常量、变量的说明部分不产生目标代码)
const a=10; var b,c; procedure p; begin c:=b+a; end; begin read(b); while b#0 do begin call p; write(2*c); read(b); end end.
步骤2
PL/0编译程序的总体设计
表格管理程序:建立变量,常量和过程标识符的 说明与引用之间的信息联系。 出错处理程序:对词法和语法、语义分析遇到的 错误给出在源程序中出错的位置和错误性质。 下面将介绍某些部分实现的关键技术。
步骤3
PL/0编译程:GETSYM框图(见教材15页图2.5) 程序文本(见教材290-292页) 当识别到标识符时先查关键字表(关键字表是按 第1个字母的大小顺序排列的,用二分法查找) 关键字表:(见教材304页主程序) word[1]:=‘begin ‘;word[2]:=‘call ‘; ... word[13]:=‘write ‘;
0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8 2 3 3 10 2 4 0 5 16 3 3 0 9 24 2 2 4 4 14 15 16 3 11 0
转向主程序入口 转向过程p入口 过程p入口,为过程p开辟空间 取变量b的值到栈顶 取常数10到栈顶 次栈顶值与栈顶值相加 栈顶值送变量c中 退栈并返回调用点(16) 主程序入口开辟5个栈空间 从命令行读入输入值置于栈顶 将栈顶值存入变量b中 将变量b的值取至栈顶 将常数值0取至栈顶 次栈顶值与栈顶值是否不等 等时转(24)(条件不满足转) 调用过程p 常数值2取至栈顶 将变量c的值取至栈顶 次栈顶值与栈顶值相乘(2*c) 栈顶值输出至屏幕 换行 从命令行读取输入值到栈顶 栈顶值送变量b中 无条件转到循环入口(11) 结束退栈
合集下载

标准实验报告(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源程序-编译原理实验代码

附件1 小组成员:程序清单#include<>#include<>#include<>void error(int n);void getsym();"。

\n");break;case 10:printf("语句之间漏了\";\"。

\n");break;case 11:printf("标识符未说明。

\n");break;case 12:printf("赋值语句中,赋值号左部标识符属性应是变量。

\n"); break;case 13:printf("赋值语句左部标识符后应是赋值号\":=\"。

\n");break;case 14:printf("call后应为标识符。

\n");break;case 15:printf("call后标识符属性应为过程。

\n");break;case 16:printf("条件语句中丢了\"then\"。

\n");break;case 17:printf("丢了\"end\"或\";\"。

\n");break;case 18:printf("while型循环语句中丢了\"do\"。

\n");break;case 19:printf("语句后的符号不正确。

\n");break;case 20:printf("应为关系运算符。

\n");break;case 21:printf("表达式内标识符属性不能是过程。

\n");break;case 22:printf("表达式中漏掉右括号\")\"。

第二章 PL0编译程序的实现 (上)

第二章 PL0编译程序的实现 (上)

2.1
PL/0 语言描述
2.1.1 PL/0语言的语法描述图 下面借用语法图来描述语法规则。其中: 英文表示终结符,中文表示非终结符。 终结符:构成语言文法的单词,是语法成分 的最小单位。 非终结符:是个语法成分,还没有进行分析。 程 序
分 程 序
语 句
条ቤተ መጻሕፍቲ ባይዱ:
表 达 式
项
因子:
2.12 PL/0 语言文法的EBNF表示
单词的种类有五种:
1. 基本字:也称保留字,如END、IF等
2. 运算符:如+、—、*、/、> =、# 等等
3. 标识符:用户定义的变量名、常数名、 过程名 4. 常数:如100等整数
5. 界符:如‘,’、‘.’、‘(’‘;’ 等
词法分析程序完成下列任务: 1.滤空格:语法分析时没用 2.识别保留字:对应的类别放在SYM中,若查不到, 认为是用户定义的标识符 3.识别标识符:对用户定义的标识符放在SMY中, 标识符本身的值放在ID中 4.拼数:所取单词是数字时,将数的类别放在SYM 中,数值本身的值存放在NUM中 5.拼复合词:对两个字符组成的算符进行识别(<=) 6.输出源程序:边读入字符边输出
源程序
表 格 管 理 程 序
词法分析程序 语法分析程序
代码生成程序
出 错 处 理 程 序
目标程序
PL/0编译程序的过程或 函数的功能表见表2.1
过程或函数的嵌套定 义层次结构如图2.3 所示
语法分析程序
图2.4 PL/0编译程序总体流程图
2.3 PL/0编译程序的词法分析
词法分析程序是为语法分析提供单词用 的,是语法分析的基础。它把输入的字 符串形式的源程序分割成一个个单词符 号。编译器为此设置了3个全程量的公用 单元为: SYM:存放每个单词的类别 ID:存放用户所定义的标识符的值 NUM:存放用户定义的数

编译原理实验:PL0语言及其实现

编译原理实验:PL0语言及其实现

课程实践项目一、PL/0语言的扩展1、课程实践要完成下列要求(1)给PL/0语言增加像C语言那样的形式为/*……*/的注释。

(2)给PL/0语言增加带else子句的条件语句和exit语句。

(3)给PL/0语言增加输入输出语句。

(4)给PL/0语言增加带参数的过程。

(5)给PL/0语言增加布尔类型。

(6)给PL/0语言增加数组类型。

(7)给PL/0语言增加函数类型。

(8)给PL/0语言增加实数类型。

(9)分离解释器和编译器为两个独立的程序。

2、扩展后的PL/0语言的语法Program →Block .Block →[ConstDecl][TypeDecl][VarDecl][FuncDecl] StmtConstDecl →const ConstDef {, ConstDef} ;ConstDef →ident = numberTypeDecl →type TypeDef ; {TypeDef ;}TypeDef →ident = TypeExpTypeExp →integer | real | Boolean | array‘[’number .. number‘]’of TypeExpVarDecl →var VarDecl ; {VarDecl ;}VarDec →ident {, ident} : TypeType →integer | real | Boolean | identFuncDecl →FuncDec { FuncDec }FuncDec→procedure ident [ ( ForParal ) ]; Block ; |function ident [ ( ForParal ) ] : Type ; Block ;ForParal →ident : Type {; ident : Type }Stmt →IdentRef := Exp | if Exp then Stmt | if Exp then Stmt else Stmt |begin Stmt {; Stmt } end | while Exp do Stmt | exit | ε |call ident [ ( ActParal ) ] | write ( Exp [, Exp ] ) |read (IdentRef [, IdentRef ] )IdentRef →ident [ ‘[’Exp‘]’ { ‘[’Exp‘]’ } ]ActParal →Exp {, Exp }Exp →odd SimpExp | SimpExp RelOp SimpExpRelOp →= | <> | < | > | <= | >=SimpExp →[+ | - ] Term {+ Term | - Term | or Term}Term →Factor {* Factor | / Factor | div Factor | mod Factor | and Factor}Factor →IdentRef | number | ( Exp ) | not Factor | ident [ ( ActParal ) ] |true | false有关该扩展的说明如下:(1)描述语言的部分符号的解释符号→、|、[、]、{和}是描述语言的符号,其中方括号[…]中的部分可以出现0次或1次,花括号{…}中的部分可以出现任意次数,包括0次。

第2章 PL0编译程序的实现

第2章 PL0编译程序的实现
第2章 PL/0编译程序的实现
1
2. 1 PL/0语言描述
终结符和非终结符 ➢ 终结符是最小的语法单位,例如构成文法的单词。 ➢ 非终结符是一个语法单位,它可以由其他一些语法单位组 成,即可以由其他一些终结符和非终结符串、或终结符串 组成。
PL/0语言的语法描述图 ➢ 用圆圈表示终结符 ➢ 用长方形表示非终结符
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,每次将
常量说明部分
变量说明部分 过程说明部分
语句
<分程序>::=[<常量说明部分>][<变量说明部分>][<过程说明部分>]<语句>
9
由语法描述图转化到BNF范式
常量定义
<常量说明部分>::=CONST<常量定义>{,<常量定义>}; <常量定义>::=<标识符>=<无符号整数> <无符号整数>::=<数字>{<数字>}
a+2(x+10)是不是表达式?
6
BNF范式
BNF(Backus Normal Form)范式表示
< > 用左右尖括号括起来的中文字表示待描述的语法 成分<语法单位>,为非终结符

第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编译程序的实现

(4)当源程序编译正确时, PL/0编译程序自动调用 解释执行程序,对目标代码进行解释执行。
出错处理程序 表格管理程序
2. PL/0编译程序的结构 PL/0源程序 词法分析程 序
语法语义分析程序
代码生成程序
目标程序
PL/0编译系统的结构框架
PL/0源程序
PL/0编译程序
目标代码
解释执行程序
输入
wsym[6]=(symbol)oddsym;
wsym[7]=(symbol)procsym;
wsym[8]=(symbol)readsym;
wsym[9]=(symbol)thensym;
wsym[10]=(symbol)varsym;
wsym[11]=(symbol)whilesym;
wsym[12]=(symbol)writesym;
}‘)’
❖<写语句> ::= WRITE’(’<表达式>{,<表达式> }‘)’
❖<字母> ::= a|b|…|X|Y|Z ❖<数字> ::= 0|1|…|8|9
2.2 PL/0编译程序的结构
PL/0的目标程序为假想栈式计算机的汇编语言,与计算机 无关
PL/0的编译程序和目标程序的解释执行程序可用各种语言 编写。
❖<表达式> ::=[+|-]<项>{<加法运算符>< 项>}
❖<项> ::= <因子>{<乘法运算符><因子>} ❖<因子> ::= <标识符>|<无符号整数>|‘(’<
表达式>‘)’
❖<加法运算符> ::= +|- ❖<乘法运算符> ::= *|/ ❖<关系运算符> ::= =|#|<|<=|>|>= ❖<条件语句> ::= IF<条件>THEN<语句> ❖<过程调用语句> ::= CALL<标识符> ❖<当型循环语句> ::= WHILE<条件>DO<语句> ❖<读语句> ::= READ’(’<标识符>{,<标识符>

PL0编译程序的实现-教案

20
PL/0编译程序的工作过程
• 采用一趟扫描方式 • 以语法分析程序为核心 词法分析程序和代码生成程序都作为一个独立的 过程,当语法分析需要读单词时就调用词法分析 程序,而当语法分析正确需要生成相应的目标代 码时,则调用代码生成程序。 • 用表格管理程序建立变量,常量和过程标识符的 说明与引用之间的信息联系。 • 用出错处理程序对词法和语法分析遇到的错误给 出在源程序中出错的位置和错误性质。
• 生成宿主机上可执行的PL/0编译程序
– 应用宿主机上的PASCAL语言系统 – 将 PL0.PAS 转换成 PL0.exe
• 目标机上可执行的PL/0编译程序:
PL0.exe
4
PL/0语言程序的编译、运行
PL/0语言程序的编译
PL/0编译:Pl0.exe PL/0源程序

假想机器语言程序
假想机器语言程序的解释执行
26
0 jmp 0 8 1 jmp 0 2 2 int 0 3 3 lod 1 3 4 lit 0 10 5 opr 0 2 6 sto 1 4 7 opr 0 0 8 int 0 5 9 opr 0 16 10 sto 0 3 11 cal 0 2 12 lod 0 4 13 opr 0 14 14 opr 0 15 15 opr 0 0
址
7
PL/0目标机指令系统
PL/0假想机器指令系统
– 共有8大值” a PL/0目标语言程序的“执行”实现原理 功能码 f 层次差 l
PL/0解释模块将目标语言转换为等价的PASCAL语句。 PL/0解释模块执行时,将目标语言指令解释成PASCAL
次栈顶与栈顶相加
Const a=10; var b,c; procedure p; begin c:=b+a; end; begin read(b); call p; write(c); end.

第二章 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语言编译程序文本时,应从整体 结构开始逐步细化,弄清楚每个过程的功能和实现 方法及过程之间的相互关系。

(完整word版)PL0源程序-编译原理实验代码

附件1 小组成员:程序清单Main.c#include<stdio.h>#include<stdlib.h>#include<string.h>void error(int n);void getsym();//void enter(enum object k,int *ptx,int lev,int *pdx);int position(char*idt,int tx);int constdeclaration(int *ptx,int lev,int *pdx);int vardeclaration(int *ptx,int lev,int *pdx);int factor(int*ptx,int lev);int term(int *ptx,int lev);int expression(int *ptx,int lev);int statement(int *ptx,int lev);int block();enum object{constant,variable,procedure};struct tab{char name[14];enum object kind;int val;int level;int adr;int size;}table[100];enum symbol{nul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss,leq,gtr,geq,lparen,r paren,comma,semicolon,period,becomes,beginsym,endsym,ifsym,thensym,whilesym,writesym,readsym,dosym,ca llsym,constsym,varsym,procsym,progsym,};enum symbol sym=nul;enum symbol mulop;enum symbol wsym[14];enum symbol ssym[256];char ch=' ';char *str;charword[14][10]={"begin","call","const","do","end","if","odd","procedure","program ","read","then","var","while","write"};//设置保留字名字int num;int lev=0;int tx=0;int k;int *mm;//=(int *)malloc(sizeof(int));char *id,sign[14];char a[14];FILE *fp1,*fp2,*fp3;void error(int n){switch(n){case 1:printf("常数说明中的\"=\"写成了\":=\"。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档