中间代码生成实验报告材料

合集下载

天津理工大学编译原理实验3:语义分析与中间代码生成

天津理工大学编译原理实验3:语义分析与中间代码生成

实验报告学院(系)名称:计算机与通信工程学院
【实验过程记录(源程序、测试用例、测试结果及心得体会等)】
根据语法分析修改的程序流程图
开始
从输入串获取字符与符号栈比较关系>|=
归约>将符号移进符号栈
是否成功
Error 出错处理Y
结束
输出结果
N
从标识符中查找数值
压入语义栈
根据四元式修改语义栈
程序运行结果:
部分源代码:
心得体会:
这次实验做得还是不够理想,虽然做出了语法制导翻译的全过程,但是还有部分地方不够完美。

例如四元式的使用及输出,不过总体来说,也算是深入的掌握了语法制导翻译的全过程,获益匪浅。

中间代码生成实验报告

中间代码生成实验报告

一、实验目的1. 理解编译原理中中间代码生成的基本概念和作用。

2. 掌握中间代码生成的常用算法和策略。

3. 提高对编译器构造的理解和实际操作能力。

二、实验环境1. 操作系统:Windows 102. 编程语言:Java3. 开发工具:Eclipse三、实验内容1. 中间代码生成的基本概念2. 中间代码的表示方法3. 中间代码生成算法4. 实现一个简单的中间代码生成器四、实验步骤1. 了解中间代码生成的基本概念中间代码生成是编译过程中的一个重要环节,它将源程序转换成一种中间表示形式,便于后续的优化和目标代码生成。

中间代码生成的目的是提高编译器的灵活性和可维护性。

2. 研究中间代码的表示方法中间代码通常采用三地址代码(Three-Address Code,TAC)表示。

TAC是一种低级表示,由三个操作数和一个操作符组成,例如:(t1, t2, t3) = op,其中t1、t2、t3为临时变量,op为操作符。

3. 学习中间代码生成算法中间代码生成算法主要包括以下几种:(1)栈式中间代码生成算法(2)归约栈中间代码生成算法(3)递归下降中间代码生成算法4. 实现一个简单的中间代码生成器本实验采用递归下降中间代码生成算法,以一个简单的算术表达式为例,实现中间代码生成器。

(1)定义语法规则设表达式E由以下语法规则表示:E → E + T | E - T | TT → T F | T / F | FF → (E) | i(2)设计递归下降分析器根据语法规则,设计递归下降分析器,实现以下功能:①识别表达式E②识别项T③识别因子F(3)生成中间代码在递归下降分析器中,针对不同语法规则,生成相应的中间代码。

例如:当遇到表达式E时,生成以下中间代码:(t1, t2, t3) = op1(t1, t2) // op1表示加法或减法(t4, t5, t6) = op2(t4, t5) // op2表示乘法或除法(t7, t8, t9) = op3(t7, t8) // op3表示赋值(4)测试中间代码生成器编写测试用例,验证中间代码生成器的正确性。

lab14语义分析报告报告材料与中间代码生成

lab14语义分析报告报告材料与中间代码生成

实验报告封面课程名称:编译原理课程代码:SS2027任课老师:彭小娟实验指导老师: 彭小娟实验报告名称:实验十四:语义分析与中间代码生成1学生姓名:学号:教学班:递交日期:签收人:我申明,本报告内的实验已按要求完成,报告完全是由我个人完成,并没有抄袭行为。

我已经保留了这份实验报告的副本。

