文章目录

  • 一、 设计目的及要求
    • 1.1 设计目的
    • 1.2 设计要求
      • 1.2.1 要求一
      • 1.2.2 要求二
      • 1.2.3 要求三
  • 二、程序设计
    • 2.1 程序的组织结构
      • 2.1.1 PL/0编译程序函数定义层次结构
      • 2.1.2 PL/0编译程序函数过程或函数功能表
      • 2.1.3 PL/0指令功能表
      • 2.1.4 PL/0语言的出错信息表
    • 2.2程序流程图
      • 2.2.1 PL/0编译程序和解释执行过程
      • 2.2.2 PL/0程序语法分析
      • 2.2.3 else语句流程图
      • 2.2.4 do-while-until语句流程图
      • 2.2.5 for语句流程图
    • 2.3 目标代码生成模式
      • 2.3.1 if-then-else
      • 2.3.2 do while-until
      • 2.3.3 for-to/downto-do
  • 三、系统实现
    • 3.1 else语句扩充
    • 3.2 do-while-until语句扩充
    • 3.3 for语句扩充
      • 3.3.1 downto-do-end
      • 3.3.2 to-do-end
  • 四、程序源代码
    • 4.1 else语句扩充
    • 4.2 do-while- until语句扩充
    • 4.3 for语句扩充
      • 4.3.1 “变量=初值”部分代码
      • 4.3.2 “downto-do-end”部分代码
      • 4.3.3 “to-do-end”部分代码
  • 五、系统测试
    • 5.1 else语句扩充
    • 5.2 do-while-until语句扩充
    • 5.3 for语句扩充
  • 六、设计总结
  • 七、致谢
  • 源码与测试用例下载

一、 设计目的及要求

1.1 设计目的

根据所学的编译原理理论知识,在符合 PL/0 语言基本词法、语法规则的前提下,以原PL/0 编译程序C语言版本代码为基础,对 PL/0 语言的功能进行扩充。使理论与实践相结合,加深对编译原理的理解。

1.2 设计要求

1.2.1 要求一

1)扩充语言成份:“if 条件 then 语句系列1 else 语句系列2”。
2)写出相应的编译程序。

1.2.2 要求二

1)扩充语言成份:“do while 语句系列 until 条件”,即循环执行循环体内的语句系列,直到条件为真为止。
2)写出相应的编译程序

1.2.3 要求三

1)扩充语言成份:
①“for 变量= 初值 to 终值 do begin 语句系列 end”
②“for 变量= 初值 downto 终值 do begin 语句系列 end”
其中,语句①中循环变量的步长为1,语句②中循环变量的步长为-1。
2)写出相应的编译程序

二、程序设计

2.1 程序的组织结构

2.1.1 PL/0编译程序函数定义层次结构

表1 层次结构图

2.1.2 PL/0编译程序函数过程或函数功能表

表 2函数功能表

2.1.3 PL/0指令功能表

表 3指令功能表

2.1.4 PL/0语言的出错信息表

表 4 出错信息表

2.2程序流程图

2.2.1 PL/0编译程序和解释执行过程

图 1 解释执行过程

2.2.2 PL/0程序语法分析

图 2 语法分析流程图

2.2.3 else语句流程图

图 3 else语句流程

表 5 else语句四元式序列

2.2.4 do-while-until语句流程图

图 4 do-while-until 语句流程

表 6 do-while-until 语句四元式序列

2.2.5 for语句流程图

图 5 for语句流程

表 7 for语句四元式序列

2.3 目标代码生成模式

2.3.1 if-then-else

2.3.2 do while-until

2.3.3 for-to/downto-do

三、系统实现

3.1 else语句扩充

本部分程序首先判断then语句块的最后一个单词是否为“;”。如果then最后一个字符是“;”,则需要跳过该符号之后再执行else及之后的语句。接下来的符号是else时,先记录当前jmp指令的位置,并为jpc指令赋值,使if为false时能直接跳转到else语句之后进行代码执行,然后调用函数处理else之后的语句,最后为jmp指令赋值,使if执行结束时能直接跳转到if-else结束位置。

图 6 else语句执行流程和代码结构

3.2 do-while-until语句扩充

本部分程序首先判断当前符号是否为do,然后读取下一个字符并判断是否为while。接着记录当前位置,此时为while循环体开始位置。接下来,允许while后能接的字符为until,然后执行while循环体内的语句。接着判断while的最后一个字符是否是“;”,是,则跳过该符号执行until及之后的语句。当下一个符号是until时,执行判断语句。当判断条件为false时,执行条件跳转,跳转到while循环体的开始位置继续运行。

图 7 do-while-until执行流程和代码结构

