语法制导翻译与生成中间代码附代码

合集下载

编译原理课件05语法制导翻译技术和中间代码生成

编译原理课件05语法制导翻译技术和中间代码生成

5.4 中间代码
四元式的特点: 1. 四元式出现的顺序和语法成份的计值 顺序相一致. 2. 四元式之间的联系是通过临时变量实 现的,这样易于调整和变动四元式. 3. 便于优化处理.
5.4 中间代码
编译系统中,有时将四元式表示成另一 种更直观,更易理解的形式——三地址代 码或三地址语句. 三地址代码形式定义为: result := arg1 OP arg2 三地址语句:语句中是三个量的赋值语句, 三地址语句 每个量占一个地址.
5.5 自下而上的语法制导翻译
例3 简单算术表达式翻译到四元式的 语义描述 例如,设有简单算术表达式的文法: E→E+E | E*E | (E) | i
T R / S T
c S a c
c R S
输入是bR / bTc / bSc /ac 输出为: 1 4 5 314 24 31 给出相应语义动作(翻 译方案) S→bTc { print "1"} { print "2"} S→a R T→R { print "3"} R→R/S { print "4"} R→S { print "5"}
5.1 概述
例如: 表达式 A+B*C 对运算对象进行类型检查, 对变 量进行先定义后使用检查 执行真正的翻译 如果静态语义正确, 语义处理则要执 行真正的翻译, 即生成程序的某种中间 代码的形式或直接生成目标代码.
5.1 概述
目前多数编译程序进行语义分析的方 法是采用语法制导翻译法 .它不是一种 采用语法制导翻译法 形式系统, 但它比较接近形式化. 语法制导翻译法使用属性文法为工具 来描述程序设计语言的语义.
5.4 中间代码

第八章 语法制导翻译和中间代码生成

第八章 语法制导翻译和中间代码生成

目标代码
5
语义分析
语义分析的任务:在词法分析和语法分析的基础上,
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
分析所写源程序的含义,在理解含义的基础上为生成 相应的目标代码作好准备或直接生成目标代码。 1)静态语义检查 例:类型检查、运算、维数、越界 2)语义翻译(具体的动作) 例:语句的翻译(中间代码或目标代码生成)
16
简化定义
对每个产生式,设属性定义性出现的集合为
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
若Xi是产生式左部非终结符(即i=0),则称属性 Xi.a是综合属性(Synthesized Attributes) 若Xi出现在产生式的右部(即i≠0 ),则称Xi.a是 继承属性(Inherited Attributes)
2
教学内容
第一节
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
属性文法 语法制导翻译概论 中间代码的形式 简单赋值语句的翻译 布尔表达式的翻译 控制语句的翻译 说明语句的翻译 数组和结构的翻译
3
第二节 第三节 第四节 第五节 第六节 第七节 第八节
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
2.组成
语法树上的每个节点的所有属性在依赖图上各有 一个节点,如果属性y依赖于属性x,那么从x的节点 到y的节点有一条有向边。 【注】如果语法树一节点的属性y依赖某个节点的属 性x,那么属性y的语义产生式的计算必须在属性x的 语义产生式的计算之后进行。 24
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
13
盛 威 网 : 专 业 的 计 算 机 学 习 网 站
3、文法规则number→number digit ,表明文法的个 数不止一个。我们必须表示出这个文法规则左边符 号的值和右边符号的值之间的关系。通过使用下标 进行区分,将文法写成如下形式: number1→number2 digit

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

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

编译方法实验报告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++;}六、总结与分析我们知道, 定义一种语言除了要求定义语法外, 还要求定义语义, 即对语言的各种语法单位赋予具体的意义。

第5章 语法制导翻译和中间代码生成

第5章  语法制导翻译和中间代码生成