申明人(签名):实验报告评语与评分:评阅老师签名:彭小娟一、实验名称:语义分析与中间代码生成1二、实验日期: 年 月 日三、实验目的:1. 理解相关概念:中间代码、三地址码,各种语句的目标代码结构2. 掌握三地址码(三元式、四元式、DAG 图),3. 理解赋值语句三地址代码的翻译模式四、实验用的仪器和材料:(操作系统:CPU :内存:硬盘:软件:)硬件:PC 人手一台软件:office五、实验的步骤和方法:1. 给出下面中缀式的逆波兰表示(后缀式),后缀式的中缀式表示/*)(*)/(*++-+-+-++e d c ab d c b a e d c b anot A or not (C or not D)2. 请将表达式-(a+b)*(c+d)-(a+b+c)分别表示成三元式、四元式序列。

3. 按7.3节所说的方法,写出下面赋值句)A+=的自下而上语法制导B-(*:DC翻译过程。

给出所产生的三地址代码。

六、数据记录和计算:七、实验结果或结论:(总结)八、备注或说明:可写上实验成功或失败的原因,实验后的心得体会、建议等。

九、引用参考文献:即在本实验中所引用的之資料。

中间代码生成实验报告doc

中间代码生成实验报告doc

中间代码生成实验报告篇一:编译方法实验报告(中间代码生成器)编译方法实验报告XX年10月一、实验目的熟悉算术表达式的语法分析与中间代码生成原理。

实验内容二、(1)设计语法制导翻译生成表达式的四元式的算法;(2)编写代码并上机调试运行通过。

输入——算术表达式;输出——语法分析结果;相应的四元式序列。

(3)设计LL(1)分析法或LR(0)分析法的属性翻译文法,并根据这些属性翻译文法,使用扩展的语法分析器实现语法制导翻译。

三、实验原理及基本步骤●算术表达式文法:G(E):E ? E ω0 T | TT ? T ω1 F | FF ? i | (E)●文法变换:G’(E) E ? T {ω0 T(本文来自:小草范文网:中间代码生成实验报告)}T ? F {ω1 F}F ? i | (E)●属性翻译文法:E ? T {ω0 “push(SYN, w)” T “QUAT”}T ? F {ω1 “push(SYN, w)” F “QUAT”}F ? i “push(SEM, entry(w))” | (E)其中:push(SYN, w) —当前单词w入算符栈SYN;push(SEM, entry(w)) —当前w在符号表中的入口值压入语义栈SEM;QUAT —生成四元式函数i.T = newtemp;ii.QT[j] =( SYN[k], SEM[s-1], SEM[s], T); j++;iii.pop( SYN, _ ); pop( SEM, _ ); pop( SEM, _ );push( SEM, T );●递归下降子程序:数据结构:SYN —算符栈;SEM —语义栈;四、数据结构设计使用递归的结构进行四元式的设计,同时,运用堆栈结构将四元式的输出序列打印出来while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i];//push(SYN,w)i++; //read(w)T();quat();}while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i];//push(SYN,w)i++; //read(w)F();quat();}void quat(){strcpy(qt[j],"(, , , )");//QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--;//pop(SYN);i_sem--;//pop(SEM);i_sem--;//pop(SEM);sem[++i_sem]=temp; //push(SEM,temp); temp++;}五、关键代码分析(带注释)及运行结果#include#include "string.h"#include "stdio.h"using namespace std;char syn[10]; //文法符号栈int i_syn;char sem[10]; //运算对象栈int i_sem;char exp[50]; //算术表达式区int i;char qt[30][15];//四元式区int j=0;char temp='q'; //临时变量,取值为r--z int E();int T();int F();void quat();//生成四元式函数int main(int argc, char* argv[]){printf("please input your expression:"); scanf("%s",exp); //输入四元式i=0; //read(w)E();if (exp[i]=='\0')for (i=0;i printf("%s\n",qt[i]);elseprintf("err");return 0;}int E(){T();while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i];//push(SYN,w)i++; //read(w)T();quat();}return 1;}int T(){F();while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i];//push(SYN,w)i++; //read(w)F();quat();}return 1;}int F(){if ( exp[i]=='('){i++; //read(w)E();if ( exp[i]!=')'){printf("err");return 0;}}else if ((exp[i]>='a' && exp[i]='0' && exp[i] sem[++i_sem]=exp[i]; } //push(SEM,w)else{printf("err");return 0;}i++; //read(w)return 1;}void quat(){strcpy(qt[j],"( , , , )");//QT[j]:=(SYN[k],SEM[s-1] ,SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp;//push(SEM,temp);temp++;}篇二:中间代码生成实验报告一、实验目的通过在实验二的基础上,增加中间代码生成部分,使程序能够对实验二中的识别出的赋值语句,if语句和while语句进行语义分析,生成四元式中间代码。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。

二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。

三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。

在本次实验中,我们使用有限自动机的理论来设计词法分析器。

首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。

然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。

在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。

(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。

在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。

首先,我们根据给定的语法规则,编写了相应的递归函数。

每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。

在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。

(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。

在本次实验中,我们使用了四元式作为中间代码的表示形式。

在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。

同时,根据语法树的结构,生成相应的四元式中间代码。

(四)代码优化代码优化的目的是提高生成代码的质量和效率。

在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。

通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。

中间代码生成

中间代码生成

中间代码生成计算机科学与工程学院课程设计报告题目全称:常用边缘算法的实现学生学号: 2506203010 姓名:王嘉指导老师:职称:指导老师评语:签字:课程设计成绩:设计过程表现设计报告质量总分编译器中间代码生成的研究与实现作者:王嘉学号:2506203010 指导老师:吴洪摘要:在编译器的翻译流水线中,中间代码生成是处于核心地位的关键步骤。

它的实现基于语法分析器的框架,并为目标机器代码的实现提供依据。

虽然在理论上没有中间代码生成器的编译器也可以工作,但这将会带来编译器的高复杂度,低稳定性和难移植性。

现代编译理论不仅要求中间代码的生成,还要求基于中间代码的优化。

本文研究并实现了一个轻量级类C语言的中间代码生成器,并就中间代码生成的原理进行了细致的阐述。

关键字:中间代码生成、语法制导翻译、翻译模式、语法树、三地址码一、目的及意义在编译器的分析综合模型中,前端将源程序翻译成一种中间表示,后端根据这个中间表示生成目标代码。

目标语言的细节要尽可能限制在后端。

尽管源程序可以直接翻译成目标语言,但使用与机器无关的中间形式具有以下优点:1.重置目标比较容易:不同机器上的编译器可以在已有前端的基础上附近一个适合这台新机器的后端来生成。

2.可以在中间表示上应用与机器无关的代码优化器。

本文介绍如何使用语法制导方法,基于一种轻量级的类C语言FineC的词法分析器和语法分析器,一遍地将源程序翻译成中间形式的编程语言结构,如声明、赋值及控制流语句。

为简单起见,我们假定源程序已经经过一遍扫描,生成了相应的词法记号流和符号表、词素表结构。

基于FineC语法标准的语法分析器框架也已经能够正常工作。

我们的任务就是补充这个框架,使其在语法分析的过程中生成相应的中间代码,并将必要的变量和函数声明存放在一个符号表链中。

二、目标语言词法和语法标准:这里定义一个编程语言称作FineC(“fine”指代轻量、精妙)。

它是一种适合编译器设计方案的语言。

编译方法实验报告(中间代码生成器)

编译方法实验报告(中间代码生成器)

编译方法实验报告2011年10月一、实验目的熟悉算术表达式的语法分析与中间代码生成原理。

二、实验内容(1)设计语法制导翻译生成表达式的四元式的算法;(2)编写代码并上机调试运行通过。

输入——算术表达式;输出——语法分析结果;相应的四元式序列。

(3)设计LL(1)分析法或LR(0)分析法的属性翻译文法, 并根据这些属性翻译文法, 使用扩展的语法分析器实现语法制导翻译。

三、实验原理及基本步骤●算术表达式文法:G(E): E ( E ω0 T | TT →T ω1 F | FF → i | (E)●文法变换:G’(E) E →T {ω0 T}T →F {ω1 F}F → i | (E)●属性翻译文法:E →T {ω0“push(SYN, w)” T “QUAT”}T →F {ω1“push(SYN, w)” F “QUAT”}F →i “push(SEM, entry(w))” | (E)其中:push(SYN, w) —当前单词w入算符栈SYN;push(SEM, entry(w)) —当前w在符号表中的入口值压入语义栈SEM;QUAT —生成四元式函数i. T = newtemp;ii. QT[j] =( SYN[k], SEM[s-1], SEM[s], T);j++;iii. pop( SYN, _ ); pop( SEM, _ ); pop( SEM, _ );push( SEM, T );●递归下降子程序:数据结构: SYN —算符栈;SEM —语义栈;四、数据结构设计使用递归的结构进行四元式的设计, 同时, 运用堆栈结构将四元式的输出序列打印出来while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)T();quat();}while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)F();quat();}void quat(){strcpy(qt[j],"(, , , )"); //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp; //push(SEM,temp);temp++;}五、关键代码分析(带注释)及运行结果#include <iostream>#include "string.h"#include "stdio.h"using namespace std;char syn[10]; //文法符号栈int i_syn;char sem[10]; //运算对象栈int i_sem;char exp[50]; //算术表达式区int i;char qt[30][15]; //四元式区int j=0;char temp='q'; //临时变量, 取值为r--zint E();int T();int F();void quat(); //生成四元式函数int main(int argc, char* argv[]){printf("please input your expression:");scanf("%s",exp); //输入四元式i=0; //read(w)E();if (exp[i]=='\0')for (i=0;i<j;i++) //输出四元式序列printf("%s\n",qt[i]);elseprintf("err");return 0;}int E(){T();while ( exp[i]=='+' || exp[i]=='-'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)T();quat();}return 1;}int T(){F();while ( exp[i]=='*' || exp[i]=='/'){syn[++i_syn]=exp[i]; //push(SYN,w)i++; //read(w)F();quat();}return 1;}int F(){if ( exp[i]=='('){i++; //read(w)E();if ( exp[i]!=')'){printf("err");return 0;}}else if ((exp[i]>='a' && exp[i]<='p')||(exp[i]>='0' && exp[i]<='9')){ sem[++i_sem]=exp[i]; } //push(SEM,w) else{printf("err");return 0;}i++; //read(w)return 1;}void quat(){strcpy(qt[j],"( , , , )"); //QT[j]:=(SYN[k],SEM[s-1],SEM[s],temp);qt[j][1]=syn[i_syn];qt[j][3]=sem[i_sem-1];qt[j][5]=sem[i_sem];qt[j][7]=temp;j++;i_syn--; //pop(SYN);i_sem--; //pop(SEM);i_sem--; //pop(SEM);sem[++i_sem]=temp; //push(SEM,temp);temp++;}六、总结与分析我们知道, 定义一种语言除了要求定义语法外, 还要求定义语义, 即对语言的各种语法单位赋予具体的意义。

中间代码生成实验报告

中间代码生成实验报告

中间代码生成实验报告《中间代码生成实验报告》摘要:本实验旨在通过编写中间代码生成程序,实现将高级语言源代码转换为中间代码的功能。

通过实验,我们掌握了中间代码的生成过程和相关算法,并对编译器的工作原理有了更深入的理解。

本实验采用了C语言作为源语言,通过词法分析、语法分析和语义分析,生成了对应的中间代码。

一、实验目的1. 理解编译器的工作原理,掌握中间代码生成的基本概念和方法;2. 掌握中间代码的表示方法和生成算法;3. 通过实践,提高编程能力和对编译原理的理解。

二、实验环境1. 操作系统:Windows 10;2. 编程语言:C语言;3. 开发工具:Visual Studio 2019。

三、实验内容1. 设计并实现中间代码生成程序,将给定的C语言源代码转换为中间代码;2. 实现词法分析、语法分析和语义分析,生成对应的中间代码;3. 测试程序,验证中间代码的正确性和有效性。

四、实验步骤1. 设计中间代码的表示方法,包括四元式、三地址码等;2. 实现词法分析器,将源代码转换为词法单元序列;3. 实现语法分析器,将词法单元序列转换为语法树;4. 实现语义分析器,对语法树进行语义检查并生成中间代码;5. 测试程序,验证中间代码的正确性和有效性。

五、实验结果经过测试,中间代码生成程序能够正确地将C语言源代码转换为中间代码,并且生成的中间代码能够正确地表达源代码的语义和逻辑结构。

通过实验,我们成功地掌握了中间代码的生成过程和相关算法,加深了对编译器工作原理的理解。

六、实验总结通过本次实验,我们深入了解了编译器的工作原理和中间代码生成的基本概念和方法。

通过实践,我们提高了编程能力和对编译原理的理解,为进一步深入学习编译原理和设计编译器打下了良好的基础。

希望通过不断的实践和学习,能够更加熟练地掌握编译原理的知识,为今后的学习和工作打下坚实的基础。

编译原理中间代码生成实验报告

编译原理中间代码生成实验报告

竭诚为您提供优质文档/双击可除编译原理中间代码生成实验报告篇一:编译原理-分析中间代码生成程序实验报告课程名称编译原理实验学期至学年第学期学生所在系部年级专业班级学生姓名学号任课教师实验成绩计算机学院制开课实验室:年月日篇二:编译原理实验中间代码生成实验四中间代码生成一.实验目的:掌握中间代码的四种形式(逆波兰式、语法树、三元式、四元式)。

二.实验内容:1、逆波兰式定义:将运算对象写在前面,而把运算符号写在后面。

用这种表示法表示的表达式也称做后缀式。

2、抽象(语法)树:运算对象作为叶子结点,运算符作为内部结点。

3、三元式:形式序号:(op,arg1,arg2)4、四元式:形式(op,arg1,arg2,result)三、以逆波兰式为例的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。

(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。

(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。

(4)如果不是数字,该字符则是运算符,此时需比较优先关系。

做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。

如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。

倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。

(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。

四、程序代码://这是一个由中缀式生成后缀式的程序#include#include#include#include#definemaxbuffer64voidmain(){chardisplay_out(charout_ch[maxbuffer],charch[32]);//intcaculate_array(charout_ch[32]);staticinti=0;staticintj=0;charch[maxbuffer],s[maxbuffer],out[maxbuffer];cout cin>>ch;for(i=0;i {out[i]=ch[i];}cout while(out[j]!=#)cout j++;}cout display_out(s,out);//caculate_array;}chardisplay_out(charout_ch[32],charch[]) {inttop=-1;inti=0,data[maxbuffer],n;intj=0;charsta[20];while(ch[i]!=#){if(isalnum(ch[i])){while(isalnum(ch[i])){out_ch[j]=ch[i];j++;i++;}out_ch[j]=;j++;else{switch(ch[i]){case+:case-:if(sta[top]==(||top==-1) {top++;sta[top]=ch[i];i++;}else{//j--;out_ch[j]=sta[top];j++;top--;//i++;}break;//break;case*:case/:if(sta[top]==*/) {out_ch[j]=sta[top];j++;//i++;top--;}else{top++;sta[top]=ch[i];i++;}break;//break;case(:top++;sta[top]=ch[i];i++;break;case):if(sta[top]==() {top--;i++;}if(top==-1){//cout }else{//while(sta[top]!=?(?){ out_ch[j]=sta[top];top--;j++;//}break;}break;/*case?#?:out_ch[j]=?#?; j++;break;*/default:cout ch[i]=#;j=0;break;}}}while(top!=-1){out_ch[j]=sta[top];j++;top--;}out_ch[j]=#;n=0;co(:编译原理中间代码生成实验报告)utwhile(out_ch[n]!=#){cout n++;}cout j=0;returnout_ch[maxbuffer];}五、实验结果:要求:自己给出3个测试用例,观察结果。

实验五-编译-用语法制导方式生成中间代码生成器

实验五-编译-用语法制导方式生成中间代码生成器

实验五-编译-⽤语法制导⽅式⽣成中间代码⽣成器实验5 ⽤语法制导⽅式⽣成中间代码⽣成器⼀、实验⽬的掌握语法制导定义和翻译的原理和技术,在语法分析器的基础上,加上语义分析,构造⼀个中间代码⽣成器。

⼆、实验内容在实验四⽣成的语法分析器基础上加⼊语义动作,将源程序翻译为对应的中间代码序列。

三、实验要求1. 个⼈完成,提交实验报告。

实验报告必须包括设计的思路,以及测试报告(输⼊测试例⼦,输出结果)。

2. 实验报告中给出采⽤测试源代码⽚断,及其对应的三地址码形式(内部表⽰形式可以⾃⾏考虑)。

例如,程序⽚断对应的中间代码为:四、实验过程本次实验运⽤flex和bison⼯具进⾏中间代码的⽣成。

并⾃动⽣成中间代码。

1.⾸先创建⼀个example⽂件夹,该⽂件夹中包含有flex.exe2.⽤⽂本编译器编辑相应的flex⽂件mylex.l,此次mylex.l可以在上次实验的l⽂件上做⼀些修改,再利⽤flex将l⽂件⽣成相应的lex.yy.c程序,mylex.l 的代码如下所⽰:mylex.l%{#include "myyacc.tab.h"%}delim [ \t\n\r]ws {delim}+letter [A-Za-z]digit [0-9]id {letter}({letter}|{digit})*integer {digit}+exponent E[+-]?{integer}number {integer}{exponent}?real integer(\.integer)?{exponent}?%option noyywrap%%"<"|"<="|">"|">="|"!="|"==" { filloperator(&yylval, yytext); return( REL); }if { return( IF ); }else { return( ELSE ); }while { return( WHILE ); }do { return( DO ); }for { return( FOR ); }switch { return( SWITCH ); }case { return( CASE ); } default { return( DEFAULT ); } break { return( BREAK ); } true { return( TRUE ); }false { return( FALSE ); } int { return( INT ); }long { return( LONG ); } char { return( CHAR ); } bool { return( BOOL ); } float { return( FLOAT ); } double { return( DOUBLE ); } "&&" { return( AND ); } "||" { return( OR ); } "!" { return( '!'); }"++" { return( INC ); } "--" { return( DEC ); } "+" { return( '+' ); } "-" { return( '-' ); } "*" { return( '*' ); } "/" { return( '/' ); } "=" { return( '=' ); } "{" { return( '{' ); }"}" { return( '}' ); }"[" { return( '[' ); }"]" { return( ']' ); }"(" { return( '(' ); }")" { return( ')' ); }";" { return( ';' ); }{ws} { }{id} { filllexeme(&yylval, yytext); return( ID ); }{number} { filllexeme(&yylval, yytext); return( NUMBER ); }{real} { filllexeme(&yylval, yytext); return( REAL ); }%%在代码中,先定义正则定义,即对letter,digit,专⽤符号, 空格进⾏声明;接着在转换规则中,定义⼀些识别规则的代码。

《编译系统设计实践》实验项目三:语法制导翻译与中间代码生成

《编译系统设计实践》实验项目三:语法制导翻译与中间代码生成

《编译系统设计实践》实验项目三:语法制导翻译与中间代码生成一、实验目的通过语法制导或翻译模式生成中间代码。

二、实验内容理解并应用课本的语法制导定义。

在自顶向下语法分析基础上设计语义规则(语法制导翻译),将源程序翻译为四元式输出,若有错误将错误信息输出。

三、设计思路1.分析过程主函数main 创建一个语法分析器和词法分析器,将词法分析器传入语法分析器中,调用语法分析器的program函数,program负责对输入流进行语法分析做出抽象语法树,然后生成中间代码。

2.程序结构目录四、测试报告1.测试一输入:int i;int j;float v;float x;float[100] a;while(true){do i=i+1;while(a[i]<v);do j=j-1;while(a[j]>v);if(i>=j) break;x=a[i];a[i]=a[j];a[j]=x;}输出:2.测试二:错误待翻译代码输入:i=i+1;int i;输出:3.测试3 :给出语法错误的代码输入:int [100]a;输出:五、实验分工在本次实验中,小组集体进行讨论分析,商定实现方法和完成目标。

小组讨论分析后由黄志杰、潘增滢同学负责编码调试,苏杰阳、陈明煜负责测试和检查审阅代码,指出并修改问题,刘晓君进行测试并撰写实验报告,最后小组同学再一起总结反思提出修改意见。

六、实验总结语法制导翻译的主要难点在于判断关键字,所以我们为判断关键字编写了独立的功能,但对于转化为三地址输出不是很了解,所以上网查阅资料借鉴了网上的代码,最后使用了函数的递归调用实现了,虽然最后的实现成果并不是十分完整,不够精确,但是对语法指导翻译有了一定的了解,也对编译原理有了更深刻的认识。

哈工大威海编译原理实验三语义分析与中间代码生成(DOC X页)

哈工大威海编译原理实验三语义分析与中间代码生成(DOC X页)

哈工大威海编译原理实验三语义分析与中间代码生成(DOCX页)哈尔滨工业大学(威海)计算机学院编译原理实验报告姓名院系计算机学院学号 090410任课教师指导教师实验地点宋健二楼机房实验时间实验三语义分析及中间代码生成实验名称同组人无预习报告(对实验主要内容的认识) 得分(1) 通过本次试验,我应该加深对于编译原理制导方案的理解,并且加深对于语法变换的所起到的作用;(2) 对于试验中要用到得中间代码的格式规范,也应该进一步的分析和掌握(3) 能够很好的使用到前面开发出来的词法分析器和语法分析器,将它们与语义分析器结合起来,跟好的更系统的掌握编译原理这门专业技能 (4) 关于符号表以及token串表的维护,现在终于使其有所作用实验内容(问题,思路,程序,结果) 得分(1)开发环境:vs2010(2)输入:在运行打开的软件下(win32格式),输入相应的代码(即要进行词法分析的字符串)(比如:int a;)(3)输出:在输入字符串后,按回车键后,既可以得到相应的词法分析的结果(比如:int a 的输入对应的输出如下:int a;首先对于词法分析打印出:Int --- key //关键字A ---str //字符串; ---bor //边界符号对于语法分析:Accept //编译语句分析成功对于输入字符串的语义分析和中间代码的生成如下中间代码:)(4)在相应的运行程序的文件夹中生成一个txt文件,用来存储生成的Token 链表(5)系统功能:(2) 开发平台(操作系统、设计语言):1、操作系统:windows 72、设计语言:c++3、编译器:vs2010(3) 设计方案;1) 主数据流图开始词法分析Token表的生成及修改语法分析修改token表语义分析语句是否为变量声明对语句按照文法的action表进行归约加一个四元式结点向下进行语义分析生成中间代码结束2) 主要数据结构:符号表、TOKEN串表等。

编译原理语义分析与中间代码生成实验报告

编译原理语义分析与中间代码生成实验报告

编译原理语义分析与中间代码生成实验报告专题6_语法制导翻译程序设计原理与实现技术***-***** 李若森计科1301一、实验目的语法制导的基本概念;目标代码结构分析的基本方法;赋值语句语法制导生成四元式的基本原理和方法;该过程包括语法分析和语义分析过程。

二、实验内容2.1 实验项目完成以下描述赋值语句和算术表达式文法的语法制导生成中间代码四元式的过程。

G[A]:A→V=EE→E+T|E-T|T T→T*F|T/F|F F→(E)|i V→i2.2 设计说明终结符号i为用户定义的简单变量,即标识符的定义。

2.3 设计要求(1) 设计语法制导翻译过程,给出每一产生式对应的语义动作;(2) 设计中间代码四元式的结构(暂不与符号表有关);(3) 输入串应是词法分析的输出二元式序列,即某算术表达式“专题1”的输出结果。

输出为输入串的四元式序列中间文件;(4) 设计两个测试用例(尽可能完备),并给出程序执行结果。

2.4 任务分析重点解决赋值语句文法的改写和语义动作的添加。

三、实现过程3.1 扩展文法G[s]:S→AA→V=EE→E+T|E-T|T T→T*F|T/F|F F→(E)|i V→i3.2 非终结符FOLLOW集FOLLOW(S) = { # } FOLLOW(A) = { # } FOLLOW(V) = { = }FOLLOW(E) = { +, -, ), # }FOLLOW(T) = { +, -, *, /, ), # } FOLLOW(F) = { +, -, *, /, ), # }3.3 LR(0)分析器的构造设DFA M的一个状态为i,该状态识别出的所有活前缀的有效项目集为Ci。

则DFA M的状态集Q={C0, C1, C2, … , Cn}=C。

C称为文法的LR(0)有效项目集规范族。

对Ci有三种操作:求文法的LR(0)有效项目集规范族C的算法:由上述算法可求得有效项目集规范族C={C0, C1, C2, … , C19}。

(精品)编译方法实验报告(中间代码生成器的设计)

(精品)编译方法实验报告(中间代码生成器的设计)

编译方法实验报告
2011年10月
一、实验目的
熟悉算术表达式的语法分析与中间代码生成原理。

二、实验内容
(1)设计语法制导翻译生成表达式的四元式的算法;
(2)编写代码并上机调试运行通过。

输入——算术表达式;
输出——语法分析结果;
相应的四元式序列。

(3)设计LL(1)分析法或LR(0)分析法的属性翻译文法,并根据这些属性翻译文法,使用扩展的语法分析器实现语法制导翻译。

三、实验原理及基本步骤
●算术表达式文法:
G(E): E →E ω0 T | T
T →T ω1 F | F
F → i | (E)
●文法变换:
G’(E) E →T {ω0 T}
T →F {ω1 F}
F → i | (E)
●属性翻译文法:
E →T {ω0“push(SYN,w)” T “QUAT”}
T →F {ω1“push(SYN, w)” F “QUAT”}
F →i “push(SEM, entry(w))” | (E)
其中:
push(SYN, w) —当前单词w入算符栈SYN;
push(SEM, entry(w)) —当前w在符号表中的入口值压入语义栈SEM;
QUAT —生成四元式函数
i.T = newtemp;
ii.QT[j] =( SYN[k], SEM[s-1], SEM[s], T); j++;
iii.pop( SYN, _ ); pop( SEM, _ ); pop( SEM, _ );
push( SEM, T );
●递归下降子程序:
数据结构:SYN —算符栈;
SEM —语义栈;。

编译原理教程实验报告

编译原理教程实验报告

一、实验目的本次实验旨在使学生通过编译原理的学习,了解编译程序的设计原理及实现技术,掌握编译程序的各个阶段,并能将所学知识应用于实际编程中。

二、实验内容1. 词法分析2. 语法分析3. 语义分析4. 中间代码生成5. 代码优化6. 目标代码生成三、实验步骤1. 词法分析(1)设计词法分析器,识别输入源代码中的各种词法单元;(2)使用C语言实现词法分析器,并进行测试。

2. 语法分析(1)根据文法规则设计语法分析器,识别输入源代码的语法结构;(2)使用C语言实现语法分析器,并进行测试。

3. 语义分析(1)设计语义分析器,检查语法分析后的语法树,确保语义正确;(2)使用C语言实现语义分析器,并进行测试。

4. 中间代码生成(1)设计中间代码生成器,将语义分析后的语法树转换为中间代码;(2)使用C语言实现中间代码生成器,并进行测试。

5. 代码优化(1)设计代码优化器,对中间代码进行优化,提高程序性能;(2)使用C语言实现代码优化器,并进行测试。

6. 目标代码生成(1)设计目标代码生成器,将优化后的中间代码转换为特定目标机的汇编语言;(2)使用C语言实现目标代码生成器,并进行测试。

四、实验结果与分析1. 词法分析实验结果:成功识别输入源代码中的各种词法单元,包括标识符、关键字、运算符、常量等。

2. 语法分析实验结果:成功识别输入源代码的语法结构,包括表达式、语句、程序等。

3. 语义分析实验结果:成功检查语法分析后的语法树,确保语义正确。

4. 中间代码生成实验结果:成功将语义分析后的语法树转换为中间代码,为后续优化和目标代码生成提供基础。

5. 代码优化实验结果:成功对中间代码进行优化,提高程序性能。

6. 目标代码生成实验结果:成功将优化后的中间代码转换为特定目标机的汇编语言,为程序在目标机上运行做准备。

五、实验心得1. 编译原理是一门理论与实践相结合的课程,通过本次实验,我对编译程序的设计原理及实现技术有了更深入的了解。

中间代码生成实验报告

中间代码生成实验报告

中间代码生成实验报告中间代码生成实验报告一、引言在计算机编程领域中,中间代码生成是编译器的一个重要阶段。

它将源代码转化为一种中间表示形式,以便于后续的优化和目标代码生成。

本实验旨在通过实现一个简单的中间代码生成器,深入理解编译器的工作原理和中间代码的作用。

二、实验背景中间代码是一种介于源代码和目标代码之间的表示形式。

它通常是一种抽象的、与机器无关的形式,具有较高的可读性和可维护性。

中间代码生成是编译器的一个重要阶段,它将源代码转化为中间代码,为后续的优化和目标代码生成提供基础。

三、实验目的本实验的主要目的是通过实现一个简单的中间代码生成器,加深对编译器工作原理的理解,并掌握中间代码的生成过程。

具体目标包括:1. 学习使用编程语言实现中间代码生成算法;2. 理解中间代码的数据结构和语义;3. 掌握将源代码转化为中间代码的过程;4. 分析和优化生成的中间代码。

四、实验设计与实现本实验采用C++语言实现一个简单的中间代码生成器。

具体步骤如下:1. 词法分析:使用词法分析器对输入的源代码进行扫描,将其划分为一个个的词法单元。

2. 语法分析:使用语法分析器对词法单元进行解析,构建语法树。

3. 语义分析:对语法树进行语义分析,检查语法的正确性,并生成中间代码。

4. 中间代码生成:根据语义分析的结果,生成对应的中间代码。

5. 中间代码优化:对生成的中间代码进行优化,提高执行效率和代码质量。

6. 目标代码生成:将优化后的中间代码转化为目标代码。

五、实验结果与分析经过实验,我们成功实现了一个简单的中间代码生成器,并生成了相应的中间代码。

通过对生成的中间代码进行分析,我们发现其中存在一些冗余和不必要的指令,可以进一步进行优化。

例如,可以通过常量折叠、死代码删除等技术,减少中间代码的长度和执行时间。

六、实验总结通过本次实验,我们深入理解了中间代码生成的过程和作用,并通过实践掌握了中间代码生成器的实现方法。

在实验过程中,我们遇到了一些困难和挑战,但通过不断的学习和尝试,最终取得了满意的结果。

实验五+中间代码生成器

实验五+中间代码生成器

实验5 中间代码生成器一、实验目的掌握语法制导定义和翻译的原理和技术,在语法分析器的基础上,加上语义分析,构造一个中间代码生成器。

二、实验内容在实验四用Yacc生成的语法分析器基础上加入语义动作,编写一个中间代码生成程序。

1.文法(见教材附录A.1,p394)program→ blockblock→{ decls stmts }decls →decls decl | εdecl →type id ;type →type [num] //数组可以不做| basic //四种基本数据类型int | float | char | bool stmts→stmts stmt | εstmt→id=expr;| if(bool)stmt| if( bool)stmt else stmt| while(bool)stmt| do stmt while(bool ) ;| break ;//break可以不做| blockbool →bool || join| joinjoin →join&& equality | equalityequality →equality == rel | equality != rel | relrel →expr < expr| expr <= expr| expr > expr| expr >= expr| exprexpr→ expr + term| expr - term| termterm→ term * unary| term / unary| unaryunary →!unary| - unary| factorfactor→ ( e xpr ) | id| num2.中间代码的形式见教材p221~222,若有必要,可以适当扩展(加以说明)。

三、实验过程3.1符号表的定义和相关函数struct SymbolElemstruct SymbolListSymbolList CreateSymbolList( SymbolList PrevList, int StartAddr )/*创建并返回一个新的符号表(SymbolList就是书上的Env),PrevList是其的上一层符号表*/void DestroySymbolList( SymbolList List )struct SymbolElem * LookUpSymbolList( SymbolList List, char * IdName )/*在符号表List中查找是否存在标识符IdName,如果存在,则返回该结点指针,否则返回空*/struct SymbolElem * LookUpAllSymbolList( SymbolList List, char * IdName )/*从符号表List开始并不断地往上一层符号表中查找是否存在标识符IdName,如果存在,则返回该结点指针,否则返回空*/struct SymbolElem * AddToSymbolList( SymbolList List, char * IdName,int IdType, int Width )/*创建一个新的符号结点,并添加到符号表中,而后返回该结点指针*/3.2常数表的定义和相关函数union ConstVal/*存放一个常数*/struct ConstElem/*常量表*/struct ConstList/*创建并返回常量表*/void CreateConstList( int StartAddr )void DestroyConstList( void )/*在常量表ConstList中查找是否存在常量,如果存在,则返回该结点指针,否则返回空*/struct ConstElem * LookUpConstList( int ConstType, union ConstVal ConstValue, int Width )/*创建一个新的常数结点,并添加到常数表中,而后返回该结点指针*/struct ConstElem * AddToConstList( char * Str, int ConstType, union ConstVal ConstValue, int Width )3.3四元式的定义和函数/*四元式数据结构*/struct Quadruple/*四元式表*/struct QuadTablevoid CreateQuadTable(int StartAddr)void DestroyQuadTable( void )/*当Arg1是变量或临时变量时,Arg1Name是该变量的名称,用于演示时使用,其余参数类同*/int Gen( int Op, int Arg1, int Arg2, int Arg3, char *Arg1Name, char *Arg2Name, char *Arg3Name )/*把四元式所对应的三地址代码写入到文件中*/void WriteQuadTableToFile( const char * FileName )四、实验结果源程序片断运行状态图运行结果本次实验很难,做了很久都没做出来。

编译原理-分析报告材料中间代码生成程序

编译原理-分析报告材料中间代码生成程序

实验报告课程名称编译原理实验学期至学年第学期学生所在系部年级专业班级学生姓名学号任课教师实验成绩计算机学院制开课实验室:年月日实验题目分析中间代码生成程序一、实验目的分析PL/0编译程序的总体结构、代码生成的方法和过程;具体写出一条语句的中间代码生成过程。

二、设备与环境PC兼容机、Windows操作系统、Turbo Pascal软件等。

三、实验内容1.分析PL/0程序的Block子程序,理清PL/0程序结构和语句格式。

画出Block子程序的流程图,写出至少两条PL/0程序语句的语法格式。

2.分析PL/0程序的Block子程序和Gen子程序,了解代码生成的方法和过程。

使用概要算法来描述语句的代码生成过程。

3.自己编写一个简单的PL/0程序,能够正确通过编译,得到中间代码。

列出自己编写的源程序和编译后得到的中间代码。

4.从中选择一个语句或表达式,写出代码生成的过程。

要求从自己的源程序中选择一条语句,结合这条语句写出语义分析和代码生成过程。

在描述这个过程中,要说清楚每个功能有哪个子程序的哪条语句来完成,说清楚语句和参数的含义和功能。

四、实验结果及分析(一)程序标注levmax = 3; { max depth of block nesting } { 最大允许的块嵌套层数}{ 语法分析过程block }{ 参数:lev:这一次语法分析所在的层次}{ tx:符号表指针}{ fsys:用于出错恢复的单词集合}procedure block(lev, tx: integer; fsys: symset);vardx: integer; { data allocation index } { 数据段内存分配指针,指向下一个被分配空间在数据段中的偏移位置}tx0: integer; { initial table index } { 记录本层开始时符号表位置}cx0: integer; { initial code index } { 记录本层开始时代码段分配位置}{ 登陆符号表过程enter }procedure enter(k: object1);begin { enter object into table } { 参数:k:欲登陆到符号表的符号类型}tx := tx + 1; { 符号表指针指向一个新的空位}with table[tx] do { 开始登录}beginname := id; { name是符号的名字,对于标识符,这里就是标识符的名字}kind := k; { 符号类型,可能是常量、变量或过程名}case k of { 根据不同的类型进行不同的操作}constant: { 如果是常量名}beginif num > amax then { 在常量的数值大于允许的最大值的情况下}beginerror(31); { 抛出31号错误}num := 0; { 实际登陆的数字以0代替}end;val := num { 如是合法的数值,就登陆到符号表}end;variable: { 如果是变量名}beginlevel := lev; { 记下它所属的层次号}adr := dx; { 记下它在当前层中的偏移量}dx := dx+1; { 偏移量自增一,为下一次做好准备}end;procedur: { 如果要登陆的是过程名}level := lev { 记录下这个过程所在层次}EndEndend { enter };{ 登录符号过程没有考虑到重复的定义的问题。

实验三语义分析及中间代码生成

实验三语义分析及中间代码生成

实验三语义分析及中间代码生成一、实验目的通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译方法。

二、实验内容实现简单的高级语言源程序的语义处理过程。

三试验要求(一)程序设计要求(1)目标机:8086及其兼容处理器(2)中间代码:三地址码或者四元式(3)设计结果:语法分析树(节点具有属性)、三地址码表、符号表、TOKEN串表(4)语义分析内容要求:1)变量说明语句2)赋值语句3)控制语句(任选一种)(5)其它要求:1)将词法分析(扫描器)作为子程序,供语法语义程序调用;2)使用语法制导的语义翻译方法;3)编程语言自定;4)最好提供源程序输入界面;5)目标代码生成暂不做;6)编译后,可查看TOKEN串、语法分析树、符号表、三地址码表;7)主要数据结构:产生式表、符号表、语法分析树、三地址码表。