3.3 for语句扩充

首先识别当前符号为for,然后执行变量定位与赋值语句。

3.3.1 downto-do-end

识别当前符号为downto,记录当前位置,即判断当前变量与终值大小关系的位置。将循环判断变量取出并放到栈顶后,判断循环变量条件并生成比较指令,判断此战顶是否大于等于栈顶,往后退两个栈元素,结果值进栈。再次记录当前位置,即do循环开始的位置。识别当前符号是否为do,并在成立的情况下运行do内循环体。然后将循环变量取出放到栈顶,再将步长1取出放到栈顶,执行指令,次栈顶减去栈顶,退两个栈元素,结果值进栈,最后将栈顶的值存入循环变量。这就完成了变量的自减。然后执行无条件跳转语句,跳转到比较变量与终值大小关系的位置。最后地址回填,将jpc的目的地址赋值为do执行完后的位置,即当次栈顶小于栈顶时,结束for循环语句。

图 8 do-while-until语句执行流程和代码结构

3.3.2 to-do-end

与上述downto-do-end基本逻辑一致,只是将判断的大于等于改为了小于等于,将变量的自减改为了自增。


图 9 for语句执行流程和代码流程

四、程序源代码

4.1 else语句扩充

解决对编译程序if-else的扩展,补充了代码中缺失的else语句块

//添加处理else语句
cx2=cx;  /*记录jmp指令的位置,执行完then语句后需要无条件转移,出发地址为cx2 */
gendo(jmp,0,0); /*执行完if为真后,无条件转移,将来会直接跳转到else后 */
bool isSemi=false; //分号;跳过
code[cx1]a = cx;   /* 经statement处理后,cx为else语句执行开始的位置,它正是前面未定的跳转地址 (回填cx1的地址,即if执行为假) 为jpc指令赋值 */
if(sym==semicolon)   //如果then语句块的最后一个单词为“;”,则跳过{getsymdo;   //取下一个单词 isSemi=true;  //有";" }//接下来的符号是else
if(sym==elsesym)  //若为else,执行其中的语句{getsymdo;statementdo(fsys,ptx,lev); //处理else后的语句 code[cx2]a=cx;  /*当前是else后语句的结束位置,判断正式结束,回填if执行结束时的地址,为jmp指令赋值,if语句执行后应跳转至此*/
}
//上述为添加的else语句处理过程

4.2 do-while- until语句扩充

解决了do while until 语句的扩充,在程序中添加了do while until语句块。