剩余串 3+ 45# +45# +45# +45# +45# 5# 5# 5# 5# 5# #
主要动作
r6 r4 r2
r6 r4
r6 # # r3 r1 acc
表达式3 + 4 5的语法语义分析和计值过程
§5.3
中间语言
所谓中间语言,也称中间代码,是复杂性介 于源程序语言和机器语言的一种记号系统。一般 来说,快速编译程序直接生成目标代码,没有将 中间代码翻译成目标代码的额外开销。但是为了 使编译程序结构在逻辑上更为简单明确,使生成 的的目标代码更为高效,通常采用中间语言。 编译程序所使用的中间语言形式较多。常见 的逆波兰式、三元式、四元式和树形表示等。来自bcd
3. 间接三元式 为了尽量不改变三元式表,可以另设一张间 接码表来表示有关三元式在三元式表的 计值顺序。用这种方法获得的中间代码 称为间接三元式。
例如,表达式a := x+y z b := t-y z 的间接三元式表示如图所示。
三元式列表 (1)( ,y,z) (2)(+,x,(1)) (3)(:=,a,(2)) (4)(-,t,(1)) (5)(:=,—,(4))
§5.4 自底向上语法制导翻译
语法制导翻译分为自底向上和自底向下两种。 自底向上语法制导翻译方法就是在自底向上语法 分析过程中逐步执行语义规则。也就是在每次归 约的同时执行相应的语义动作。
5.4.1 简单算术表达式和赋值语句的翻译
简单算术表达式和赋值语句是指不含数组 元素、记录等复杂数据结构的算术表达式和赋值 语句。
简单算术表达式求值的属性文法。 例5.1 :
规则 1.S→E 2.E→E1+T 3.E→T 4.T→T1 F 5.T→T1 6.F→(E) 7.F→digit 语义规则 print(E.val) E.val := E1.val+T.val E.va1 := T.valv T.val := T1.val F.val T.val := T1.val F.val := E.val F.val := digit.lexval

第08章语法制导翻译和中间代码生成

第08章语法制导翻译和中间代码生成
28
常用的中间语言
• 三地址代码(四元式) 三地址代码(四元式) • 语法结构树(三元式) 语法结构树(三元式) • 后缀式
特点
• 形式简单、语义明确、便于翻译 形式简单、语义明确、 • 独立于目标语言
29
三元式和树形表示
• 每个三元式由三个部分组成,分别是:算符op, 每个三元式由三个部分组成,分别是:算符op, op 第一运算对象ARG1和第二运算对象ARG2 ARG1和第二运算对象ARG2。 第一运算对象ARG1和第二运算对象ARG2。运算 对象可能是源程序中的变量, 对象可能是源程序中的变量,也可能是某个三 元式的结果,用三元式的编号表示。 元式的结果,用三元式的编号表示。 • 表达式的树形表示很容易实现:简单变量或常 表达式的树形表示很容易实现: 数的树就是该变量或常数自身,如果表达式e1 数的树就是该变量或常数自身,如果表达式e1 e2的树分别为T1和T2,那么e1+e2 e1*e2, 的树分别为T1 e1+e2, 和e2的树分别为T1和T2,那么e1+e2,e1*e2, e1的树分别为 的树分别为: -e1的树分别为:
9
–lexval 是单词 digit 的属性 lexval
例8-3 3*5+4 的
语法树与属性计算
L Print(19) E.val=19
E.val=15 T.val=15 T.val=3 F.val=3 digit.lexval=3 *

T.val=4 F.ቤተ መጻሕፍቲ ባይዱal=4
F.val=5 dgit.lexval=5
• 用中间语言过渡的好处: 用中间语言过渡的好处:
–便于编译系统的实现、移植、代码优化 便于编译系统的实现、移植、 便于编译系统的实现

编译第8章