四、实验设计(1)系统功能(包括各个子功能模块的功能说明);可对一段包含加减乘除括号的赋值语句进行语法分析,其必须以$为终结符,语句间以;隔离,判断其是否符合语法规则,依次输出判断过程中所用到的产生式,并输出最终结论,若有错误可以报错并提示错误所在行数及原因(2)开发平台(操作系统、设计语言);Windows 7,Microsoft Visual C++ 6.0(Dos),C++。

(3) 数据结构struct token//词法 token结构体{int code;//编码int num;//递增编号token *next;};token *token_head,*token_tail;//token队列struct str//词法 string结构体{int num;//编号string word;//字符串内容str *next;};str *string_head,*string_tail;//string队列struct ivan//语法产生式结构体{char left;//产生式的左部string right;//产生式的右部int len;//产生式右部的长度};ivan css[20];//语法 20个产生式struct pank//语法 action表结构体{char sr;//移进或归约int state;//转到的状态编号};pank action[46][18];//action表int go_to[46][11];//语法 go_to表struct ike//语法分析栈结构体,双链{ike *pre;int num;//状态int word;//符号编码ike *next;};ike *stack_head,*stack_tail;//分析栈首尾指针struct L//语义四元式的数据结构{int k;string op;//操作符string op1;//操作数string op2;//操作数string result;//结果L *next;//语义四元式向后指针L *Ltrue;//回填true链向前指针L *Lfalse;//回填false链向前指针};L *L_four_head,*L_four_tail,*L_true_head,*L_false_head;//四元式链,true链,false链struct symb//语义输入时符号表{string word;//变量名称};(4)五、实验结果六、实验总结通过本次实验,我了解了当我编写的代码在经过编译过程中所进行的处理,分为词法分析,语法分析,语义分析和中间代码生成,生成的中间代码经过代码生成器变形成了我们常提到的目标程序.语义分析和中间代码生成会有静态检查:包括类型检查、控制流检查、唯一性检查和关联名字检查等等一判断源程序是否符合语言规定的语法和语义要求。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、实验目的通过在实验二的基础上,增加中间代码生成部分,使程序能够对实验二中的识别出的赋值语句,if语句和while语句进行语义分析,生成四元式中间代码。

