2015广工编译原理课程设计报告(文档最后含源码下载地址)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计
课程名称___编译原理__________题目名称___PL/0编译器的扩充__学生学院___计算机学院_________专业班级_计算机科学与技术13(9)学号
学生姓名
指导教师___林志毅________________ 2016年1月2日
一、已完成的内容:
(1)扩充赋值运算:*=和/=
(2)扩充语句(Pascal的FOR语句)
FOR<变量>:=<表达式>STEP<表达式>UNTIL<表达式>Do<语句>(3)增加类型:①字符类型;②实数类型。
(4)增加注释;多行注释由/*和*/包含,单行注释为//
二、实验环境与工具
(1)计算机及操作系统:PC机,Windows7
(2)程序设计语言:C++
(3)使用软件Borland C++Builder6.0
(4)教学型编译程序:PL/0
三、具体实现:
1.扩充赋值运算:*=和/=
(1)语法树
变量*=表达式
(2)修改GetSym()方法(写出修改的代码)
else if(CH=='*'){
GetCh();
if(CH=='='){SYM=TIMESBECOMES;GetCh();}
else SYM=TIMES;
}else if(CH=='/'){
GetCh();
if(CH=='='){SYM=SLASHBECOMES;GetCh();}
(3)修改STATEMENT()方法(写出修改的代码)
case IDENT:
i=POSITION(ID,TX);
if(i==0)Error(11);
else if(TABLE[i].KIND==VARIABLE||TABLE[i].KIND==FLOATTYPE) {/*ASSIGNMENT TO NON-VARIABLE*/
GetSym();
if(SYM==BECOMES||SYM==TIMESBECOMES|| SYM==SLASHBECOMES||SYM==PLUSBECOMES||SYM==MINUSBECOMES){
RELOP=SYM;
if(SYM!=BECOMES){//若为除等于(或其他类似符号)则先把符号左边的变量值放入栈中GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
}
GetSym();
}else Error(13);
EXPRESSION(FSYS,LEV,TX);
if(RELOP==TIMESBECOMES){
GEN(OPR,0,4);
}else if(RELOP==SLASHBECOMES){
GEN(OPR,0,5);
}else if(RELOP==PLUSBECOMES){
GEN(OPR,0,2);
}else if(RELOP==MINUSBECOMES){
GEN(OPR,0,3);
}
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
}
(4)运行测试(测试的PL0源码扩充单词的测试并贴运行结果截图)PL0源码:
PROGRAM EX01;
VAR A,B,C,D;
BEGIN
A:=16;
A/=2;
WRITE(A);//结果为8
B:=4;
B*=2;
WRITE(B);//结果为8
C:=6;
C+=2;
WRITE(C);//结果为8
D:=10;
D-=2;
WRITE(D);//结果为8
END.
(5)运行结果:
(6)出现的问题及解决
开始时在实现/=和*=操作时,*=的实现很顺利,而/=却一直没有得到理想的结果,通过与同学的讨论得知代码中除号指令的解析中,其实为除余操
作,于是将%改为/,但是结果还是错误,经过调试发现是两个相除的数在栈
相反了,正确的状态应该是除数位于次栈顶,而被除数位于栈顶。
解决:在调用EXPRESSION函数解析/=右边表达式前,先将其左边变量的值放入栈中。
2.扩充语句(Pascal的FOR语句)
FOR<变量>:=<表达式>STEP<表达式>UNTIL<表达式>Do<语句>
(1)语法图
(2)修改GetSym()方法(写出修改的代码)
此处无修改,FOR、STEP、UNTIL及DO等关键字已放置关键字数组中,通过该数组便可识别。
(3)修改STATEMENT()方法(写出修改的代码)
case FORSYM:
GetSym();
STATEMENT(SymSetUnion(SymSetNew(STEPSYM),FSYS),LEV,TX);//处理for
后面的赋值语句
CX3=CX;GEN(JMP,0,0);//用于第一次执行for语句时跳过step语句
CX1=CX;//记录step后语句的代码位置
if(SYM==STEPSYM){
GetSym();
STATEMENT(SymSetUnion(SymSetNew(UNTILSYM),FSYS),LEV,TX);//处理
step后面的表达式
}else Error(8);
if(SYM==UNTILSYM){
CODE[CX3].A=CX;//回填第一次进入for循环时的直接跳转地址
GetSym();
}else Error(8);
CONDITION(SymSetAdd(DOSYM,FSYS),LEV,TX);//