编译原理chapter7

合集下载

编译原理chapter7

编译原理chapter7
2、由于语义分析是在语法分析的过程中进行 的,所以状态栈实际上是需要的,这里没有写 出来。
3、这个分析过程是针对整型变量做的。实际 上在一个表达式中,可能出现各种不同类型的 变量或常量,所以,编译程序要么拒绝接受某 种混合运算,要么能产生有关类型转换的指令。
第七章 语法制导翻译并产生中间代码
第二节 简单算术表达式和赋值语句的翻译 二、类型转换
产生式
语义子程序
(1)A i=E {p=lookup();
if (p==null) error(); else GEN(=, E•PLACE ,_,ENTRY(i);}
(2)E -E (1)
{T=NEWTEMP; GEN(@, E(1)•PLACE ,_,T); E•PLACE =T ;}
(2)(+,A,(1)) (3)(=,X,(2)) (4)(*,B,C) (5)(-,D,(4)) (6)(=,Y,(5))
三元式表 间接码表 (1)(*,B,C) (1) (2)(+,A,(1)) (2) (3)(=,X,(2)) (3) (4)(-,D,(4)) (1) (5)(=,Y,(5)) (4)
第七章 语法制导翻译并产生中间代码
第一节 概述 一、中间代码生成方法 语法制导翻译;属性文法制导翻译
第七章 语法制导翻译并产生中间代码
第一节 概述 二、属性文法制导翻译
在上下文无关文法的基础上,将文法的终结符、
非终结符及动作符号附加以语义参数,这些参数 称作为文法符号的属性,从而构成属性文法。 注:1)在属性文法中是利用各种属性作为语义动 作之间的通信介质 2)一个文法符号可以和多个语义参数相关联 3)属性可分为两种:继承属性和综合属性。
第七章 语法制导翻译并产生中间代码

编译原理Chapter7 考试重点章节

编译原理Chapter7 考试重点章节
7
山东交通学院
《编译原理》
规范推导/规范句型/规范归约
最右推导:在推导的任何一步αβ,其中α和β是句型, 都是对α中的最右非终结符进行替换。 最右推导被称为规范推导。由规范推导所得的句型称为规范 句型 例:G[S]: S→E E→E+T | T T→(E) | i SE T (E) (E+T) (E+i) (T+i) (i+i) 规范归约: 假定α是G的一个句子,称序列αn、αn-1 …、α0是α的一个 规范归约,如果该序列满足: 1、 αn = α 2、 α0为文法的开始符号 3、对任何j,0<j<=n, αj-1是从αj经把句柄替换为相应产生 式的左部而得到的
杨海 yanghai_sdjtu@
23
山东交通学院
《编译原理》
构造识别活前缀的FA(续)
(2) LR(0) 项目集的闭包:即FA中的状态 若当前处于A –> X•YZ刻画的情况,期望移进First(Y) 中的某些符号,假如有产生式Y –> u 。那么Y –> .u, 这个项目也是刻划期望移进First(Y)中的某些符号的 情况。 A –> X•YZ Y –> •u 这两个项目对应移进归约分析的同一个状态,这两个 项目构成一个项目集, 对应每个项目集,分析表将有 一个状态。
4
山东交通学院
《编译原理》
3、规约的一个特殊情况:栈中的全部内容w归约 为开始符号S (即施用 S –> w),且没有余留输 入了,意味着已成功分析了整个输入串。
4、移进归约分析中还会出现一种情况,就是出 错,比如当前的token不能构成一个合法句子的 一部分,例如上面的文法,试分析i+)时就会发生 错误。

编译原理第七章

编译原理第七章

4
LR 分析器工作示意图
5
步骤 符号栈 输入符号串
1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) # #a #ab #aA #aAb #aA #aAc # aAcd #aAcB #aAcBe #S abbcde# bbcde# bcde# bcde# cde# cde# de# e# e# # #
13、 T • int 14、 T int • 15、 T •(E) 16、 T (• E) 17、 T (E •) 18、 T (E) • 注意: ① 初态 ② 句柄识别态 ③ 句子识别态
注意:拓广文法引入的意义。(确保初态唯一)
23
NFA for Viable Prefixes of the Example
求解方程组可得: [S’] = [S] = [A] = a+[A] [B] = aAc
推论:若文法G中有产生 式B→A,则有 LC(A) LC(B)· {}
[A] = a|[A]
[A] = a*=a
这样求出了每个非终结符在规范推导中用该非终结符的右部 替换该非终结符之前,它的左部可能出现的所有前缀,也就 是在规范归约过程中用句柄归约成该非终结符之前不包括句 柄的活前缀。 15
归约(如何找当前句柄归约)?
3
3) 4) 5) 6)
#ab #aA #aAb #aA
bcde# bcde# cde# cde#
归约(A→b) 移进 归约(A→Ab) 移进
分析:已分析过的部分在栈中的前缀不同,而且移进和归 约后栈中的状态会发生变化
我们引入一个新的状态栈来表示符号栈中的符号目前状态
用LR分析表来表示不同状态下对于各输入符号应采取的动 作