//添加do while until 语句
if (sym == dosym) //此时识别的符号是do
{getsymdo;if (sym == whilesym) //do while 语句 {cx1 = cx; //记录当前的位置,即while循环体开始位置 getsymdo;memcpy(nxtlev, fsys, sizeof(bool)* symnum);nxtlev[untilsym] = true; //后跟符号为until statementdo(fsys, ptx, lev); //执行while循环体 if (sym == semicolon) //分号,跳过 {getsymdo;}if (sym == untilsym) //为until 执行条件语句 {getsymdo;conditiondo(nxtlev, ptx, lev); //执行条件判断 gendo(jpc, 0, cx1); //条件跳转,为flase是跳转到while循环体内 }}
//以上为添加的do while until 语句

4.3 for语句扩充

解决对编译程序for语句的扩展,补充了for-to和for-downto语句块

4.3.1 “变量=初值”部分代码

找到变量位置并为变量赋初值

if(sym==forsym)  //准备按照for语句处理
{getsymdo;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;memcpy(nxtlev,fsys,sizeof(bool)*symnum); nxtlev[tosym]=true;nxtlev[downtosym]=true;nxtlev[dosym]=true;expressiondo(nxtlev,ptx,lev);}else{error(13);  //没有检测到赋值符号 }if(i!=0){gen(sto,lev-table[i]level,table[i]adr);}

4.3.2 “downto-do-end”部分代码

if(sym==downtosym)
{cx1=cx; //记录当前位置,即downto后开始判断当前变量与终值大小关系的位置 getsymdo;                                                gendo(lod,lev-table[i]level,table[i]adr); //将循环判断变量取出放到栈顶 nxtlev[beginsym]=true; //接下来识别的符号为begin expressiondo(nxtlev,ptx,lev); //判断循环变量条件 gen(opr,0,11); //生成比较指令 次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈 cx2=cx; //记录循环开始地址gen(jpc,0,0); //条件跳转,暂时未知目的地址 ,用0代替 if(sym==dosym){getsymdo ;statementdo ( fsys, ptx, lev) ; //运行do内代码                                               gen (lod, lev - table [i] level, table[i]adr); //将循环变量取出放在栈顶 gen (lit, 0, 1); //常数1添加到栈顶 即将步长取到栈顶 gen (opr, 0, 3); //循环变量减少1 次栈顶减去栈顶,退两个栈元素,结果值进栈gendo (sto, lev - table[i] level, table[i]adr);  //将栈顶的值存入循环变量 gendo(jmp , 0, cx1); //无条件跳转,到判断变量与终值大小关系的位置 code[cx2]a=cx; /*地址回填, jpc的目的地址时do执行完后的位置
即当次栈顶小于栈顶时,结束for循环语句*/ } else{error(18);}
}

4.3.3 “to-do-end”部分代码

if(sym==tosym)
{cx1=cx;  //记录比较地址getsymdo;gendo(lod,lev-table[i]level,table[i]adr); memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlev[beginsym]=true;expressiondo(nxtlev,ptx,lev); //处理循环边界表达式gen(opr,0,13);  //生成条件比较表达式cx2=cx;  //记录条件跳转地址gen(jpc,0,0);if(sym==dosym){getsymdo;statementdo(nxtlev,ptx,lev);gen(lod,lev-table[i]level,table[i]adr);  //变量提到栈顶gen(lit,0,1);  //常数1加到栈顶gen(opr,0,2);  //循环变量增加到1gendo(sto,lev-table[i]level,table[i]adr);  //赋值gen(jmp,0,cx1);  //回条件判断code[cx2]a=cx;  //跳出循环 } else{error(18);  /* 缺少do */}
}

五、系统测试

5.1 else语句扩充








5.2 do-while-until语句扩充




5.3 for语句扩充










六、设计总结

经历了长达一周的课程设计工作,我们小组终于完成了本次课程设计的代码编写及论文编撰任务。我们在确认合作意向之后,很快就确定下来了各自的任务分工,在独立完成各自任务的同时,我们也常常合作工作,指出对方的不足并解决,对方的一些问题很庆幸能与默契地搭档一起进行本次课程设计。

在课程设计的过程中,我们首先遇到的问题是庞大源代码的阅读,我们需要先初步阅读并理解老师给出的基础代码之后,再在此基础上进行代码的扩充,基础代码的行数已经多达上千行,我们采取分工的方式,一人读懂一部分函数的功能,然后再以口述的方式给对方讲解,节省理解代码的时间。

接下来,我们先进行的是if-else语句的扩充这一部分的难点是理清jpc和jmp的跳转以及地址的回填如何进行。我们根据老师给出的指导,仔细分析了代码执行流程和结构,确定了jpc和jmp的地址并根据网上查找到的资料,确定了地址回填的编写方式在编写过程中,我们起初将cx2=cx语句写在了if(sym=elsesym)语句内部,后来检查的时候,我们经过讨论,认为应该放到if前,因为then的语句执行完之后即可跳转到else语句末尾,而不必先识别else再跳转。最后,我们还是放在了外部,因为如果放在外部,在编译时无需再编译else语句,能节省时间

dowhile语句的扩充因为有else的语句扩充作为基础,写代码并不困难,基本的逻辑思路是一致的,但是我们犯了一个逻辑上的错误,我们把题目的do-while-until理解成了do-while的结构,导致地址的跳转逻辑错误。

for语句的难点是变量和终值大小的比较如何实现,以及变量的自增与自减如何实现我们首先确定了for语句的代码大致执行顺序与结构,但是接着的代码编写部分有些无从下笔我们决定先整理出函数表以及指令功能表,以便接下来的编写能更清晰地调用相关函数实现目标功能。for后的“变量=初值”部分的代码直接使用的base代码中已给出的赋值代码,并未做修改。变量与终值的比较及变量的自增自减,我们在查找了相关的资料之后,才确定了gen的函数调用方式。

通过本次课设,我们进一步巩固了编译原理的理论知识,在课设过程中以实践的方式,进一步加深了对相关知识的理解与应用。

七、致谢

在本次课程设计中,首先我们由衷地感谢台安老师对于编译原理课程的教授与指导。从课程设计正式开始到后期的完成,都离不开台老师的悉心指导。台老师严谨求时的治学态度,踏实坚韧的工作精神,平易近人的待人方式给我们许多启发和帮助。也正是因为老师的认真负责,为我们编译原理的课设奠定了坚实的理论基础。在此,我们再次向台老师致以诚挚的谢意和崇高的敬意。

其次,在本次课设中还要感谢我亲爱的搭档,我们两个人分工明确,在确定了思路后就立刻开始完成自己的部分,在不理解的地方一起进行讨论,最终在规定的时间内完成。

最后再次感谢所有在本次课程设计中帮助过我们的老师和同学们!

源码与测试用例下载

https://download.csdn.net/download/weixin_47500703/85901408

编译原理课程设计-对pl0语言进行扩充相关推荐

  1. 编译原理课程设计-C语言子集编译器(Java实现)

    编译原理课程设计-一个C语言子集编译器 项目地址 https://github.com/qiushuang139/c-compliers 联系方式: email:qiushuang820@outloo ...

  2. 编译原理公式计算器C语言,编译原理课程设计-简单计算器实现.doc

    编译原理课程设计-简单计算器实现 课程设计报告课程:编译原理学号:姓名:班级:11级嵌入式应用技术班教师:时间:2014年6月计算机科学与技术系 设计名称:简单计算器的实现设计内容.目的与要求:设计内 ...

  3. c语言实现编译器编译原理,编译原理课程设计--C语言编译器实现.doc

    编译原理课程设计--C语言编译器实现 甘肃政法学院 编译原理课程设计 题 目 C语言编译器实现 计算机科学学院计算机科学与技术专业10 级 计本 班 学 号: 201081010137 姓 名: 杨青 ...

  4. 基于c语言的编译原理课程设计,编译原理课程设计心得体会

    与<编译原理课程设计心得体会>相关的范文 本文由leishensc贡献 doc文档可能在WAP端浏览体验不佳.建议您优先选择TXT,或下载源文件到本机查看. 2008-2009 学年第二学 ...

  5. 编译原理课程设计词法分析

      编译原理课程设计词法分析任务书 5)参考文献: (1)张素琴,吕映芝. 编译原理[M]., 清华大学出版社 (2)蒋立源.康慕宁等,编译原理(第2版)[M],西安:西北工业大学出版社 6)课程设计 ...

  6. 对计算机课程设计的认识,编译原理课程设计心得体会范文

    经过一个星期的编译原理课程设计,本人在刘贞老师的指导下,顺利完成该课程设计.通过该课程设计,收获颇多. 一.对实验原理有更深的理解 通过该课程设计,掌握了什么是编译程序,编译程序工作的基本过程及其各阶 ...

  7. 课程设计是计算机科学与技术专业的一门,计算机107编译原理课程设计.doc

    淮阴工学院 编译原理课程设计指导书 王文豪 江苏·淮阴工学院·计算机工程系 二OO九年三月 前言 <编译原理>是计算机科学与技术专业最重要的一门专业基础课程,内容庞大,涉及面广,知识点多. ...

  8. 广西大学编译原理课程设计

    github地址:github地址 Curriculum-design-of-Compilers-Principles 简要介绍:这是由广西大学计算机科学与技术系的三位同学编写的编译原理课程设计.使用 ...

  9. 编译原理课程设计:语法分析器

    配套代码: 编译原理课程设计:语法分析器-Python文档类资源-CSDN下载所使用的开发环境:Windows10.python(PyCharm)环境注意:expression更多下载资源.学习资料请 ...