二、实验方法实验程序由c语言完成,在Turboc 2.0环境中调试通过。

语义分析程序的基本做法是对文法中的每个产生式分别编写一个语义分析子程序,当程序语法部分进行推倒或规约时,就分别调用各自的语义分析程序。

当语法分析结束时,语义分析也就结束了。

在本实验程序中,当语法分析部分识别出语确的句子时,就进入content函数(当语法分析识别出不正确的句子时,不进入content函数,也就是不进行语义分析),然后根据句子的类型进行分类,进入不同的语义处理部分。

对于赋值语句,关键是产生正确的处理算术表达式E的四元式。

程序中的ec函数的功能就是产生算术表达式的四元式,在ec函数中使用了两个栈idshed,opshed,分别是算术表达式的数据栈和符号栈。

每次提取一个数字和一个算符,然后将算符与与栈顶算符进行优先级比较,优先级高则将单前数字和算符进栈,低或者相等的话则将当前栈顶元素进行合并,产生四元式。

直至整个算术表达式结束。

其中还有一些细节问题,具体的做法可以参看程序。

对于实验给定的if语句的文法格式,条件判断式C只中可能是>或者<=两种关系,不可能是布尔表达式,这样程序就简单的多了。

通过ec函数可以产生条件判断式C中的E的四元式,然后只要加上转向四元式就可以了。

