编译原理(4)语义_2(表达式及赋值语句的翻译)
编译原理语义分析与中间代码生成
编译原理语义分析与中间代码生成在编译原理中,语义分析是编译器的重要组成部分之一,它负责验
证和处理源代码中的语义信息,为后续的中间代码生成做准备。本文
将介绍语义分析的基本概念和流程,并探讨中间代码生成的相关技术。
一、语义分析的基本概念和流程
语义分析是指对源代码进行语义检查和语义信息提取的过程。其主
要目标是确保源代码在语义上是正确的,并从中提取出各种语义信息,以便后续阶段使用。
语义分析的基本流程如下:
1. 词法分析和语法分析:在进行语义分析之前,需要先对源代码进
行词法分析和语法分析,以便将代码转化为具有结构的中间表示形式(如抽象语法树)。
2. 符号表的构建:符号表是语义分析的重要数据结构,用于存储程
序中出现的各种标识符及其相关信息,如类型、作用域等。在语义分
析阶段,需要构建符号表并实时更新。
3. 类型检查:类型检查是语义分析的核心任务之一。它通过对表达式、赋值语句、函数调用等进行类型推导和匹配,来验证程序是否存
在类型错误。
4. 语义规则检查:除了类型检查外,语义分析还需要检查程序是否符合语言规范中的其他语义规则,如变量是否已声明、函数调用是否正确等。
5. 语义信息提取:语义分析还负责提取源代码中的各种语义信息,如函数调用关系、变量的定义和引用关系、控制流信息等。这些信息将为后续的代码优化和代码生成提供依据。
二、中间代码生成的相关技术
中间代码是指某种形式的中间表示形式,通常与源代码和目标代码之间存在一定的映射关系。它在编译过程中起到连接前后两个阶段的桥梁作用,并且可以进行一些优化。
常见的中间代码形式之一是三地址码。三地址码是一种低级的代码表示形式,每条指令最多包含三个操作数。它具有简洁明了的特点,适合进行后续的优化工作。
编译原理6-4.2-4.3- 自顶向下翻译-递归下降翻译
(a) 按(6.1)自下而上计算 自下而上计算 图6.16
(b) 按(6.3)自上而下计算 自上而下计算
计算属性值的两种方法
例6.11 如果把构造抽象语法树的属性文法 定义(见表6.4)转化成翻译模式,那么关于 转化成翻译模式, 定义(见表 转化成翻译模式 E的产生式和语义动作就变为: 的产生式和语义动作就变为: 的产生式和语义动作就变为
删除左递归后:引入非终结符R
E→ T → { R.i := T.nptr } R { E.nptr := R.s } R→ + → T{ R1.i := mknode(‘+’, R.i, T.nptr) } R1 { R.s := R1.s } R→ → T { R1.i := mknode(‘-’, R.i, T.nptr) } R1 { R.s := R1.s } R→ ε { R.s := R.i } //返回最终语法树 → 返回最终语法树 其余不变, (其余不变,略)
A →A1Y { A.a:= :=g(A1.a , Y.y) } := A →X { A.a:= :=f(X.x) } :=
(6.1)
消除左递归,转换为如下文法 消除左递归,转换为如下文法: A →XR R →YR | ε 考虑语义动作, 考虑语义动作,翻译模式变为 A→ X R R→Y R1 R→ ε {R.i := f(X.x)} {A.a := R.s} {R1.i := g(R.i , Y.y)} {R.s := R1.s} {R.s := R.i } (6.2)
《编译原理》课程教学大纲
《编译原理》课程教学大纲
(Principles of Compiler)
课程性质: 专业课
适用专业: 计算机科学与技术
先修课程:PASCAL语言程序设计或C语言程序设计、离散数学、数据结构
后续课程:
总学分:4学分(其中实验0.5)
一、教学目的与要求
1.教学目的
编译原理是计算机科学与技术专业中的一门很重要的专业课程,它在系统软件中占有十分重要的地位,是计算机科学与技术专业学生的一门主修课。通过本课程的学习,使学生掌握编译理论基础,包括词法分析、语法分析、中间代码生成、代码优化和目标代码生成。理解编译的实现方法,了解自动机语言的形式化定义、编译技术的各种概念以及具体实现过程的方法。从形式语言理论角度讨论词法分析和语法分析技术,为学生从事系统软件开发打下良好的基础。
2.教学要求
编译原理是一门重要的专业选修课程,本课程将以课堂讲授为主,讲授编译系统的一般构造原理、基本实现技术和一些自动构造工具,布置一定量的作业,配合相应的实验,帮助学生理解有关编译的基本概念,甚至更深入地理解编程语言。从而使学生的编程能力得到真正的锻炼与提高。
二、课时安排
三、教学内容
1.引论(4学时)
(1)教学的基本要求
了解:编译程序与高级程序设计语言的关系;编译和解释的概念;编译程序的几个阶段所完成的任务及编写编译程序的主要方法
理解:编译理论和实践相结合的重要性
掌握:编译的各个阶段及其主要任务
(2)教学内容
①程序设计语言与编译
②编译程序概述
③编译程序的生成
④编译程序的构造
2.编译基础知识(4学时)
(1)教学的基本要求
了解:文法的分类;闭包、正闭包、文法、语言、推导、归约、语法树、二义文法的概念,无ε产生式的文法及文法的简化
编译原理(4)语义_4(数组元素、过程、说明语句的翻译)解析
4.6
数组元素的翻译
(2) E→E(1) +E(2) {T=newtemp; emit(+,E(1).place, E(2).place,T); E.place=T;} (3) E→(E(1) ) {E.place= E(1).place;} (4) E→V { if (V.offset==null)
计算方法决定了数组元素四元式的产生形式。 数组元素的存放方式:按行存放和按列存放。
1 2 5 8 3 6 9 1 4 7 2 5 8 3 6 9 1 2 3 4 5 6 7 8 9
A=
4 7
我们主要讨论按行存放的数组元素地址计算方法。
4.6
数组元素的翻译
4.6
数组元素的翻译
4.6
数组元素的翻译
void *malloc(unsigned int size);
void *calloc(unsigned int num,
unsigned int size);
我们主要讨论静态数组元素的引用如何翻译。
4.6
数组元素的翻译
4.6.1 数组元素的地址计算及中间代码形式
数组元素的地址计算
数组元素的存放方式决定了数组元素的地址计算方法,地址
实现数组元素的地址计算时,将产生两组四元式序列:
一组计算CONSPART,其值存放在临时变量T中;
编译原理
形式语言理论是编译的重要理论基础,重点 介绍如何采用形式化的方法描述程序设计语言。
字母表和符号串
1. 字母表
字母表是元素的非空有穷集合,习惯 上用大写字母表示。
例如,∑={ a, b, c } 根据字母表的定义,Σ是字母表,它由a、b、 c三个元素组成。
形式化语言
例如 对于程序中“赋值语句” 的非形式化的 描述为:
语法:赋值语句由一个变量,后随一个赋值号 “=”,其后面再跟一个表达式构成。
语义:首先计算语句右部表达式的值,然后把 所得结果送给左部变量中。
语用:赋值语句可用来计算和保存表达式的 值。
形式化语言
这种非形式化的描述,不够清晰和准确,为了 精确定义和描述程序设计语言,需采用形式化的 方法。
2.3.1 上下文无关文法
上下文无关文法的定义: 一个上下文无关文法G是一个四元式 G=(VT,VN,S,P),其中 VT:终结符集合(非空); VN:非终结符集合(非空),且VT VN=; S:文法的开始符号,SVN; P:产生式集合(有限),每个产生式形式为: P, PVN, (VT VN)* ; 开始符S至少必须在某个产生式的左部出现一 次。
一个数据类型通常包括以下三种要素:
用于区别这种类型数据对象的属性; 这种类型的数据对象可以具有的值; 可以作用于这种类型的数据对象的操作;
编译原理教程课后习题答案——第四章
第四章语义分析和中间代码生成
完成下列选择题:
(3)表达式h AVB)A(CVD)的逆波兰表示为 ________ o
a. -)ABVACDV
b. A-I BVCDVA
c. ABVq CDVA
d. A-I BVACDV (4)有一语法制导翻译如下所示: S —bAb
{print M 1 } A-(B
{print" 2" } A_a
{print" 3 } B-Aa)
{print 7 4" } 若输入序列为b(((aa)a)a)b,且采用自下而上的分析方法,则输出序列为. a. b ・
c. d ・
【解答】 ⑴ b (2) a (3)b
(4)b 何谓"语法制导翻译”试给出用语法制导翻译生成中间代码的要点,并用一简例
予以说明。 【解答】语法制导翻译(SDTS)直观上说就是为每个产生式配上一个翻译子程序(称
语义动作或语义子程序),并且在语法分析的同时执行这些子程序。也即在语法分析过程中, 当一个产生式获得匹配(对于自上而下分析)或用于归约(对于自下而上分析)时,此产生式相 应的语义子程序进入工作,完成既定的翻译任务。
用语法制导翻译(SDTS)生成中间代码的要点如下:
(1) 按语法成分的实际处理顺序生成,即按语义要求生成中间代码。
(2) 注意地址返填问题。
(3) 不要遗漏必要的处理,如无条件跳转等。 例如下而的程序段:
■
if (i>0) a=i+e-b*d; else a=0;
在生成中间代码时,条件"i>0”为假的转移地址无法确定,而要等到处理"else"时方可确 左,这时就存在一个地址返填问题。此外,按语义要求,当处理完(i>0)后的语句(即"i>0”为 真时执行的语句)时,则应转出当前的if 语句,也即此时应加入一条无条件跳转指令,并且 这个转移地址也需要待处理完else 之后的语句后方可获得,就是说同样存在着地址返填问 题。对于赋值语句a=i +e-b*d ,其处理顺序(也即生成中间代码顺序)是先生成i+e 的代码,再 生成b*d 的中间代码,最后才产生“/运算的中间代码,这种顺序不能颠倒。
语义分析——精选推荐
语义分析
实验四、语法分析实验
⼀、实验⽬的
(1)编制⼀个语义分析程序
(2)语义分析程序是在语法分析程序的基础上进⾏编写的,主要任务是根据语法分析来插⼊中间代码、语义规则以及⽣成四元式。(3)通过语义分析的练习,能够进⼀步了解编译原理。
(4)通过了解语义分析程序的设计原则、语义规则的描述技术、识别机制及语义分析程序的⾃动构造原理。
⼆、实验内容和要求
(1)根据语法分析程序进⾏改写语义分析程序
(2)根据语⾔的语义规则,插⼊中间代码、语义规则以及⽣成四元式等
(3)并在分析过程中进⾏语义检查,四元式作为输出或以某种形式的语法树作报告错误
三、实验⽅法、步骤及结果测试
1、实验⽅法、步骤:
完成静态语义审查和处理
a) 上下⽂相关性审查
b) 类型匹配审查
c) 类型转换
d) 如:s:=2*3.1416*r*(h+r);
i. 赋值语句的语义:计算赋值符号右边表达式的值,送到赋值号左边的变量中。
ii. 检查赋值号左右两边的类型是否匹配
iii. 根据赋值语句的语义,将它翻译成四元式中间代码
2、原理分析:我是在语法分析程序的基础上进⾏修改的,是根据语法分析来插⼊中间代码、制定语义规则以及⽣成四元式。
void S(){
char y=str[t-1];int x;
if(syn==10){
scaner();
if(syn==18){
scaner(); x=E();printf("\n(':=',%d, ,%c)\n",x,y);
}
}
}
int E(){
int x;printf("E ");
x=T();return E1(x);
编译原理课程设计-翻译成四元式
编译原理课程设计
一、课程设计题目:
第(20)题:写一程序,演示对给定下标变量赋值语句文法,且已知建立内情向量,对给定的下标变量赋值语句翻译成四元式。
二、编程环境:
在Turboc下编程运行,可随意输入数组维数,对输入的给定下标变量赋值语句翻译成四元式。
三、设计原理:
一个含数组元素的赋值语句的文法模式可为下所示:
A->V:=E V->i[elist]|i elist->elist,E|E E->E+E|(E)|V 即一个赋值语句A是一个V(指变量)后跟赋值号:=和一个算术表达式E。
为了计算数组元素的VARPART,需要把关于变量V的文法改写成:V->elist]|i elist->elist,E|i[E 把数组名i和最左的下标式写在一起
的目的是使在整个下标串elist的翻译过程中随时都能知道数组名i的符号表
入口,从而随时能够了解登记在符号表中的有关数i的全部信息。为了计算
VARPART的四元式序列,需要知道数组名的符号表入口,下标式的个数,将
VARPART的中间结果单元名字在符号表中的位置等。
还要根据含有数组元素的赋值句的翻译规则进行翻译。
四、设计过程:
数组元素a[i1,i2,…,in]地址D的计算公式为: D=CONSPART+VARPART
CONSPART=a-c ,其中c是常数(d2d3…dn+d3…dn+…+dn+1).由题目已知建立了内情向量表,但是为了方便起见还是要输入数组的维数以及是几乘几的数组。
为了计算常数c编了一个专门的函数Conspart(int a[],DIM);其核心是:
编译原理(4)语义-2(表达式及赋值语句的翻译)
例如,赋值语句 x = b 刚开始读入到符号栈中,显示为
i = i, 使用E →i规约,得到:
i = E(符号栈) _ _ b(语义栈)
所以,E.Place中必须保存b在符 号表中的入口地址;
x=b 翻译为( =, b, _ , x)
4.4 表达式及赋值语句的翻译
1.设计6个产生式的语义子程序
(1) A→ i=E
(4)(j,_,_,假出口)
(5)(=,c,_,1)
(6){if语句后面的四元式}
在这个例子中,真出口和假出口不能在生成四元式的当时产 生;假如a和b并不是简单的布尔变量,或者条件语句后执行 的语句并不是仅仅一句,所有的真假出口都无法给定。
4.4 表达式及赋值语句的翻译 3、布尔表达式的文法:
(1) 普通布尔表达式文法:
4.4 表达式及赋值语句的翻译
(2)运算对象(三种): 布尔变量 布尔常量(false、true) 关系表达式 1、运算符rop : <、<=、==、!=、>=、> 2、运算对象:算术表达式
3、返回值类型:bool类型
例:bool a,b,c; int x,y,z
思考:运算顺序??
a = b ∨ c ∧ true ∨ (x+y >= z)
西北农林科技大学本科教程
第 10 讲
主讲教师:赵建邦
编译原理教学大纲
编译原理教学大纲
《计算机编译原理》课程大纲
一、适用对象
本课程适用于计算机科学与技术以及相关专业的网络教育、成人教育学生。
二、课程性质
本课程是计算机科学与技术专业学生的专业基础课。编译原理课程是计算机专业的一门主干课程。课程介绍程序设计语言编译程序构造的一般原理、基本设计方法、主要实现技术和一些自动构造工具。首先从剖析一个简单的编译程序PL/0入手,对编译程序设计的基本理论,如有穷自动机、上下文无关文法等给予介绍;对于广泛使用的语法分析和语义分析技术,如递归子程序法、算符优先分析、LR 分析及语法制导翻译等进行了详细的讲解;对编译程序的结构及其各部分功能、实现方法以及整体的设计考虑给予了描述;对编译程序的构造工具进行介绍;同时对面向对象语言的编译程序和构造进行介绍。
前序课程:高级程序语言、离散数学、数据结构、计算机组成原理。
三、教学目的
通过本课程的学习,使学生掌握设计和实现程序设计语言的最基本的理论和技术,掌握编译程序工作原理和构造方法。同时,能够达到去鉴赏、评价和实现某种程序设计语言。主要有如下教学目的:
(1)对编译过程从整体上有一个较清晰的了解,掌握高级语言程序的编译过程。(2)掌握文法、自动机、正规式等编译基本理论知识。
(3)掌握确定的自顶向下的语法分析方法和自底向上的算符优先分析及LR 分析方法。(4)掌握语法制导翻译的语义分析方法,掌握中间代码的优化和目标代码的生成。(5)理解符号表和目标程序运行时的存储组织。(6)了解面向对象语言编译程序的原理和构造。
四、教材及学时安排
教材:张素琴、吕映芝、蒋维杜、戴桂兰,编译原理(第2版),清华大学出版社,2005年2月,ISBN :
第17讲 赋值语句的翻译
E.place:=newtemp;
E.code:=E1.code || E2.code E.place:=newtemp;
||
gen(E.place
‘:=’
E1.plac视e 频‘+区’ E域2.place)
E.code:=E1.code || E2.code || gen(E.place ‘:=’ E1.place ‘*’ E2.place)
视频区域
数组元素地址计算
设A为n维数组,按行存放,每个元素宽度为w lowi 为第i维的下界 upi 为第i维的上界 ni 为第i维可取值的个数(ni = upi -lowi + 1) 视频区域
base为A的第一个元素相对地址 可变部分
元素A[i1,i2,…,ik]相对地址公式 ((…i1 n2+i2)n3+i3)…)nk+ik)×w + base-((…((low1 n2+low2)n3+low3)…)nk+lowk)×w C = ((…((low1 n2+low2)n3+low3)…)nk+lowk)×w
数组元素地址计算
引入下列语义变量或语义过程
Elist.ndim: 下标个数计数器 Elist.place: 保存临时变量的名字,这些临时变量存
放已形成的Elist中的下标表达式计算出来的值视频区域 Elist.array: 保存数组名 limit(array,j) :函数过程,它给出数组array的第j
编译原理-教学大纲
编译原理教学大纲
编译程序设计堪称计算机科学中理论和实践相结合的典范。在本课程中,您将学习编译程序构造的基本原理和设计方法,提高对计算机系统的总体认识,还可以从信息表示变换的角度理解计算、理解计算思维,拓广计算应用的视野。
课程概述
《编译原理》课程是计算机科学与技术专业的必修课程。本课程主要介绍程序设计语言编译程序构造的基本原理和设计方法,包括:编译程序概述、高级语言及其语法描述、词法分析、语法分析、属性文法和语法制导翻译、语义分析和中间代码产生、符号表、运行时存储空间组织、优化、目标代码生成等。
理论和实践相结合是编译程序设计的重要特色。形式语言和自动机理论为编译程序的设计提供了坚实的理论基础,正是在科学理论的保证下,才形成了一系列先进的编译程序设计方法和工具,使得编译程序的构造具有很高的系统性和自动化程度。
授课目标
通这门课程的学习,您将能:
1.在理解编译系统的结构、工作流程以及编译程序各组成部分的设计原理和实现技术的基础上,获得分析、设计、实现和维护编译系统的初步能力。
2.深入理解程序语言和程序执行过程,提高对计算机系统的总体认识。
3.从语言翻译和表示变换的角度理解计算。编译过程体现的诸如抽象、自动化、递归、分解、权衡等众多计算思维方法,可以广泛应用于自然语言处理、程序验证、网络信息处理等领域的问题求解。
课程大纲
第1讲引论
1.5 编译程序的生成
1.6 小结
1.1 什么是编译程序
1.2 为什么要学习编译原理
1.3 编译过程
1.4 编译程序的结构
第2讲高级程序设计语言概述
2.1 常用的高级程序设计语言
编译原理概念_名词解释
编译过程的六个阶段:
词法分析,语法分析,语义分析,中间代码生成,代码优化,目标代码生成解释程序:
把某种语言的源程序转换成等价的另一种语言程序——目标语言程序,然后再执行目标程序。
解释方式是接受某高级语言的一个语句输入,进行解释并控制计算机执行,马上得到这句的执行结果,然后再接受下一句。
编译程序:
就是指这样一种程序,通过它能够将用高级语言编写的源程序转换成与之在逻辑上等价的低级语言形式的目标程序(机器语言程序或汇编语言程序)。
解释程序和编译程序的根本区别:
是否生成目标代码
句子的二义性(这里的二义性是指语法结构上的。):
文法G[S]的一个句子如果能找到两种不同的最左推导(或最右推导),或者存在两棵不同的语法树,则称这个句子是二义性的。
文法的二义性:
一个文法如果包含二义性的句子,则这个文法是二义文法,否则是无二义文法。
LL
(1)的含义:
(LL
(1)文法是无二义的;LL
(1)文法不含左递归)
第1个L:
从左到右扫描输入串第2个L:
生成的是最左推导
1:向右看1个输入符号便可决定选择哪个产生式
某些非LL
(1)文法到LL
(1)文法的等价变换:
1.提取公因子
2.消除左递归
文法符号的属性:
单词的含义,即与文法符号相关的一些信息。如,类型、值、存储地址等。
一个属性文法(attribute grammar)是一个三元组A=(G, V, F)
G:
上下文无关文法。
V:
属性的有穷集。每个属性与文法的一个终结符或非终结符相连。属性与变量一样,可以进行计算和传递。
F:
关于属性的断言或谓词(一组属性的计算规则)的有穷集。断言或语义规则与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性。
编译原理 第4章 new1语义分析和中间代码生成
实现简单算术表达式和赋值语句到四元 式的翻译一般采取下列步骤:
(1)分析文法的特点。 (2)设置一系列语义变量,定义语义过程、 语义函数。 (3)修改文法,写出每一条规则式的语义 子程序。 (4)扩充LR分析栈,构造LR分析表。
第4章 语义分析和中间代码生成
语义子程序所涉及的语义变量、语义过程及函数
(3) E→(E(1))
(4) E→i
val[TOP]= val[TOP+1]
val[TOP]=lexval (注:lexval为i的整型内 部值)
文法的LR分析表见表3.20。
第4章 语义分析和中间代码生成
扩充分析栈工作的总控程序功能,使其在完成语法 分析的同时也能完成语义分析工作(这时的语法分析栈 已成为语义分析栈);即在用某一个规则进行归约之后, 调用相应的语义子程序完成与所用产生式相应的语义动 作,并将每次工作后的语义值保存在扩充后的“语义值” 栈中。
同,因此很容易将其翻译成四元式形式。
第4章 语义分析和中间代码生成
考虑以下文法G[A]:A→i=E
E→E+E∣E*E∣−E∣(E)∣i 在此,非终结符A代表“赋值句”。 为了实现由表达式到四元式的翻译,需要给文法 加上语义子程序,以便在进行归约的同时执行对应的
语义子程序。
第4章 语义分析和中间代码生成
第4章 语义分析和中间代码生成
编译原理分知识点习题-语法制导和翻译
编译原理分知识点习题-语法制导和翻译
1.⼀般情况下,为什么语义分析部分仅产⽣中间代码
解答:⼀般情况下,语义分析部分仅产⽣中间代码,其原因是:
可使难点分解,分别解决。
可对语义分析产⽣的中间代码进⾏优化,以产⽣⾼效率的⽬标代码。
语义分析通常与机器⽆关,⽬标代码往往与机器有关。把语义分析与⽬标代码⽣成分开,可让⼀个语义分析程序适⽤于多个⽬标代码⽣成程序。
2.(湖北省⾼等教育⾃学考试)什么是语法制导翻译为什么把这种⽅法叫语法制导翻译
解答:所谓语法制导翻译,是指在语法规则的制导下,通过计算语义规则,完成对输⼊符号串的翻译。
由于使⽤属性⽂法时把语法规则和语义规则分开,但在使⽤语法规则进⾏推导或规约的同时⼜使⽤这些语义规则来知道翻译与最终产⽣⽬标代码,所以称为语法制导翻译。
3.给出将附值语句翻译成四元式的语法制导定义,允许右部表达式
含有加法、乘法、取负、括号运算。⽣成赋值语句X:=B*(C+D)+A 的四元式。
解答:赋值语句的⾃下⽽上的语法制导翻译过程描述为:
规则语义动作
(1)A::=i:=E {GEN (:=,,__,ENTRY(i) ) }(2)E::=E1+E2 {:=NEWTEMP;
GEN(+,, ,}
(3)E::= E1*E2 { :=NEWTEMP;
GEN(*,, ,}
(4)E::=-E1 { :=NEWTEMP;
GEN(@,,__,}
(5)E::=(E1) {:= }
(6)E::=i {:= ENTRY(i) }
⽣成的赋值语句X:=B*(C+D)+A的四元式为:
(+,C,D,T1)
编译原理习题课(4)
MAXINT – 5 MAXINT – 4 MAXINT – 3 MAXINT – 2 MAXINT – 1
MAXINT
10
构造翻译模式
for v:=initial to final do S 其意义如下: begin
t1:=initial; t2:=final; if t1 t2 then begin
v:=t1; S; while v t2 do begin
v:=succ(v); S; end end end
S→ for id:=E1 to E2 do S1 改造为: S→ F S1 F→ for id:=E1 to E2 do
11
F→ for id:=E1 to E2 do {
INITIAL=NEWTEMP;
四元式序列 100. ( jnz, A, -, 0) 101. ( j, -, -, 102) 102. ( jnz, B, -, 104) 103. ( j, -, -, 0) 104. ( jnz, C, -, 103) 105. ( j, -, -, 106) 106. ( jnz, D, -, 104) 107. ( j, -, -, 100)
(7) M→ { M.quad:=nextquad }
{ E.truelis一t:=m遍ak扫elis描t(n的ext翻qua译d);模式
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(r1) ( _ , _ , _ , 0)
(q1) ( _ , _ , _ , r1) (p1) ( _ , _ , _ , q1) (r2) ( _ , _ , _ , 0) (q2) ( _ , _ , _ , r2)
(p2) ( _ , _ , _ , q2)
算法执行完,其实就是将(r2) 中的result变为p1,最终形成一个链
2、语义子程序: (1) E→i (布尔值) { E.tc=nxq; E.fc=nxq+1; emit(jnz,entry(i),_,0);
简单变量:普通变量和常数,不包括数组、结构体成员等复
合型数据结构。 简单算术表达式:仅含简单变量的算术表达式
简单算术表达式与四元式 简单算术表达式的计值顺序与四元式出现的顺序相同,因此很
容易将其翻译成四元式形式。
当然,这些翻译方法稍加修改也可用于产生三元式或间接三元 式。
回顾: 表达式及赋值语句的翻译
4.4
表达式及赋值语句的翻译
1.设计6个产生式的语义子程序 (1) A→ i=E { p=lookup(i.name); if(p==NULL) error( ); else emit(=,E.place,_,p);
}
(a)对非终结符E定义语义变量E.place,即用E.place表示存放E 值的变量名在符号表中的入口地址或临时变量名的整数码 例如,赋值语句 x = b 刚开始读入到符号栈中,显示为
西北农林科技大学本科教程
第 10 讲
主讲教师:赵建邦
第四章 语义分析和中间代码生成
4.1 4.2 4.3 4.4 4.5
4.6
4.7 4.8 4.9
语义分析概述 属性文法 几种常见的中间语言 表达式及赋值语句的翻译 控制语句的翻译 数组元素的翻译 过程或函数调用语句的翻译 说明语句的翻译 递归下降语法制导翻译方法简介
4、解决“真”、“假”出口问题的方法:拉链和回填
(1) 拉链:在同一个表达式内,每个四元式产生的时候,强制 其出口为0,若后面一个四元式和它出口相同,用前面产生式 的序号去填充后面产生式的跳转位置(result),从而将不同
的四元式链接起来,俗称“拉链”。
假如下面三个四元式都是真出口: (i) ( _ , _ , _ , 0) (i) (_ , _ , _ , 0) (j) (_ , _ , _ , i) (k) (_ , _ , _ , j)
(6){if语句后面的四元式}
在这个例子中,真出口和假出口不能在生成四元式的当时产 生;假如a和b并不是简单的布尔变量,或者条件语句后执行 的语句并不是仅仅一句,所有的真假出口都无法给定。
4.4
表达式及赋值语句的翻译
3、布尔表达式的文法:
(1) 普通布尔表达式文法:
G[E]: E→E∧E | E∨E | ┐E | (E) | i | i rop i
表4.2(2) 赋值语句X=−B*(C+D)的翻译过程
4.4
表达式及赋值语句的翻译
4.4.2 布尔表达式的翻译
1、布尔表达式的组成
布尔表达式:由运算符与运算对象组成。
定义布尔变量
A、B、C、D
A = bop1 B bop2 C bop3 D
(1)运算符:非┐(单目)、与∧ (双目)、或∨ (双目) 注意:1、优先级: ┐ ⋗ ∧ ⋗ ∨
i = i, 使用E →i规约,得到:
i = E(符号栈) _ _ b(语义栈) 所以,E.Place中必须保存b在符 号表中的入口地址; x=b 翻译为( =, b, _ , x)
4.4
表达式及赋值语句的翻译
1.设计6个产生式的语义子程序 (1) A→ i=E { p=lookup(i.name); if(p==NULL) error( ); else emit(=,E.place,_,p);
规约的时候,再次扩充语义栈,添加tc栈和fc栈;
2、nxq:这是一个int变量,翻译工作开始之前,初始值 是1,翻译工作开始之后,每执行一次emit(),nxq自增1, 即: nxq = 四元式个数+1;
4.4
表达式及赋值语句的翻译
5、布尔表达式的翻译
1、文法:
G[E]: E→EAE | EBE | ┐E | (E) | i | i rop i EA→E∧ EB→E∨
4.4
表达式及赋值语句的翻译
(2) 回填算法:把链首p所链接的每个四元式的第四区段(result) 都改写为地址t。 (r) (_ , _ , _ , 0)
Backpatch(p, int t){ Q=p; while(Q!=0) { q=四元式Q的第四区段内容; 把t填进四元式Q的第四区段; Q=q; } // while } //Backpatch
(j) ( _ , _ , _ , 0)
(k) ( _ , _ , _ , 0)
注意:(k)为链首,(i)为链尾,链尾result=0
4.4
表达式及赋值语句的翻译
(1) 拉链算法: p1 ,p2各自是两个链首,将它们合并成一个以p2为链首的新链
merge(p1 ,p2){ if(p2==0) return(p1); else { p=p2; while(四元式p的第四区段内容不为0) p=四元式p的第四区段内容; 把p1填进四元式p的第四区段; return(p2); } // else } // merge
}
(b) 定义语义函数lookup(i.name),其功能是审查终结符i.name
是否出现在符号表中,是则返回i.name在符号表的入口指针,
否则返回NULL。 (c) 定义语义函数emit(op,arg1,arg2,result),emit的功能是产 生一个四元式并填入四元式表中。
4.4
表达式及赋值语句的翻译 { E.place=newtemp( ); emit(+,E(1).place, E(2).place, E.place); }
(2) 优化的布尔表达式文法: G[E]: E→EAE | EBE | ┐E | (E) | i | i rop i EA→E∧ EB→E∨ 好处:在句子中,如果出现 “a∨b”或“a ∧ b”之类的
表达式,当扫描到“a∨”或“a ∧”之后就立即可以进行规约, 不用去关系b的取值。
4.4
表达式及赋值语句的翻译
所以,按照优化方式计算布尔表达式,需要给出整个表达式
的真假出口。 (1) 真出口: 若E(1)为真,则E为真; 若E(2)为真,则E为真;
所以E的真出口有两个:
E(1)的真出口和E(2)的真出口。
(a) E = E(1)∨E(2)
(2) 假出口:
E(1)的假出口并不是E的假出口,E(1)如果为假,必须计算E(2) , 因此:E(2)的假出口是整个E的假出口。
(d) 定义语义函数newtemp( ),即每次调用newtemp( )时都将回 送一个代表新临时变量的整数码;临时变量名按产生的顺序可 设为T1、T2……
4.4
表达式及赋值语句的翻译 { E.place= E(1).place ;}
(5) E→(E(1))
(6) E→i
{ p=lookup(i.name); if(p!=NULL) E.place=p; else error ( ); }
计算布尔表达式的值有两种方法:
1、按照优先级和各变量的值,一步步求出结果;
2、优化计算:
b = true; a = b ∨ c ; (不计算c, a=true) b = false; a = b ∧ c ; (不计算c, a=false)
4.4
表达式及赋值语句的翻译
2、布尔表达式的计算
(q) (_ , _ , _ , r) (p) (_ , _ , _ , q)
(r) (_ , _ , _ , t) (q) (_ , _ , _ , t)
(p) (_ , _ , _ , t)
4.4
表达式及赋值语句的翻译
(3) 其它需要说明的问题: 1、对于每个非终结符E,我们需要为它赋予两个语义值 E.tc和E.fc,分别用来记录E所对应的四元式的真链和假链。 也就是说,为每个非终结符E添加两个属性:tc和fc;因此,
4.4
表达式及赋值语句的翻译
2、布尔表达式的计算
(1) 假出口:
若E(1)为假,则E为假; 若E(2)为假,则E为假; 所以E的假出口有两个: E(1)的假出口和E(2)的假出口。
(b) E = E(1) ∧ E(2)
(2) 真出口:
E(1)的真出口并不是E的真出口,E(1)如果为真,必须计算E(2) , 因此:E(2)的真出口是整个E的真出口。 练习布尔表达式 a∧b∨c≥d 的真假出口。
4.4
表达式及赋值语句的翻译
布尔表达式中,每个布尔分量一般至少对应两个四元式。
例如:E = E(1)∨E(2) = a∨b
对应: (1)(jnz, a,_,真出口) (2)(j,_,_,3) (3)(jnz, b,_,真出口) (4)(j,_,_,假出口)
if(a || b) c=1;
(5)(=,c,_,1)
2、∧和∨服从左结合
3、运算符的优先级:算术 ⋗关系⋗布尔⋗“=”
4.4
表达式及赋值语句的翻译
(2)运算对象(三种):
布尔变量 布尔常量(false、true) 关系表达式
1、运算符rop : <、<=、==、!=、>=、> 2、运算对象:算术表达式
3、返回值类型:bool类型
例:bool a,b,c; int x,y,z a = b ∨ c ∧ true ∨ (x+y >= z) a = b ∨ c ∧ true ∨ x+y >= z 思考:运算顺序??
例4.2 试分析赋值语句X= -B*(C+D)的语法制导翻译过程 。
[解答] 赋值语句X=-B*(C+D)的语法制导翻译过程如表4.2
所示(加工分析过程参考表4.1)。
其实,利用带注释的语法树进行规约的同时, 就可以完成相应的语义分析(一起看黑板)。
表4.2(1) 赋值语句X=−B*(C+D)的翻译过程
4.4
表达式及赋值语句的翻译
2、布尔表达式的计算
了解1:对布尔运算、关系运算、算术运算的运算对象的类型
可不区分布尔型或算术型,假定不同类型的变换工作将在需 要时强制执行。 思考:C语言的强制转换?? 了解2:布尔表达式在程序语言中不仅用作计算布尔值,还作 为控制语句(如if-else、while等)的条件表达式,用以确定程序 的控制流向。无论布尔表达式的作用如何,按照程序执行的 顺序,都必须先计算出布尔表达式的值。
4.4
表达式及赋值语句的翻译
非终结符A代表“赋值句” 非终结符E代表“表达式”
考虑以下文法G[A]: A→ i = E
E→ E+E | E*E | −E | (E) | i
显然,文法G[A] 是一个二义文法,但通过确定运算符的结合 性及规定运算符的优先级就可避免二义性的发生。 用该文法作为示例的目的:为了更简要地说明语义子程序的 设计过程以及赋值语句的语法制导翻译过程。 如,对于赋值语句x=-b*(c+d),已经预先规定运算顺序
本讲目标
பைடு நூலகம்
第四章《语义分析和中间代码生成》
4.4
表达式及赋值语句的翻译
简单算术表达式和赋值语句的翻译 布尔表达式的翻译(难点)
重点掌握
算术表达式语义子程序 布尔表达式的真假出口
布尔表达式的语义子程序
根据翻译图得到布尔表达式的四元式
4.4
表达式及赋值语句的翻译
4.4.1 简单算术表达式和赋值语句的翻译
{ E.place=newtemp( ); emit(*,E(1).place, E(2).place,E.place); }
(2) E→ E(1)+E(2)
(3) E→ E(1)*E(2)
(4) E→−E(1)
{ E.place=newtemp( ); emit(uminus, E(1).place,_, E.place); }
1.3.3 语义分析和中间代码生成(续) –简单算术表达式的计值顺序与四元式出现的顺序相同: –例如,计算圆柱体表面积的C语言程序: s = 2 * 3.1416 * r *(h + r);
赋值语句的四元式中间代码:
(1)(*,2, 3.1416,T1) (2)(*,T1, r, (3)(+,h, r, (4)(*,T2, T3, (5)(=,T4, _, T2) T3) T4) s)