最新文章

  1. spring-boot学习资料
  2. Silverlight Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)
  3. glBegin()和glEnd()之间可调用的函数
  4. 根据mysql数据库日志恢复删除数据
  5. php中strtotime的意思,php中strtotime函数用法详解
  6. 分析了这么多年的福利彩票记录,原来可以用Python这么买彩票!
  7. 盘点66个Pandas函数,轻松搞定“数据清洗”!
  8. Taro+react开发(76):taro安装
  9. 解决Django静态文件配置pycharm高光问题
  10. java webservice 接收数据_WebService客户端,接收数据解析存入数据库
  11. 【java】java中的线程池 ThreadPoolExecutor源码分析
  12. 计算机系统的工作方式,计算机的操作系统与工作方式
  13. 均衡发展学校计算机室解说词,迎接省均衡发展学校解说词
  14. 区块链技术指南:常见问题
  15. 基于Simulink的转速、电流双闭环直流调速系统的建模与仿真
  16. 从实际项目出发,告诉你vue3到底香不香
  17. 阿里巴巴编码规范认证考试总结
  18. 2019年最新Java学习路线图
  19. 【LaTeX应用】latex排版中插入参考文献
  20. JAVA访问控制权限

热门文章

  1. 围观 | 互联网大厂食堂PK:工作不是重点,食堂战胜一切!
  2. 变量的作用域和生存期:_生存分析简介:
  3. OLAP和OLTP比较
  4. AD19 PCB板完整绘制过程(4层)
  5. MATLAB神经网络43个案例分析
  6. 惠民工程(最小生成树裸题)
  7. Form--Form表单
  8. 爬虫|wallhere壁纸批量下载
  9. ElementUI日期转为“yyyy-MM-dd“格式
  10. mac系统安装ae打不开,显示意外退出的解决方法