本实验程序中只给出真出口的转向四元式,没有给出假出口的转向四元式,这在实际中是不可以的,但在本实验中,实际上是对每条独立的语句进行语法分析,给出假出口转向四元式实际上意义不大,而且假出口转向语句的转移目标必须要到整个语句分析结束以后才可以知道,这样就要建立栈,然后回填,这样会使程序复杂很多,所以没有加上假出口转向四元式。

对于while语句,具体的做法和if语句差不多,所不同的是当while语句结束时,要多出一条无条件转向四元式,重新转到条件判断式C的第一条四元式。

当要产生无条件转向四元式时,它的转向目标C的第一条四元式已经产生了,所以具体的做起来是不太困难的。

只要记下当前while中的C的第一条四元式的位置,填上就可以了。

整个程序的结束是当读入“. ”时,程序就中止。

程序中还有很多细节问题,具体的可以后面的附录:程序的完整代码。

三、测试程序ff:=6+6*6-;if sl>89+56*67then f:=7*7+4;ff:=6+6*6-6%4+8;if sl+78*76>89*56+67then while a-7>98+45*45 do f:=7*7+4;.四、运行结果首先对测试程序进行语法分析,识别出正确的句子,当识别出正确的句子时,就对当前句子进行语义分析,而语法不正确的句子不进行语义分析。

