陈泳鑫 310006379 编译原理实验报告.docx
- 文档编号:18190555
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:25
- 大小:167.24KB
陈泳鑫 310006379 编译原理实验报告.docx
《陈泳鑫 310006379 编译原理实验报告.docx》由会员分享,可在线阅读,更多相关《陈泳鑫 310006379 编译原理实验报告.docx(25页珍藏版)》请在冰点文库上搜索。
陈泳鑫310006379编译原理实验报告
编译原理实验
题目____PL/0编译器_______
学院计算机学院
专业软件工程
年级班别10级4班
学号3110006379
学生姓名陈泳鑫
指导教师杨劲涛
答辩
程序设计
报告撰写
平时
总成绩
2013年1月3日
一、课内实验的内容
对PL/0作以下修改扩充:
(1)增加单词:
保留字ELSE,FOR,TO,DOWNTO,RETURN
运算符*=,/=,++,--,&,||,!
(2)修改单词:
不等号#改为<>
(3)增加条件语句的ELSE子句,要求:
写出相关文法,语法图,语义规则。
二、实验修改部分:
1、增加四个保留字和七个运算符,共十一个单词。
修改部分:
#definesymnum43//保留字从32增加到43个
2、增加五个保留字:
ELSE,FOR,STEP,RETURN
头文件pl0.h
enumsymbol{新增加单词:
elsesym,forsym,stepsym,returnsym,pluseq/*+=*/,plusone/*++*/,plus/*+*/,minuseq/*-=*/,minusone/*--*/,minus/*-*/,and,or,not}
头文件pl0.h
#definenorw24//关键字从13增加到24个
main.cpp
init();
新增加:
(增加后数组的内容要再次根据字母顺序重新排列)
strcpy(&(word[0][0]),"begin");
strcpy(&(word[1][0]),"call");
strcpy(&(word[2][0]),"const");
strcpy(&(word[3][0]),"do");
strcpy(&(word[4][0]),"else");/*增加单词:
保留字else*/
strcpy(&(word[5][0]),"end");
strcpy(&(word[6][0]),"for");/*增加单词:
保留字for*/
strcpy(&(word[7][0]),"if");
strcpy(&(word[8][0]),"odd");
strcpy(&(word[9][0]),"procedure");
strcpy(&(word[10][0]),"read");
strcpy(&(word[11][0]),"return");/*增加单词:
保留字return*/
strcpy(&(word[12][0]),"step");/*增加单词:
保留字step*/
strcpy(&(word[13][0]),"then");
strcpy(&(word[14][0]),"while");
strcpy(&(word[15][0]),"write");
wsym[0]=beginsym;
wsym[1]=callsym;
wsym[2]=constsym;
wsym[3]=dosym;
wsym[4]=elsesym;/*else*/
wsym[5]=endsym;
wsym[6]=forsym;/*for*/
wsym[7]=ifsym;
wsym[8]=oddsym;
wsym[9]=procsym;
wsym[10]=readsym;
wsym[11]=returnsym;/*return*/
wsym[12]=stepsym;/*step*/
wsym[13]=thensym;
wsym[14]=whilesym;
wsym[15]=writesym;
3、增加四个运算符:
+=,-=,++,--,∧,∨,┓
●PL0.cpp
getsym();
增加对+,-,++,--,+=,-=的识别;
Statement();
增加对+,-,++,--,-=的语句的处理;
Init()中改动:
ssym[‘&’]=and;
ssym[‘|’]=or;
ssym[‘~’]=not;
facbegsys[plusone]=true;//添加前自加运算
facbegsys[minusone]=true;//添加前自减运算
Getsym()增加的内容:
intgetsym()
{
inti,j,k;
while(ch==''||ch==10||ch==9)
{
getchdo;
}
if(ch>='a'&&ch<='z')
{
k=0;
do{
if(k { 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; } } elseif(ch=='>')/*检测大于或大于等于符号*/ { getchdo; if(ch=='=') { sym=geq; getchdo; } else { sym=gtr; } } /*这里之间为添加的内容*/ elseif(ch=='+'){/*检测+,+=,++符号*/ getchdo; if(ch=='='){ sym=pluseq; getchdo; }else if(ch=='+'){ sym=plusone; getchdo; }else{ sym=plus; } }elseif(ch=='-'){/*检测-,-=,--符号*/ getchdo; if(ch=='=') { sym=minuseq; getchdo; } elseif(ch=='-') { sym=minusone; getchdo; } else { sym=minus; } } /*这里之间为添加的内容*/ else{ sym=ssym[ch];/*当符号不满足上述条件时,全部按照单字符号处理*/ //getchdo; //richard if(sym! =period) { getchdo; } //endrichard } } } } return0; } Statement()增加的内容: (将本来“if(sym==becomes)……”部分的内容修改为处理++,+=,--,-=),并在Statement()中定义变量intsym2; if(sym==becomes||sym==pluseq||sym==minuseq|| sym==plusone||sym==minusone) { sym2=sym; getsymdo; gendo(lod,lev-table[i].level,table[i].adr); } else { error(13); } if(sym2==plusone||sym2==minusone)/*准备按照a++、a--语句处理,与read类似*/ { if(i! =0) { if(sym2==plusone) { gendo(lit,0,1); gendo(opr,0,2); gendo(sto,lev-table[i].level,table[i].adr); } if(sym2==minusone) { gendo(lit,0,1); gendo(opr,0,3); gendo(sto,lev-table[i].level,table[i].adr); } } } else { memcpy(nxtlev,fsys,sizeof(bool)*symnum); expressiondo(nxtlev,ptx,lev); if(i! =0) { if(sym2==becomes) gendo(sto,lev-table[i].level,table[i].adr); if(sym2==pluseq) { gendo(opr,0,2); gendo(sto,lev-table[i].level,table[i].adr); } if(sym2==minuseq) { gendo(opr,0,3); gendo(sto,lev-table[i].level,table[i].adr); } } }//else } } } 4、修改单词: 不等号#改为<> ●PL0.cpp init(); 移除: ssym['#']=neq; 在getsym()里增加对<>的识别(在<或<=基础上修改)。 下面为在<基础上修改,注意在if(ch==’<’)中修改,不包括elseif(ch=='>')那部分: if(ch=='<')/*检测小于或小于等于符号*/ { getchdo; if(ch=='=') { sym=leq; getchdo; } /*在之间添加*/ elseif(ch=='>')//addneq { sym=neq; getchdo; } /*在之间添加*/ else { sym=lss; } } 5、增加条件语句的ELSE子句 else { if(sym==ifsym)/*准备按照if语句处理*/ { getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[thensym]=true; nxtlev[dosym]=true;/*后跟符号为then 或do*/ conditiondo(nxtlev,ptx,lev);/*调用条 件处理(逻辑运算)函数*/ if(sym==thensym) { getsymdo; } else { error(16);/*缺少then*/ } cx1=cx;/*保存当前指令地 址*/ gendo(jpc,0,0);/*生成条件跳转指令,跳转地址暂写0*/ /*这里之间开始添加*/memcpy(nxtlev,fsys,sizeof(bool)*symnum); //添加后跟符号 nxtlev[elsesym]=true; statementdo(nxtlev,ptx,lev);/*处理 then后的语句*/ code[cx1].a=cx;/*经statement处理后 ,cx为then后语句执行完的位置,它正是前面未定的跳转地址*/ if(sym==elsesym) { cx2=cx; getsymdo; gendo(jmp,0,0); code[cx1].a=cx; statementdo(fsys,ptx,lev); code[cx2].a=cx; }/*这里之间开始添加*/ } else { if(sym==beginsym)/*准备按照复合语句处理*/ { getsymdo; memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[semicolon]=true; nxtlev[endsym]=true;/*后跟符号为分号或 end*/ /*循环调用语句处理函数,直到下一个符号不 是语句开始符号或收到end*/ 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);/*缺少end或分号*/ } } 写出相关文法: G(S): S→ifSelseS|ifS|a Else语法图: 三、结构设计说明 1、PL/0编译程序的结构图如下: 由于PL/0编译程序采用一趟扫描方法,所以语法语义分析过程block是整个编译程序的核心。 下面给出编译程序的总体流程图,以弄清block过程在整个编译程序中的作用。 在流程图中可以看出,主程序置初值后先调整用读单词过程getsym取一个单词,然后再调用语法分析过程block,直到遇源程序的结束符“.”为止。 四、各功能模块描述 GetSym(): 词法分析,从源文件中读出若干有效字符,组成token串,识别它的类型为保留字/标识符/数字或其它符号。 GEN(): 目标代码生成过程,本过程用于把生成的目标代码写入目标代码数组,供后面的解释器解释执行. TEST(): 测试当前单词是否合法 ENTER(): 在名字表中加入一项 POSITION(): 查找名字的位置,找到则返回名字表中的位置,否则返回0 ConstDeclaration(): 常量声明处理 VarDeclaration(): 变量声明处理 ListCode(): 输出目标代码清单 FACTOR(): 因子处理过程 TERM(): 项处理过程 EXPRESSION(): 表达式处理过程 CONDITION(): 条件处理过程 STATEMENT(): 语句处理过程 Block(): 编译程序主体,参数: lev: 这一次语法分析所在的层次,tx: 符号表指针, fsys: 用于出错恢复的单词集合 BASE(): 通过过程基址求上一层过程的基址 Interpret(): 解释程序,PL/0编译器产生的类PCODE目标代码解释运行过程 五、主要成份描述 1.符号表 在编译程序中符号表用来存放语言程序中出现的有关标识符的属性信息,这些信息集中反映了标识符的语义特征属性.符号表的主要功能如下: 、收集符号属性 、上下文语义合法性检查的依据 、作为目标代码生成阶段地址分配的依据. 、符号表的数据结构: structtablestruct { charname[al];/*名字*/ enumobjectkind;/*类型: const,var,arrayorprocedure*/ intval;/*数值,仅const使用*/ intlevel;/*所处层,仅const不使用*/ intadr;/*地址,仅const不使用*/ intsize;/*需要分配的数据区空间,仅procedure使用*/ }; structtablestructtable[txmax];/*名字表*/ 2.运行时的存储组织和管理 当源程序经过语法分析,如果未发现错误时,由编译程序调用解释程序,对存放在CODE中的代码CODE[0]开始进行解释执行.当废弃结束后,记录源程序中标识符的TABLE表已没有作用.因此存储区只需以数组CODE存主的只读目标程序和运行机制时的数据区S,S是由解释程序定义的一维整数型数组.解释执行时的数据空间S为栈式计算机的在座空间,遵循后进先出规则,对每个过程(包括主程序)当调用时,才分配数据空间,退出过程进,则所分配原则的数据空间被释放. 解释程序还定义了4个寄存器: 1、指令寄存器.存放当前正在解释的一条目标指令2、程序地址寄存器.指向下一条要执行的目标程序的地址3、栈顶寄存器.4、基址寄存器.指向每个过程被调用时,在数据区S中给它分配原则的数据段起始地址,也称基地址. 为了实现过程被调用时给它分配数据段,过程运行结束后释放数据段以及嵌套过程之间结标志符引用的问题,当过程被调用时,在栈顶分配三个联系单元,这三个联系单元存放的内容分别为: SL静态链,动态链DL,RA返回地址。 3.语法分析方法 语法分析的任务是识别由词法分析给出的单词符号序列在结构上是否符合给定的文法规则.PL/0编译程序的语法分析采用了自顶向下的递归子程序法.粗略地说: 就是对应每个非终结符语法单元,编一个独立的处理过程(或子程序).语法分析研究从读入第一个单词开始由非终结符’程序即开始符出发,沿语法描述图箭头所指出的方向进行分析.当遇到非终结符时,则调用相应的处理过程,从语法描述图看也就进入了一个语法单元,再沿当前所进入的语法描述图的箭头方向进行分析,当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,则执行相应的语义程序(就是翻译程序).再读取下一个单词继续分析.遇到分支点时将当前的单词与分支点上的多个终结符逐个相比较,若都不匹配时可能是进入下一非终结符语法单位或是出错. 如果一个PL/0语言程序的单词序列在整修语法分析中,都能逐个得到匹配,直到程序结束’.’,这时就说所输入的程序是正确的.对于正确的语法分析做相应的语义翻译,最终得出目标程序. 4.中间代码表示 PL/0编译程序所产生的目标代码是一个假想栈式计算机的汇编语言,可称为类pcode指令代码,它不依赖任何实际计算机,其指令集极为简单,指令格式如下: f L a lit0a 将常数值取到栈顶,a为常数值 Lodla 将变量值取到栈顶,a为偏移量,l为层差 Stola 将栈顶内容送入某变量单元中,a为偏移量,l为层差 Cala 调用过程,a为过程地址,l为层差 Int0a 在运行栈中为被调用的过程开辟a个单元的数据区 jmp0a 无条件跳转至a地址 Jpc0a 条件跳转,当栈顶布尔值非真则跳转至a地址,否则顺序执行 opr00 过程调用结束后,返回调用点并退栈 opr01 栈顶元素取反 opr02 次栈顶与栈顶相加,退两个栈元素,结果值进栈 opr03 次栈顶减去栈顶,退两个栈元素,结果值进栈 opr04 次栈顶乘以栈顶,退两个栈元素,结果值进栈 opr05 次栈顶除以栈顶,退两个栈元素,结果值进栈 opr06 栈顶元素的奇偶判断,结果值在栈顶 opr07 opr08 次栈顶与栈顶是否相等,退两个栈元素,结果值进栈 opr09 次栈顶与栈顶是否不等,退两个栈元素,结果值进栈 opr010 次栈顶是否小于栈顶,退两个栈元素,结果值进栈 opr011 次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈 opr012 次栈顶是否大于栈顶,退两个栈元素,结果值进栈 opr013 次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈 opr014 栈顶值输出至屏幕 opr015
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 陈泳鑫 310006379 编译原理实验报告 编译 原理 实验 报告