编译原理_第7章

编译原理_第7章

29
§7.3 赋值语句的翻译
3.例题:写出下列代码段中表达式的翻译制导过 程及其所产生的四元式 begin Integer:B、C、D、X;
X:=-B*(C+D);
end
符号表 <B> B <C> C <D> D <X> X Int Int Int Int (1) (2) (3) (4) 四元式 Op - + * := arg1 <B> <C> T1 T3 arg2 <D> T2 - result T1 T2 T3 X
语义处理分两步:
1.静态语义分析,即验证语法结构合法的程序是否真正有意义。
2.若静态语义正确,语义处理则要执行真正的翻译。 即要么生成程序的一种中间表示形式(中间代码),
要么生成实际的目标代码。
静态语义检查包括:
(1)类型检查; (2)控制流检查; (3)一致性检查; (4)相关名字检查。
2
第七章
8
§7.1 中间语言
例子:如图所示,为a+a*(b-c)+(b-c)*d的DAG
+
+
* a b c
*
d
9
§7.1 中间语言
2.抽象语法树
例子:(1)a:=b*-c+b*-c的图表示法
assign a * b uminus c b + * uminus c DAG
10
assign
a + * b uminus c
数据区中的相对地址offset.
(3)综合属性: T.type-名字的类型; T.width-名字的域宽(即该类型名字所占用 的存储单元个数)
22
§7.2 二、保留作用域信息

编译原理第七章

编译原理第七章