ff:=6+6*6- Error(4):Except ID or NUM; Error(2):Syntax errorif sl>89+56*67 then f:=7*7+4; success!!!(1) [ *, 56, 67, T1 ](2) [ +, 89, T1, T2 ](3) [j>, sl, T2, (4) ](4) [ *, 7, 7, T3 ](5) [ +, T3, 4, T4 ](6) [ :=, T4, -, f ]ff:=6+6*6-6%4+8; success!!!(7) [ *, 6, 6, T5 ](8) [ +, 6, T5, T6 ](9) [ %, 6, 4, T7 ](10) [ -, T6, T7, T8 ](11) [ +, T8, 8, T9 ](12) [ :=, T9, -, ff ]if sl+78*76>89*56+67 then while a-7>98+45*45 do f:=7*7+4;success!!!(13) [ *, 78, 76, T10 ](14) [ +, sl,T10, T11 ](15) [ *, 89, 56, T12 ](16) [ +,T12, 67, T13 ](17) [j>, T11, T13, (18) ](18) [ -, a, 7, T14 ](19) [ *, 45, 45, T15 ](20) [ +, 98,T15, T16 ](21) [j>, T14, T16, (22) ](22) [ *, 7, 7, T17 ](23) [ +,T17, 4, T18 ](24) [ :=, T18, -, f ](25) [j, _, _, (18)]. Error(2):Syntax error五、实验小结终于完成了编译原理的三次实验,这几次实验使我们更彻底地巩固了编译原理。