编译第8章
–是一种接近形式化的语义描述方法 –长于描述静态语义、短于描述动态语义 –每个语法符号有相应的属性符号 –每个产生式有相应的计算属性的规则:
• 属性变量=属性表达式
1、属性文法定义
属性文法(attribute grammar)是一个三元 组:A=(G,V,F),其中 G:是一个上下文无关文法 V:有穷的属性集,每个属性与文法的一个终结符或非 终结符相连,这些属性代表与文法符号相关信息, 如它的类型、值、代码序列、符号表内容等等 .属 性与变量一样,可以进行计算和传递。属性加工 的过程即是语义处理的过程。 F:关于属性的属性断言或一组属性的计算规则(称为 语义规则) . 断言或语义规则与一个产生式相联,只 引用该产生式左端或右端的终结符或非终结符相 联的属性.
addtype
id3
addtype
例5-4:real id1,id2,id3 的分析树和属性计算
8.3 中间代码的形式
何谓中间代码: 源程序的一种内部表示,不依赖目标机的 结构,易于机械生成目标代码的中间表示。 为什麽要此阶段 逻辑结构清楚; 利于不同目标机上实现同一种语言; 利于进行与机器无关的优化; 这些内部形式也能用于解释;
• 语义处理
–例:变量的存储分配 –例:表达式的求值 –例:语句的翻译(中间代码的生成)
• 总目标:生成等价的中间代码
语义处理方法
• 对应每一个产生式编制一个语义子程序, 当一个产生式获得匹配时,调用相应的 语义子程序实现语义检查与翻译。 • 在产生式的右部的适当位置,插入相应 的语义动作,按照分析的进程,执行遇 到的语义动作。
8)若把语义子程序改成产生某种中间代 码的动作,就能在语法分析制导下,随 着分析的进展逐步生成中间代码。 9)若把语义子程序改成产生某种机器的 汇编语言指令,就能随着分析的进展逐 步生成某机器的汇编语言代码。

语法制导翻译和中间代码生成

语法制导翻译和中间代码生成
addtype(id.entry,L.in)
继承属性L.in
语 义 规 则
语句: real id1, id2, id3 的分析树,采用自上而下的分析方法
产 生 式
D TL
T int
T real
L L1,id
L id
L.in:=T.type
T.type=integer
F.val=3
F.val=5
digit.lexval=4
digit.lexval=5
digit.lexval=3
+
*
3*5+4的带注释的分析树
如果一个语法制导定义仅仅使用综合属性,则称这种语法制导定义为S属性定义。通常采用自底向上的方法对其分析树加注释,即从树叶到树根,按照语义规则计算每个节点的属性值。
表达式文法 E→T+T| T or T T → n | true | false
E → T1 + T2 { T1.type = int AND T2.type = T1. type E.type :=int } E → T1 or T2 { T1.type = bool AND T2.type= T1.type E.type :=bool } T → n { T.type := int } T → true { T.type := bool } T → false { T.type := bool }
T.type:=real
L1.in:=L.in
addtype(id.entry,L.in)
addtype(id.entry,L.in)
D
L.in= real
L.in= real
L.in= real
T.type=real

语法制导翻译和中间代码生成【共50张PPT】

语法制导翻译和中间代码生成【共50张PPT】

例 完成类型检查的属性文法
1) E→T1+T2{T1.t=int AND T2.t=int}
2) E→T1 or T2 {T1.t=bool AND T2.t=bool}
3) T→num
{T.t :=int}
4) T→true {T.t :=bool}
5) T→false
{T.t :=bool}
6.1 属性文法(续)
四元式(续)
四元式的优点:
四元式比三元式更便于优化 优化要求改变运算顺序或删除某些运算,引起编号的变化。 三元式通过编号引用中间结果,编号的变化引起麻烦;四元 式通过临时变量引用中间结果,编号变化无影响。
四元式对生成目标代码有利
四元式表示很类似于三地址指令,很容易转换成机器代 码。
四元式(续)
3) E→T
{ E.val :=T.val }
4) T→T1*F { T.val :=T1.val * F.val }
5) T→F
{ T.val :=F.val }
6) F→(E) { F.val :=E.val }
7) F→digit { F.val :=digit.lexval }
E.val、T.val、F.val都是综合属性
每个使用性标识符是否都有声明? 运算符的分量类型是否相容? 赋值语句的左右部的类型是否相容?
➢ 赋值语句的翻译目标:
在赋值语句右部表达式产生的四元式序列后加一 条赋值四元式
简单赋值语句到四元式的翻译
考虑如下文法描述的简单赋值句的翻译: A→i:=E E→E+E|E*E|-E|(E)|i (6.1)
:=
a
+
叶子结点代表运算量, 非叶子结点代表运算符
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《编译系统设计实践》实验项目三:语法制导翻译与生成中间代码学号:姓名:年级:学院: 数计学院专业: 计算机本组其它成员:学号姓名学号姓名实验时间:2016-2017学年第一学期任课教师:一、实验目的通过语法制导或翻译模式生成中间代码。

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

