1、课 程 设 计课程名称 编译原理 题目名称 编译原理课程设计 学生学院 计算机学院 专业班级 2011 级计算机科学与技术 7 班 学 号 3111006002 学生姓名 谢佳旭 2013 年 1 月 08 日目录一、课程设计目的5二、课程设计要求51、设计内容5三、课程设计环境与工具6四、结构设计说明51、PL/0 语言编译器.52、总流程图63、各功能模块描述6五、主要成分描述7六、测试用例. 91、测试*=和/=的运算功能92、测试 FOR语句功能.9七、开发过程和完成情况91、扩充赋值运算:*= 和 /=92、扩充 FOR语句(Pascal).103、添加单行注释.12八、心得体会.1
2、4出错处理函数表格管理函数PL/0 源程序目标代码生成程序程序目标代码生成程序程序目标代码生成程序程序目标代码生成程序程序目标代码生成程序程序一、课程设计目的在分析理解一个教学型编译程序(如 PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。达到进一步了解程序编译过程的基本原理和基本实现方法的目的。二、课程设计要求1 课程设计基本内容(成绩范围:“中” 、 “及格”或“不及格” )(1)扩充赋值运算:*= 和 /=扩充语句(Pascal 的 FOR语句):FOR :=STEP UNTILDo 选做内容(成绩评定范围扩大到:“优”和“良” )(1)增加类型: 字符
3、类型; 实数类型。(2) 增加 注释 ; 注释由/* 和*/包含;(3)扩充函数: 有返回值和返回语句; 有参数函数。(4)增加一维数组类型(可增加指令) 。(5)其他典型语言设施。三、课程设计环境与工具(1)运行平台:WIN7 旗舰 SP1 (2)实现工具:C+Builder 6.0(3)教学型编译程序:PL/0 四、结构设计说明和各功能模块描述(1)PL/0 语言编译器PL/0语言可看成是 PASCAL语言的子集,它的编译程序是一个编译解释执行系统。PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关。(2)PL/0 编译程序的过程或函数的功能表1、 void Error(int
4、 n) :错误处理,打印出错位置和错误编码2、 void GetCh():漏掉空格,读取一个字符3、 void GetSym():词法分析,读取一个单词4、 void GEN(FCT X, int Y, int Z):生成目标代码,并送入目标程序区5、 void TEST(SYMSET S1, SYMSET S2, int N):测试当前单词符号是否合法6、 void ENTER(OBJECTS K, int LEV, int /临时存放运算符if(i!=0) /开始处理GetSym();GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); /取值到栈顶EXP
5、RESSION(FSYS,LEV,TX);if(ADDOP=ADDEQ)/遇到*=时GEN(OPR,0,4); /次栈顶乘以栈顶,退两个栈元素,结果值进栈.else /遇到/=时GEN(OPR,0,5); /次栈顶乘以栈顶,退两个栈元素,结果值进栈GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/出栈取值到内存2、扩充 FOR语句(Pascal)FOR := STEP DO FOR := UNTIL DO 其中,语句的循环变量的步长为 2,语句的循环变量的步长为-2。以下为新增代码段:/开始插入新增代码case FORSYM: GetSym();if(SY
6、M != IDENT) Error(32);else i=POSITION(ID,TX);if(i = 0) Error(11);else if (TABLEi.KIND!=VARIABLE) /*ASSIGNMENT STEPNON-VARIABLE*/Error(12); i=0; /赋值语句中,赋值号左部标识符属性应是变量/否则报错GetSym();if(SYM = BECOMES) GetSym();else Error(13); /赋值语句左部标识符后应是赋值号:= 否则报错EXPRESSION(SymSetUnion(SymSetNew(TOSYM,DOWNTOSYM),FSYS)
7、,LEV,TX);/EXPRESSION(FSYS,LEV,TX);if (i!=0)GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/保存初值if(SYM = TOSYM) /FOR TO组合,即递增CX1=CX; /保存循环开始点GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/将循环判断变量取出放到栈顶GetSym();EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX);/*判断循环变量条件,看是否跳出循环*/GEN(OPR,0,13); /生成比较指令,看
8、循环变量是否依旧满足条件CX2=CX; /保存循环结束点GEN(JPC,0,0); /生成条件跳转指令,跳出循环,跳出的地址未知GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/将循环变量取出放在栈顶 GEN(LIT,0,2); /将步长取到栈顶GEN(OPR,0,2); /循环变量加步长,实现逐级递增GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/将栈顶的值存入循环变量if(SYM=DOSYM) /处理循环体GetSym();STATEMENT(FSYS,LEV,TX);else Error(48);GEN(JMP
9、,0,CX1);/无条件跳转到循环开始点CODECX2.A=CX; /*回填循环结束点的地址,CX为ELSE后语句执 行完的位置,它正是前面未定的跳转地址*/else if(SYM=DOWNTOSYM) /FOR DOWNTO组合,即递减CX1=CX;/保存循环开始点GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/将循环判断变量取出放到栈顶GetSym(); EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX);/*判断循环变量条件,看是否跳出循环*/GEN(OPR,0,11);/生成比较指令,看循环
10、变量是否依旧满足条件CX2=CX; /保存循环结束点GEN(JPC,0,0);GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/将循环变量取出放在栈顶GEN(LIT,0,2); /将步长取到栈顶GEN(OPR,0,3); /循环变量加步长,实现逐级递减GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);/将栈顶的值存入循环变量if(SYM=DOSYM) /处理循环体GetSym();STATEMENT(FSYS,LEV,TX);/循环体处理else Error(48);GEN(JMP,0,CX1);/无条件跳转到循环开始点
11、CODECX2.A=CX; /*回填循环结束点的地址,CX为ELSE后语句执 行完的位置,它正是前面未定的跳转地址*/else Error(47);break;/结束插入新增代码 3、添加单行注释在程序中,形如/C:=1;的代码段将会被忽略if(ch=/) /开始处理if(EOF!=fscanf(fin,“%c“,if(EOF=fscanf(fin,“%c“,break;elseprintf(“%c“,/);fprintf(fa1,“%c“,/);linell=/;ll+;elseprintf(“注释出错!“);return -1;八、心得体会课程设计的基本内容并不算难,但 FOR 语句功能实现比较繁琐,需要花时间调试和验证结果。增加单词比较简单易行,而实现扩充功能则相对困难,需要理解编译程序的核心和基本思想,包括基本的语法分析和句法分析以及中间代码的生成,还有十分重要的堆栈应用。把这些基础知识串联起来,理解好编译程序结构和原理及基本实现方法,才能更顺利的完成后面的设计内容。当然,理论联系实际并不是那么简单,遇到困难并非那么轻易就能解决,通过和同学的交流,交流自己的调试错误所在和交换设计思路,同样把问题清晰化,最终达成一个解决方案。很高兴本次课程设计达到了预期目标,巩固了编译程序理论知识,学以致用,当然也不能局限于课程设计,往后的自觉动手实践才能继续保持进步。