当前位置:文档之家› 编译原理课设报告2

编译原理课设报告2

编译原理课程设计题目:pl/0编译程序的改进与完善学生所在学院:信息科学与工程学院学生所在班级:06级计算机软件1班学生姓名:学生学号:指导教师:张世辉一、课设目的:1.阅读、研究、改进、设计和调试一个简单的编译程序;2.加深对编译程序理论和编译过程的理解。

二、课设内容:1扩充语句for(<语句>;<条件>;<语句>)<语句>;2扩充语句if <条件> then <语句> else <语句>;3扩充语句repeat <语句>;until <条件>;4增加自增自减运算++和—和+=,-=运算;5修改不等号#,为!=;6增加一维数组声明格式:<ident>[<ident>/<number>:<ident>/<number>];赋值格式:<ident>[<index>]:=<表达式>;调用格式:<ident>[<index>]三、程序结构:PL/0源程序图1 编译程序结构图2功能模块调用1.各功能模块的作用:Pl0.c:主程序Error:出错处理,打印出错位置和错误编码Getsym:词法分析,读取一个单词Getch:漏掉空格,读取一个字符Gen:生成目标代码,并送入目标程序区Test:测试当前当前符号是否合法Block:分程序分析处理过程,词法语法分析Enter:登陆名字表Position:查找标识符在名字表中的位置Constdeclaration:常量定义处理Vardeclaraction:变量说明处理Listcode:列出目标代码清单Statement:语句处理Expression:表达式处理Term:项处理Factor:因子处理Condition:条件处理Interpret:对目标代码的解释执行程序Base:通过静态链求出数据取得基地址增加两个功能:Arraydeclaration:数组声明处理Arraycoef:数组索引计算和“虚拟机”动作生成2.保留字: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,elsesym,forsym, inc, dec, whilesym, writesym,readsym, dosym, callsym, constsym,varsym,procsym, repeatsym, untilsym, plusbk, minusbk,lbrack, rbrack, colon,}共43个,其中补充保留字为:else, for, repeat, until, plusbk, minusbk,Lbrack, rbrack, colon3.虚拟机代码enum fct { lit, opr, lod, sto, cal, inte, jmp, jpc, lda, sta, }共10个,补充的lda,sta用于数组操作4.名字表中的类型enum object{ constant, variable, procedure, arrays, }共4个,扩充arrays,以便实现数组5.名字表结构struct tablestruct{char name[al];enum object kind;int val;int level;int adr;int size;//扩充名字表结构,增加一个data域保存数组的下界int data; /* 其他数据,对arrays来说是下界*/} 6.错误信息表(1) 常数说明中的=写成了:=(2) 常数说明中的=后应是数字(3)常数说明中的标识符后应是=(4) const,var,procedure后应为标识符(5)漏掉了,或;(6)过程说明后的符号不正确(应是语句开始符,或过程定义符)(7)应是语句开始符(8)程序体内语句部分的后跟符不正确(9)程序结尾丢了句号。