三、设计思路1.分析过程主函数,读取文件,存入字符串数组,调用语义分析,判断关键字,调用相应的语义规则(这里只有if与while与赋值语句),赋值语句调用表达式处理,if语句调用条件表达式处理,while也就是调用表达式处理,然后就是一个递归过程,不断的递归调用,按序输出三地址语句。

在本例程序中选用expr及num作为运算数。

2.主要函数string link() //字符串与数字的连接string element() //获取表达式中的元素对象string expression() //处理表达式string expression_1() //处理表达式string biaodashi() //处理表达式,转为三地址输出string biaodashi_1() //递归---处理表达式,转为三地址输出string getOperator() //判断并获取运算符void condition(int L1,int L2) //输出if语句的条件的三地址代码void yuyifenxi_list() //生成并输出条件返回地址void yuyifenxi_list_1() //递归---生成并输出条件返回地址void yuyifenxi(int next,int &flag) //判断关键字,调用相应的产生式分析void readfile() //文件读入四、测试报告1.第一组测试:图1-1 输入待翻译代码图1-2 中间代码生成2.第二组测试:图2-1 输入待翻译代码图2-2 中间代码生成3、第三组测试:错误待翻译代码图3-1 输入待翻译代码图3-2 中间代码生成五、实验总结实验三的重点在于判断关键字,调用相应的产生式分析及处理表达式,转为三地址输出部分,也就是很费时间的难点部分,但通过查阅书本及网上资料,还就是将其以多个处理函数的递归调用实现了,虽然最后实现结果对错误的分析还不够精确有些差强人意,但毕竟还算有些收获了。

另外,通过三次实验下来,对于一个简易编译器的实现已经有了一个整体的构架了,相信在通过自己以后的深入学习,一定能写出属于自己的编译器。