2014年6月15日12时14分
非终结符号T有两个综合属性 T.type 和T.width,分别表示 名字的类型和名字的域宽 (即该类型名字所占用的存储单 元个数)。 假定整数类型域宽为4;实数域宽为8;一个数组的域宽可 以通过把数组元素数目与一个元素的域宽相乘获得;每个 指针类型的域宽假定为4。 计算说明语句中名字的类型和相对地址的翻译模式如下:
子表达式 (base-((low1*n2)+low2)*w的值是可以在编译时 确定的。
2014年6月15日12时14分
例 1 设A为一个10*20的数组,即n1=10,n2=20。并设w=4。 赋值语句x:=A[y, z] 被翻译成如下三地址语句序列: T1:=y*20 T1:=T1+z T2:=A-84 T3:=4*T1 T4:=T2[T3] x:=T4
2014年6月15日12时14分
7.4 布尔表达式的翻译 在程序设计中,布尔表达式有两个基本作用:一个是用作 计算逻辑值;另一个用作控制流语句之中的条件表达式。 计算布尔表达式的值通常有两种办法。一种办法是,如同 计算算术表达式一样,一步不差地从表达式各部分的值计 算出整个表达式的值。例如,按通常的习惯,用数值1代 表true,用0代表false,那么,布尔式1 or (not 0 and 0) or 0的计算过程是: 1 or (not 0 and 0) or 0 =1 or (1 and 0) or 0 =1 or 0 or 0 =1 or 0 =1
S→id:=E {p:=lookup(); if p≠nil then emit(p’:=’E.place) else error} {E.place:=newtemp; emit(E.place’:=’E1.place’+’E2.place)}

编译原理Chapter 7

编译原理Chapter 7

prev
next 40
LR(0)分析表的构造※
dir
LR(0)分析表相当于识别活前缀的有限自动
机DAF的状态转换矩阵
prev
next 41
LR(0)分析表的构造算法
dir
令包含S’→•S 的项目集Ik的下标k为分析器的初态
LR(0)分析表的ACTION和GOTO表的构造步骤如下:
若项目 A→•a 属于Ik,且转换函数GO(Ik,a)= Ij ,当a为终结符时,则置ACTION[k,a]为Sj 若项目 A→• 属于Ik ,则对a为任何终结符或‘#’, 置ACTION[k,a] = rj ,j为产生式在文法G’中的编 号 若项目 X→•A 属于Ik ,且GO(Ik,A)= Ij ,则置 GOTO[k,A]=j,其中A为非终结符,j为某一状态号 若项目 S’→S• 属于Ik ,则置ACTION[k,#] = acc 其它填上“报错标志”,可用空白表示
Step2 对初态集或其它所构造的项目集应用转
换函数 GO(I,X)= CLOSURE(J)求出新状态 J的项目集
Step3 重复Step2直到不出现新的项目集为止
prev next 36
dir
S’ E A B
E aA | bB cA | d cB | d
c
c a
I4:Ac•A A•cA A•d I2:Ea•A A•cA A•d
prev
next 46
S’E[0] EaA[1]|bB[2] AcA[3]|d[4] BcB[5]|d[6]
dir
对输入串bccd#的分析
符号栈 输入串 bccd# ACTION S3
up
步骤 状态栈 0 1 03 2 035 3 0355 4 5 6 7

编译原理课件第7章

编译原理课件第7章

P→MD M→ {offset := 0 }
D→D ; D
D→id : T {enter( , T.type, offset );
offset := offset + T.width}
T→integer {T.type := integer; T.width := 4}
T→real {T.type := real; T.width := 8}
D→id : T {enter( , T.type, offset ); offset := offset + T.width}
P
offset=0
D
D
;
offset=8
D
offset=12
id
:
T
id
:
T
real
enter(x,real,0)
2020/2/3
T.type=real T.width=8
• type row = record
• address: integer;
• lexeme: array[1..15] of char
• end;
• var table : array [1..10] of row;
6.如果T是类型表达式,那么pointer(T)也是类型表 达式,表示“指向类型为T的对象的指针”。
integer T.type=integer
T.width=4
enter(i,integer,8)
20
例 x:real; i:integer 的翻译
P{offset:=0}D {offset:=0}D;D {offset:=0}x:T{enter(x,T.type,offset);

编译原理课件Chapter-7

编译原理课件Chapter-7
INTEGER X;
(2)
CALL M2( IND + 1 );
END M1;
M2: PBLOCK( INTEGER J );
高层(内层)模块可以引用低层(外层) 模块中的变量,例如在M1中可引用外层模块中 定义的变量 Y。
在 M1 中引用Y时,可通过其 display 区找 到程序块 1 的活动记录基地址,加上 Y 在该数 据区的相对地址就可以求得 y 的绝对地址。
abp
(a) 进入模块1
1 BBLOCK; 2 REAL X, Y; STRING NAME; M1: PBLOCK( INTEGER IND ) ; INTEGER X;
CALL M2( IND + 1 );
3 END M1; M24: PBLOCK( INTEGER J ); BBLOCK; ARRAY INTEGER F( J ); LOGICAL TESTI; … END END M2;
(h)当最外层模块执行完,运行栈恢复到进入模块时 的情况,运行栈空。
main的数据 (空) 进入main函数的情况 OS
abp(0) → (空) 1
BBLOCK; 2 REAL X, Y; STRING NAME; M1: PBLOCK( INTEGER IND ) ; INTEGER X;
CALL M2( IND + 1 );
3 END M1; M24: PBLOCK( INTEGER J ); BBLOCK; ARRAY INTEGER F( J ); LOGICAL TESTI; … END END M2;
CALL M1( X / Y )
END
1 X, Y, NAME
2 M1: (IND); X;
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Return sequence
被调用者将返回值放到和参数相邻的位置 恢复top_sp和寄存器,跳转到返回地址。 和寄存器, 恢复 和寄存器 跳转到返回地址。
版权所有 计算机学院 闫健恩
25
调用代码序列的例子
版权所有 计算机学院 闫健恩
26
7.3.4栈中的 栈中的 变长数据
如果数据对象 的生命期局限 于过程活动的 生命期, 生命期,就可 以分配在运行 时刻栈中。 时刻栈中。 top指向实际的 指向实际的 栈顶 top_sp用于寻 用于寻 找顶层记录的 定长字段
18
运行时刻栈的例子
运行栈: 运行栈:把控制栈中的信息拓广到包括过程 活动所需的所有局部信息(即活动记录) 活动所需的所有局部信息(即活动记录) s a : array s
版权所有 计算机学院 闫健恩
19
运行时刻栈的例子
运行栈: 运行栈:把控制栈中的信息拓广到包括过程 活动所需的所有局部信息(即活动记录) 活动所需的所有局部信息(即活动记录) s a : array r i: integer s r
版权所有 计算机学院 闫健恩
11
7.3 栈式分配
内容: 内容: 活动树 活动记录 调用代码序列 栈中的变长数据
版权所有 计算机学院 闫健恩
12
7.3.1 活动树
过程调用(过程活动)在时间上总是嵌套的: 过程调用(过程活动)在时间上总是嵌套的:
后调用的先返回 因此可以用栈式分配来处理过程活动所需要的 内存空间。 内存空间。
22
k: integer
7.3.3 调用代码序列
调用代码序列(calling sequence)为活动记录 调用代码序列 为活动记录 分配空间,填写记录中的信息; 分配空间,填写记录中的信息; 返回代码序列(return sequence)恢复及其状 返回代码序列 恢复及其状 是调用者继续运行。 态,是调用者继续运行。 调用代码序列会分割到调用者和被调用者 中。
5
版权所有 计算机学院 闫健恩
7.1 概述
主题
存储管理:栈分配、堆管理、 存储管理:栈分配、堆管理、垃圾回收 对变量、 对变量、数据的访问 本章核心问题
如何访问到数据
版权所有 计算机学院 闫健恩
6
1)存储分配的典型方式 )
目标程序的代码放置在代码 目标程序的代码放置在代码 区 静态区、堆区、 静态区、堆区、栈区分别放 置不同类型生命期的数据值, 置不同类型生命期的数据值, 即数据区
程序运行的所有过程活动可以用树表示
每个结点对应于一个过程活动 根结点对应于main过程的活动 根结点对应于 过程的活动 过程p的某次活动对应的结点的子结点对应于 过程 的某次活动对应的结点的子结点对应于 此次活动调用的各个过程活动(从左向右, 此次活动调用的各个过程活动(从左向右,表 示调用的先后顺序)。 示调用的先后顺序)。
第七章 运行时刻环境
计算机科学与技术学院 闫健恩
版权所有 计算机学院 闫健恩
1
概 述 静态存储管理 栈式存储管理 堆式存储管理
版权所有 计算机学院 闫健恩
2
7.1 概述
运行时刻环境
为数据分配安排存储位置 确定访问变量时使用的机制 过程之间的连接 参数传递 和操作系统、 和操作系统、输入输出设备相关的其它接口
版权所有 计算机学院 闫健恩
27
7.4 非局部数据的访问(无嵌套过程) 非局部数据的访问(无嵌套过程)
没有嵌套过程时的数据访问
C语言中,每个函数能够访问的变量 语言中, 语言中
要么是这个函数的局部变量:就在当前活动记录内, 要么是这个函数的局部变量:就在当前活动记录内, 可以通过top_sp指针加上相对地址来访问变量 可以通过 指针加上相对地址来访问变量 要么是全局变量:在静态区, 要么是全局变量:在静态区,抵制在编译时刻可知
PASCAL中,如果过程 中 如果过程A 的声明中包含了过程B的 的声明中包含了过程 的 声明,那么B可以使用在 可以使用在A 声明,那么 可以使用在 中声明的变量。 中声明的变量。 B的代码运行时 的代码运行时, 当B的代码运行时,如果 它使用的是A中的变量 中的变量。 它使用的是 中的变量。 那么这个变量指向运行栈 中最上层的同名变量。 中最上层的同名变量。 但是, 但是,我们不能通过嵌套 层次直接得到A的活动记 层次直接得到 的活动记 录的相对位置。 录的相对位置。
版权所有 计算机学院 闫健恩
8
静态和动态存储分配
动态分配
栈式存储:和过程的调用 返回同步进行分 栈式存储:和过程的调用/返回同步进行分 配和回收, 配和回收,值的生命期和过程生命期相同
有可变数组、有过程和函数的递归和嵌套。 有可变数组、有过程和函数的递归和嵌套。
堆存储: 堆存储:生命期比相应过程调用的生命期更 长的调用。 长的调用。
10
7.2 静态存贮分配
符号表如下,DA栏表示数据区编号,ADDR栏是相对 符号表如下,DA栏表示数据区编号,ADDR栏是相对 栏表示数据区编号 地址 NAME VA 入 位 长 TYPE KIND L DA ADDR 口 置 度 01 0 4 integer 简变 K a 02 4 1 integer 简变 K a+4 03 5 1 integer 简变 K a+8 ┋
版权所有 计算机学院 闫健恩
7
2)静态和动态存储分配 )
静态分配
编译器在编译时刻就可以做出存储分配决 定,不需要考虑程序运行时刻的情形 不存在可变长的数组、可变长的字符串、 不存在可变长的数组、可变长的字符串、 指针; 指针; 不存在函数或过程的嵌套和递归。 不存在函数或过程的嵌套和递归。 全局变量
7.4.2 嵌套深度
嵌套深度是正文概念, 嵌套深度是正文概念,可以根据源程序静 态地确定 不内嵌于任何其他过程中的过程,嵌套 不内嵌于任何其他过程中的过程, 深度为1 深度为 嵌套在深度为i的过程中的过程 的过程中的过程, 嵌套在深度为 的过程中的过程,深度 为i+1.
版权所有 计算机学院 闫健恩
目的
编译程序除了要关心目标代码生成问题外, 编译程序除了要关心目标代码生成问题外, 还必须要考虑程序运行时使用的数据区域的管理 问题。 问题。
版权所有 计算机学院 闫健恩
3
7.1 概述
为什么要使用数据区 程序运行时各种数据必须放在内存中, 程序运行时各种数据必须放在内存中, 便于访问和使用。 便于访问和使用。 数据区的管理 内存永远不能满足需要; 内存永远不能满足需要; 必须找到存贮的数据; 必须找到存贮的数据; 按照程序单位(过程、函数) 按照程序单位(过程、函数)分配和 管理数据区。 管理数据区。
版权所有 计算机学院 闫健恩
13
活动树的例子( 活动树的例子(1)
程序: 程序:P277,图7-2 , 过程调用(返回) 过程调用(返回)序 列和活动树的前序 后序) (后序)遍历对应 假定当前活动对应结 点N,那么所有尚未 , 结束的结点对应于N 结束的结点对应于 及其祖先结点。 及其祖先结点。
有静态变量(static)、指针、表单等。 、指针、表单等。 有静态变量 手工进行回收 垃圾回收机制
版权所有 计算机学院 闫健恩
9
7.2 静态存贮分配
分配方式 在符号表中按照对象属性顺序分配 数据区,从而建立一个数据映像, 数据区,从而建立一个数据映像,运 行时按照此映像分配实际的内存数据 区。
版权所有 计算机学院 闫健恩
版权所有 计算机学院 闫健恩
20
运行时刻栈的例子
运行栈: 运行栈:把控制栈中的信息拓广到包括过程 活动所需的所有局部信息(即活动记录) 活动所需的所有局部信息(即活动记录) s a : array q (1, 9) k: integer s r q(1,9)
版权所有 计算机学院 闫健恩
21
运行时刻栈的例子
版权所有 计算机学院 闫健恩
void A() { int void { } void C(); } 调用C, 又调用 又调用B时 当A调用 ,C又调用 时: 调用
B的活动记录 的活动记录 C的活动记录 的活动记录 A的活动记录 的活动记录
29
x,y; B() int b; x = b+y; C(){B();}
根据源语言、目标机器、操作系统的限制, 根据源语言、目标机器、操作系统的限制,可 以有不同的分割方案 把代码尽可能放在被调用者中。 把代码尽可能放在被调用者中。
版权所有 计算机学院 闫健恩
23
调用/返回代码序列的要求 调用 返回代码序列的要求
数据方面
能够把参数正确地传递给被调用者 能够把返回值传递给调用者
7.3.2 活动记录
过程调用和返回由控制栈进行管理 每个活跃的活动对应于栈中的一个活动 记录 活动记录按照活动的开始时间, 活动记录按照活动的开始时间,从栈底 到栈顶排列
版权所有 计算机学院 参 返 回 值 可选的控制链 可选的访问链 保存的机器状态 局 部 数 据 临 时 数 据
很容易将C语言的函数作为参数进行传递 很容易将 语言的函数作为参数进行传递
参数中只需要包括函数代码的开始地址。 参数中只需要包括函数代码的开始地址。 在函数中访问变量的模式很简单, 在函数中访问变量的模式很简单,不需要考虑过程 是如何激活的。 是如何激活的。
版权所有 计算机学院 闫健恩
28
7.4.1非局部数据的访问(无嵌套过程) 非局部数据的访问(无嵌套过程) 非局部数据的访问
17
指向调用者的 活动记录 用来访问存于其 它活动记录中的 非局部数据
版权所有 计算机学院 闫健恩
运行时刻栈的例子
a[11]为全局变量 为全局变量 main没有局部变量 没有局部变量 r有局部变量 有局部变量I 有局部变量 q的局部变量 ,和参 的局部变量i, 的局部变量 数m,n。 。
相关文档
最新文档