(10)语句之间漏了;(11)标识符未说明(12)赋值语句中,赋值号左部标识符属性应是变量(13)赋值号左部标识符属性应是赋值号(14)call后应为标识符(15)call后标识符属性应为过程(16)条件语句中丢了then(17)丢了end或;(18)while循环语句中丢了do(19)语句后的符号不正确(20)应为关系运算符(21)表达式内标识符属性不能是过程(22)表达式中漏掉右括号)(23)因子后的非法符号(24)表达式的开始符不能使此符号(31)数越界(32)read语句括号中的标识符不是变量补充错误处理:(50)数组格式错误(51)数组访问错误7.语法描述图:图3 程序语法描述图图4 分程序语法描述图图5 语句语法描述图图6条件语法描述图图7 表达式语法描述图图8 项语法描述图图9 因子语法描述图四、功能扩充1.在语句处理中增加repeat-until语句if(sym == repeatsym){cx1 = cx;getsymdo;statementdo(nxtlev, ptx, lev);if(sym == untilsym){getsymdo;conditiondo(nxtlev, ptx, lev);cx2=cx;gendo(jpc, 0, 0);code[cx2].a=cx1; }else error(33); //没有写until出错} }注意:repeat是可以作为语句的开始符,所有要在初始化函数中的语句开始符中添加statbegsys[repeatsym]=true;语句。

2.语句处理中加入for循环语句if(sym == forsym){getsymdo;if(sym != lparen) error(34);//没有左括号出错else {getsymdo;statementdo(nxtlev, ptx, lev); //S1代码if(sym != semicolon) error(10); //语句缺少分号出错else{cx1=cx;getsymdo;conditiondo(nxtlev, ptx, lev); //E代码if(sym!=semicolon)error(10);//语句缺少分号出错else {cx2=cx;gendo(jpc,0,0);cx3=cx;gendo(jmp,0,0);getsymdo;cx4=cx;statementdo(nxtlev, ptx, lev); //S2代码if(sym != rparen) error(22);//缺少右括号出错else {gendo(jmp,0,cx1);getsymdo;cx5=cx;statementdo(nxtlev, ptx, lev); //S3代码code[cx3].a=cx5;gendo(jmp,0,cx4);code[cx2].a=cx;} } } } }3.语句处理中加入if-then-else语句在原有程序if(sym==then){...}后加入下列代码:cx1 = cx;gendo(jpc, 0, 0);statementdo(fsys, ptx, lev);if(sym == elsesym){getsymdo;cx2 = cx;gendo(jmp, 0, 0);code[cx1].a = cx;statementdo(fsys, ptx, lev);code[cx2].a = cx;}else code[cx1].a = cx;4.扩充++和—运算符对于++和--运算符,扩充时要注意存在两个情况:1)作为语句的时候;2)作为表达式中的因子的时候。

注意:扩充时增加因子开始符facbegsys[incs]=true 和facbegsys[decs]=true 。

扩充的语法描述见结构设计中的PL/0分程序和主要语句的语法描述中的描述图,详细代码见程序。

1)作为语句的时候,有四种情况:a++; a--; ++a; --a;文法的EBNF 表示形式为:<自增自减语句>::=<标识符>[++ |--]|[++|-- ]<标识符>文法分析过程大体如下图:++a 和—a a++和a —生成中间代码对于a++;++a;和a--;--a;语句的处理如下:先将变量的值取出放在栈顶,后将1入栈,后执行加法或减法运算oprv 指令的2(加法)、3(减法),后将运算后的栈顶值存回变量。

a++;和++a;语句的中间代码:lod 0 3;lit 0 1;opr 0 2;sto 0 3;a--;和--a;语句的中间代码:lod 0 3;lit 0 1;opr 0 3;sto 0 3;2)作为因子的时候,有两种情况:a++和a--作为因子,比如:b:=a++*a--;语句++a 和--a 作为因子,比如:b:=--a+2*++a;语句文法的EBNF 表示形式为:<表达式>::=...[ ++|--]<标识符>|<标识符>[++| --]...其中的...表示前后都可以有其他的项或因子生成中间代码①对于因子++a和--a的中间代码生成处理和a++;等语句处理一样;②对于因子a++和a—的中间代码生成处理如下:a++:lod 0 3;lit 0 1;opr 0 2;sto 0 3;lod 0 3;lit 0 1;opr 0 3; a--:lod 0 3;lit 0 1;opr 0 3;sto 0 3;lod 0 3;lit 0 1;opr 0 2;先将变量的值取出放在栈顶,后将1入栈,后执行加法或减法运算opr指令的2(加法)、3(减法),后将运算后的栈顶值存回变量,后将变量的值又取出来放入栈顶,后将1入栈,如果是a++就执行减法,如果是a—就执行加法,以实现先用a的值后再加1。

5.修改不等号#为!=注释源程序中的ssym['#'] = neq语句,在getsym中加入下列代码://修改不等号为!=else if(ch=='!'){getchdo;if(ch=='='){sym=neq;getchdo; }else sym=nul; }6.加入对一维数组的支持本程序将数组看做变量的一种,由var声明函数调用array声明函数完成数组声明,这样就处加入文件输出的相关语句外,可以完全保留block 函数和enter函数;通过改写factor函数使数组因子包括了后缀的索引号,这样就可以调用通用的表达式函数赋值数组了。

相关主题