六、附录代码#include <iostream>#include <algorithm>#include<conio、h>using namespace std;int address=100; //每条分析语句的地址int LID=0; //表示过程执行到相应位置的地址符号int tID=0; //用于替换表达式的标识符int ip=0;string shuru[666]; //存放从文件读入的字符串int maxsize; //设置存放数组的长度string biaodashi();/*****字符串与数字的连接*****/string link(string a,int b){string t="";do{t+=b%10+'0';b/=10;}while(b);reverse(t、begin(),t、end());return a+t;}/*****获取表达式中的元素对象*****/string element(){if(shuru[ip]=="expr"||shuru[ip]=="num"){ip++;return shuru[ip-1];}else if(shuru[ip]=="("){ip++;string result=biaodashi();if(shuru[ip]==")")ip++;else puts("Lack)");return result;}else puts("error");return "";}/*****处理表达式*****/string expression_1(string &op){if(shuru[ip]=="*"||shuru[ip]=="/"){op=shuru[ip];ip++;string arg1=element();string op_1="",result=link("t",tID++);string arg2=expression_1(op_1);if(op_1=="")op_1="=";if(arg2=="") cout<<address++<<":"<<" "<<result<<" = "<<arg1<<endl;else cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op_1<<" "<<arg2<<endl;return result;}return "";}/*****处理表达式*****/string expression(){string op="",result=link("t",tID++);string arg1=element();string arg2=expression_1(op);if(op==""){op="=";}if(arg2==""){cout<<address++<<":"<<" "<<result<<" = "<<arg1<<endl;}else{cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op<<" "<<arg2<<endl;}return result;}/*****递归---处理表达式,转为三地址输出*****/string biaodashi_1(string &op){string result="";if(shuru[ip]=="+"||shuru[ip]=="-"){op=shuru[ip];ip++;string arg1=expression();string op_1="";string arg2=biaodashi_1(op_1);result=link("t",tID++);if(op_1==""){op_1="=";}if(arg2==""){cout<<address++<<":"<<" "<<result<<" = "<<arg1<<endl;}else{cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op_1<<" "<<arg2<<endl;}}return result;}/*****处理表达式,转为三地址输出*****/string biaodashi(){string arg1="",op="";if(shuru[ip]=="+"||shuru[ip]=="-"){arg1=shuru[ip];ip++;}arg1+=expression();string arg2=biaodashi_1(op);string result=link("t",tID++);if(op==""){op="=";}if(arg2==""){cout<<address++<<":"<<" "<<result<<" = "<<arg1<<endl;}else{cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op<<" "<<arg2<<endl;}return result;}/*****判断并获取运算符*****/string getOperator(){if(shuru[ip]=="="||shuru[ip]=="<>"||shuru[ip]=="<"||shuru[ip]==">"||shuru[ip]=="<="||shuru[ip]==">="){ip++;return shuru[ip-1];}else{puts("error");}return "";}/*****输出if语句的条件的三地址代码*****/void condition(int L1,int L2) //L1,L2分别为if条件为true与false时候的跳转地址{string result=link("t",tID++);string arg1=biaodashi(); //获得表达式的运算符的左边内容string op=getOperator(); //获得表达式的运算符string arg2=biaodashi(); //获得表达式的运算符的右边内容if(arg2==""){cout<<" "<<result<<" = "<<arg1<<endl;}else{cout<<address++<<":"<<" "<<result<<" = "<<arg1<<" "<<op<<" "<<arg2<<endl;}cout<<address++<<":"<<" if true "<<result<<" goto "<<"L"<<L1<<endl;cout<<address++<<":"<<" if false "<<result<<" goto "<<"L"<<L2<<endl;}/*****判断关键字,调用相应的产生式分析*****/void yuyifenxi(int next,int &flag){if(shuru[ip]=="expr"){ip++;if(shuru[ip]=="=") //赋值语句转化为四元式{ip++;string arg1=biaodashi();string arg2="";if(arg2 == "") cout<<address++<<":"<<" expr = "<<arg1<<endl;}else puts("error");}else if(shuru[ip]=="if") //if的语义子程序{ip++;int L1=LID++;int L2=LID++;if(shuru[ip]=="("){ip++;condition(L1,L2);}else{puts("Lack(");return;}if(shuru[ip]==")") ip++;else {puts("Lack)");return;}printf("L%d:\n",L1);yuyifenxi(next,flag);ip++;if(shuru[ip]=="else"){printf("L%d:\n",L2);ip++;yuyifenxi(next,flag);}}else if(shuru[ip]=="while") //while的语义子程序{ip++;int L1=LID++;int L2=LID++;if(shuru[ip]=="("){ip++;printf("L%d:\n",L1);condition(L2,next);}else{puts("Lack(");return;}if(shuru[ip]==")") ip++;else {puts("Lack)");return;}printf("L%d:\n",L2);yuyifenxi(next,flag);printf("goto L%d\n",L1);flag=1;}}/*****递归---生成并输出条件返回地址*****/void yuyifenxi_list_1(){if(shuru[ip]==";"){ip++;int next=LID++;int flag=0;yuyifenxi(next,flag);if(flag)printf("L%d:\n",next);yuyifenxi_list_1();}}/*****生成并输出条件返回地址*****/void yuyifenxi_list(){int next=LID++;int flag=0;yuyifenxi(next,flag);if(flag)printf("L%d:\n",next);yuyifenxi_list_1();}void Modular(){int next=LID++;int flag=0;yuyifenxi_list();if(flag)printf("L%d:\n",next);}/*****文件读入*****/void readfile() //将字符串输入到shuru中{maxsize=0;while(cin>>shuru[maxsize])maxsize++;}/*****主函数*****/int main(){freopen("input、txt","r",stdin);cout<<"语义分析如下:"<<endl;readfile();Modular();return 0; }。

相关文档
最新文档