从詷法分析到语法分析直到这次的中间代码都是看似简单的基础知识,却花了不少时间对课本多次反复研究、请教学习,进行深层次地探讨才找出编程时出现的种种问题。

还有很多程序方面很细节的问题,很容易被突略,却往往又是关键。

总地来说,虽然实验做得很辛苦,但真的可以从实验当中学习到很多,认识到很多。

并对编译理解也透彻了许多,比较清晰地掌握了编译程序的原理和方法。

附录:#include<string.h>#include<stdio.h>#include<stdlib.h>#define reser 20char *charstring="abcdefghijklmnopqrstuvwxyz";char *numstring="0123456789";char *strstring="abcdefghijklmnopqrstuvwxyz0123456789";char reserve[reser][10];char idshed[40][10],opshed[40][10];char token[15],id[15],sym[15];char line[80],tempp[240];char ch,ch1,temp,tem;char tx[10];char tn[4],signt1[20],signt2[20],ju[20];int cc,ii,k,num,kind,t,e4=0,e3=0,judge=1,row1=0;int startc,idsh=0,opsh=0,tt=1,nn=1,signwh,over=0,adds=0,whs=0,pp=0;int li=0;char filename[15];FILE *fp;void getch(){if(li==0) {if (cc==ii){cc=1; ii=0;if (row1==1) fseek(fp,-1,1); /*读行首字符将指针退回一格,若是整个文本的开头,则不需要*/line[0]=fgetc(fp);row1=1;while(((temp=fgetc(fp))!='\n') && (temp!=EOF)){ line[cc]=temp;cc++;tempp[pp]=temp;pp++;}line[cc]=' '; /*将缓冲带后加上一个空字符,以便行和行之间号区分*/cc++;tempp[pp]=' ';pp++;while(((temp=fgetc(fp))=='\n') && (temp!=EOF)); /* 跳过空行*/ line[cc]='\0';}tem=line[ii];ii++;ch=tem;}else{ch=tempp[pp];pp++;}}void getnbc(){getch();while (ch==' ')getch();if (ch=='{'){do{getch();}while( ch=='}');getnbc();}}void retract(){ii--;}void ret(){pp--;}int jchar(char ch){ /* 判断ch是不是字母*/ if(strchr(charstring,ch)==0)return 0;else return 1;}int jnum(char ch){ /* 判断ch是不是数字*/ if(strchr(numstring,ch)==0)return 0;else return 1;}int jstr(char ch){ /* 判断ch是不是字母或数字*/ if(strchr(strstring,ch)==0)return 0;else return 1;}void advance(){getnbc();kind=0;if (jchar(ch)==1){k=0;do {if(k<15){ token[k]=ch; k++;}getch(); }while(jstr(ch)==1);if (li==0)retract();else ret();token[k]='\0'; /*截去token中的无用字符*/ strcpy(id,token);for(t =0;t<=20;t++){if(strcmp(reserve[t],id)==0)break;}if ( t<=20 ) kind=t ;else kind=21;strcpy(sym,id);}elseif (jnum(ch)==1){k=0;do{if ( k<15 ) {token[k]=ch; k++;}getch();}while( jstr(ch)==1);if (li==0)retract();else ret();kind=22;token[k]='\0';strcpy(sym,token);}else{if(ch=='.') kind=26;k=0;do{sym[k]=' '; k++;}while(k!=15);sym[0]=ch;sym[1]='\0';}}void error(int n){judge=0; /*出错退出,将judge=0*/switch(n){case 0:{printf(" Error(0):Expect ':' \n"); break;}case 1:{printf(" Error(1):Expect '=' \n"); break;}case 2:{printf(" Error(2):Syntax error \n");break;}case 3:{printf(" Error(3):Except Operater \n");break;}case 4:{printf(" Error(4):Except ID or NUM \n");break;}case 5:{printf(" Error(5):Except ';' \n");break;}case 6:{printf(" Error(6):Except '<' or '>'\n");break;}case 7:{printf(" Error(7):Except '=' \n" );break;}case 8:{printf(" Error(8):Except 'then' \n");break;}case 9:{printf(" Error(9):Except Condition Expression\n ");break;} case 10:{printf(" Error(10):Except 'do' ");break;}default:; }}void e(){advance();if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)||(strcmp(sym,"*")==0)||(strcmp(s ym,"%")==0)){ printf("%s",sym);advance();if((kind==21) || (kind==22)){ /* kind为21,22分别表示的是标志符和数字*/ printf("%s",sym);e();}else { e4=1 ;error(4);} } /*出错退出,e4=1*/}void c(){advance();if((kind==21) || (kind==22)){printf("%s",sym);e();if(e4==1); /*e4的作用是判断程序从e()中是不是出错退出*/ else {if(strcmp(sym,">")==0){printf("%s",sym);advance();if((kind==21) || (kind==22)) {printf("%s",sym);e();}else{error(4);}}else {if(strcmp(sym,"<")==0){printf("%s",sym);advance();if(strcmp(sym,"=")==0){printf("%s",sym);advance();if((kind==21) || (kind==22)){printf("%s",sym);e();}else{error(4);}} else{error(7);}} else{error(6);}}}}else{e3=1; error(9);} /*出错退出,e3=1*/}void statement(){if(judge==1) /*judge的作用为判断程序是不是出错退出,若是,则无需advance()*/advance();switch (kind){case 21:{ /* id */printf("%s",sym);advance();if(strcmp(sym,":")==0){ printf("%s",sym);advance();if(strcmp(sym,"=")==0){printf("%s",sym);advance();if((kind==21) || (kind==22)){printf("%s",sym);e();if(e4==1) ;else{if(strcmp(sym,";")==0){printf("%s",sym);judge=1;printf(" success!!!\n");startc=1;}else error(5); }e4=0; /*将e4重新置为0,以免对下面程序有影响*/ }else error(4);} else{ error(1);}} else { error(0);}break;}case 8:{ printf("%s ",sym); /* if */c();if(e4==1);else{ if(e3==1); /*e3的作用是判断程序从c()中是不是出错退出*/ else{if(strcmp(sym,"then")==0){printf(" %s ",sym);statement();}else{error(8);}}e3=0; /*将e3重新置为0,以免对下面程序有影响*/}e4=0;break;}case 19:{ /* while */printf("%s ",sym);c();if(e4==1);else{ if(e3==1);else{if(strcmp(sym,"do")==0){printf(" %s ",sym);statement();}else{error(10);}}e3=0;}e4=0;break;}default: { printf("%s ",sym);error(2);judge=1;break;} }}void pushid(){strcpy(idshed[idsh],sym);idsh++;}void pushop(){strcpy(opshed[opsh],sym);opsh++;}void gen(char op[10],char a[10],char b[10]){printf("(%d) [ %2s,%3s,%3s, T%d ]\n",nn,op,a,b,tt);tt++;nn++;itoa(tt-1,tn,10);strcpy(tx,"T");strcat(tx,tn);}void ec(){advance();pushop();advance();pushid();if((strcmp(opshed[opsh-1],"*")==0)||(strcmp(opshed[opsh-1],"%")==0)){gen(opshed[opsh-1],idshed[idsh-2],idshed[idsh-1]);opsh--;idsh=idsh-1;strcpy(idshed[idsh-1],tx);} else{if((strcmp(opshed[opsh-1],"+")==0)||(strcmp(opshed[opsh-1],"-")==0)){ adds=1;if((strcmp(opshed[opsh-2],"+")==0)||(strcmp(opshed[opsh-2],"-")==0)){gen(opshed[opsh-2],idshed[idsh-3],idshed[idsh-2]);strcpy(idshed[idsh-2],tx);}} }advance();if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)||(strcmp(sym,"*")==0)||(strcmp(sym,"%")==0)){if (li==0)retract();else ret();ec(); }}void content(){int reu;reu=nn;switch(kind){ case 21:{advance();advance();advance();pushid();advance();if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)||(strcmp(sym,"*")==0)||(strcm p(sym,"%")==0)){if (li==0)retract();else ret();ec();if (adds==1)gen(opshed[opsh-1],idshed[idsh-2],idshed[idsh-1]);adds=0;printf("(%d) [ :=, %s, -, %s ]\n",nn,tx,idshed[0]);nn++;opsh=0;}else{printf("(%d) [ :=, %s, -, %s ]\n",nn,idshed[1],idshed[0]);nn++;}break;}case 8:{idsh=0;opsh=0;advance();pushid();advance();if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)||(strcmp(sym,"*")==0)||(strcm p(sym,"%")==0)){if (li==0)retract();else ret();ec();if(adds==1)gen(opshed[opsh-1],idshed[idsh-2],idshed[idsh-1]);adds=0;strcpy(signt1,tx);idsh=0;opsh=0;}else{strcpy(signt1,idshed[0]);}if(strcmp(sym,">")==0)strcpy(ju,"j>");else{strcpy(ju,"j<=");advance();}idsh=0;opsh=0;advance();advance();if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)||(strcmp(sym,"*")==0)||(strcm p(sym,"%")==0)){if (li==0)retract();else ret();ec();if (adds==1)gen(opshed[opsh-1],idshed[idsh-2],idshed[idsh-1]);adds=0;strcpy(signt2,tx);idsh=0;opsh=0;}else{strcpy(signt2,idshed[0]);}printf("(%d) [%s, %s, %s, (%d) ]\n",nn,ju,signt1,signt2,nn+1);nn++;advance();idsh=0;opsh=0;if(kind==21) pushid();content();break;}case 19:{idsh=0;opsh=0;advance();pushid();advance();if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)||(strcmp(sym,"*")==0)||(strcm p(sym,"%")==0)){if (li==0)retract();else ret();ec();if(adds==1)gen(opshed[opsh-1],idshed[idsh-2],idshed[idsh-1]);adds=0;strcpy(signt1,tx);idsh=0;opsh=0;}else{strcpy(signt1,idshed[0]);}if(strcmp(sym,">")==0)strcpy(ju,"j>");else{strcpy(ju,"j<=");advance();}idsh=0;opsh=0;advance();pushid();advance();if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)||(strcmp(sym,"*")==0)||(strcm p(sym,"%")==0)){if (li==0)retract();else ret();ec();if (adds==1)gen(opshed[opsh-1],idshed[idsh-2],idshed[idsh-1]);adds=0;strcpy(signt2,tx);idsh=0;opsh=0;}else{strcpy(signt2,idshed[0]);printf("(%d) [%s, %s, %s, (%d) ]\n",nn,ju,signt1,signt2,nn+1);nn++;advance();idsh=0;opsh=0;if(kind==21) pushid();content();printf("(%d) [j, _, _, (%d)]\n",nn,reu);nn++;break; }default:{break; }}}main(){strcpy(reserve[8],"if");strcpy(reserve[19],"while");strcpy(reserve[4],"do");strcpy(reserve[16],"then");printf("Please Input Source Program Filename:");scanf("%s",filename);fp=fopen(filename,"r");cc=0;ii=0;ch='\0';while (kind!=26) /*kind==26为读到了'.',程序结束*/{startc=0;pp=0;statement();li=1;if(startc==1){pp=0;advance();pushid();content(); }} }。

相关文档
最新文档