编译原理-第8章-符号表管理
第8章 符号表管理和错误处理

2011年8月10日 18
小结
编译程序在其工作过程中使用最多的数据结构是表 编译程序在其工作过程中使用最多的数据结构是表, 最为重要, 在这些表中,符号表最为重要 它的生存期最长、 在这些表中,符号表最为重要,它的生存期最长、使 用最频繁。 用最频繁。 掌握符号表的作用、内容、组织(多采用散列法 散列法) 掌握符号表的作用、内容、组织(多采用散列法) 明确错误处理的两种方法: 明确错误处理的两种方法:错误校正和局部化处理 了解局部化处理方法的实现
S.P 词法分析程序
符 号 表 管 理
语法分析程序 语义分析、 语义分析、生成中间代码 代码优化 生成目标程序 O.P
错 误 处 理
编译原理
2011年8月10日
1
第9章 符号表管理和错误处理
教学目标
明确符号表的作用、内容、 1. 明确符号表的作用、内容、组织 2. 明确错误处理的两种方法:错误校正和局部化处理 明确错误处理的两种方法:
编译原理
2011年8月10日
8
构造Hash函数的方法: 函数的方法: 构造 函数的方法
将标识符中的每个字符转换为一个非负整数 将得到的各个整数组合成一个整数( 将得到的各个整数组合成一个整数(可以将第一 中间的和最后一个字符值加在一起, 个、中间的和最后一个字符值加在一起,也可以将 所有字符的值加起来) 所有字符的值加起来) 将结果数调整到0~M-1范围内,可以利用取模的方 范围内, 将结果数调整到 范围内 为素数) 法,Ki%M(M为素数) ( 为素数
编译原理
2011年8月10日
15
错误局部化处理的实现(递归下降分析法) 错误局部化处理的实现(递归下降分析法) err: 全局变量,存放错误信息。 全局变量,存放错误信息。 •用递归下降分析时,如果发现错误,便将有关 用递归下降分析时,如果发现错误, 用递归下降分析时 错误信息(字符串或者编号) err, 错误信息(字符串或者编号)送err,然后转错 误处理程序; 误处理程序; • 出错程序先打印或显示出错位置以及出错信息, 出错程序先打印或显示出错位置以及出错信息, 然后跳出一段源程序,直到跳到语句的右界符或 然后跳出一段源程序 直到跳到语句的右界符或 正在分析的语法成分的合法后继符号为止,然后 正在分析的语法成分的合法后继符号为止 然后 再往下分析。 再往下分析。
编译原理蒋宗礼课件第8章

22
8.4.2 程序块结构符号表的其他实现
对图8.10 中的程序
...
a0 ... b0 ...
NULL NULL
(a) 处理到语句(5)时的符号表
... a0 ... b1 ... b0 NULL NULL
(b) 处理到语句(7)时的符号表
23
8.4.2 程序块结构符号表的其他实现
对图8.10中的程序
名字 符号种类 符号表表项1 符号表表项2 符号表表项3 abc i myarray ... 变量 变量 数组 int int int ... 基本属性 类型 地址 扩展属性指针 0 4 8 NULL NULL 维数 2 各维维长 3 4 扩展属性
图8.3 多种符号共用符号表的一种实现结构
11
8.1.2 符号表中的属性
19
8.4.2 程序块结构符号表的其他实现
• 将所有块的符号表放在一个大数组中,然后再引入 一个程序块表来描述各程序块的符号表在大数组中 的位置及其相互关系
名字 外层块 符号个数 起始指针 0 1 2 3 -1 0 1 1 2 1 1 1 程序块表 1 2 3 4 5 a b b b a 符号表 属性
– 如栈式存储分配时,i的地址是以栈指针sp为基址 加上i相对于活动记录起始地址的偏移量offseti
• 符号表中各符号的地址属性就是该符号相对于 第一个符号的偏移地址
13
8.3 符号表的组织结构 8.3.1 符号表的线性表实现
• 用线性表实现符号表较为直观
– 数组实现:插入n个符号、执行e次查找操作的时 间复杂度为T(n, e) = O(n(n+e)) – 有序数组实现:插入n个符号、执行e次查找操作 的时间复杂度为T(n, e) = elog n+ (log i) + i ≤ (n+e)log n+O(n2)
编译原理符号表的作用

编译原理符号表的作用介绍编译原理中的符号表是一个重要的数据结构,用于存储程序中的标识符及其相关信息。
标识符可以是变量、常量、函数名等,在编译过程中需要进行词法和语义分析,符号表提供了一个地方来管理这些标识符,并为编译器的其他模块提供必要的信息。
作用符号表在编译过程中起着关键作用,它具有以下几个主要作用。
1. 标识符的声明符号表记录了程序中所有标识符的声明情况,包括标识符的类型、作用域等信息。
对于变量,符号表可以记录其数据类型和内存地址;对于函数,符号表可以记录其参数列表、返回值类型等。
编译器可以通过符号表查找标识符的声明信息,并根据需要进行语义检查和代码优化。
2. 标识符的引用和解析编译过程中,标识符可能会被多次引用,符号表用于解析标识符的引用。
编译器可以根据符号表中的信息确定标识符的类型、作用域等,从而进行语义检查和类型推导。
如果编译器在符号表中找不到对应的标识符,就会报错或警告,提示可能存在的错误。
3. 作用域管理符号表还可以用于管理标识符的作用域。
在程序中,不同的代码块可能定义了相同名称的标识符,符号表可以通过作用域信息来区分这些标识符。
当编译器遇到一个标识符时,它可以在符号表中查找该标识符的作用域,并根据作用域规则来解析标识符的含义。
4. 错误检测和提示符号表还可以用于错误检测和提示。
编译器可以通过符号表判断标识符是否已经定义或声明,以及是否满足相应的语义规则。
如果标识符在符号表中已经存在多个定义,编译器可以发现这种错误,并给出相应的错误提示信息。
符号表的组织结构为了高效地实现符号表的作用,通常采用哈希表或树形结构来组织符号表。
下面是一些常见的符号表组织结构。
1. 线性表符号表可以使用线性表结构进行组织,例如数组、链表等。
线性表结构简单直观,适用于较小规模的符号表。
但对于大规模的符号表,线性表的查找效率较低。
2. 哈希表哈希表是一种基于键值对存储的数据结构,可以快速地查找和插入数据。
符号表中的标识符可以作为哈希表的键,对应的信息可以作为值进行存储。
编译原理(第2版)课后习题答案详解

第1 章引论第1 题解释下列术语:(1)编译程序(2)源程序(3)目标程序(4)编译程序的前端(5)后端(6)遍答案:(1)编译程序:如果源语言为高级语言,目标语言为某台计算机上的汇编语言或机器语言,则此翻译程序称为编译程序。
(2)源程序:源语言编写的程序称为源程序。
(3)目标程序:目标语言书写的程序称为目标程序。
(4)编译程序的前端:它由这样一些阶段组成:这些阶段的工作主要依赖于源语言而与目标机无关。
通常前端包括词法分析、语法分析、语义分析和中间代码生成这些阶段,某些优化工作也可在前端做,也包括与前端每个阶段相关的出错处理工作和符号表管理等工作。
(5)后端:指那些依赖于目标机而一般不依赖源语言,只与中间代码有关的那些阶段,即目标代码生成,以及相关出错处理和符号表操作。
(6)遍:是对源程序或其等价的中间语言程序从头到尾扫视并完成规定任务的过程。
第2 题一个典型的编译程序通常由哪些部分组成?各部分的主要功能是什么?并画出编译程序的总体结构图。
答案:一个典型的编译程序通常包含8 个组成部分,它们是词法分析程序、语法分析程序、语义分析程序、中间代码生成程序、中间代码优化程序、目标代码生成程序、表格管理程序和错误处理程序。
其各部分的主要功能简述如下。
词法分析程序:输人源程序,拼单词、检查单词和分析单词,输出单词的机内表达形式。
语法分析程序:检查源程序中存在的形式语法错误,输出错误处理信息。
语义分析程序:进行语义检查和分析语义信息,并把分析的结果保存到各类语义信息表中。
中间代码生成程序:按照语义规则,将语法分析程序分析出的语法单位转换成一定形式的中间语言代码,如三元式或四元式。
中间代码优化程序:为了产生高质量的目标代码,对中间代码进行等价变换处理。
目标代码生成程序:将优化后的中间代码程序转换成目标代码程序。
表格管理程序:负责建立、填写和查找等一系列表格工作。
表格的作用是记录源程序的各类信息和编译各阶段的进展情况,编译的每个阶段所需信息多数都从表格中读取,产生的中间结果都记录在相应的表格中。
编译原理第8章

6、翻译模式
P:说明语句,D:类型说明语句,id:标识符(变量名),T:类型 T T T T integer {T.type:=integer;T.width:=4} 变量名及 real {T.type:=real;T.width:=8} 其性质填 T1 {T.type:=pointer(T1.type);T.width:=4} 入符号表 array[num] of T1 {T.type:=array(num.val,T1.type); offset T.width:=num.val*T1.width} D id:T {Enter(,T.type,offset); offset:=offset+T.width} offset D D;D P D {offset:=0} 内存用户区 语义子程序(语义动作) 产生式
* a * b * @b * @ b * @
c c c c b d a+a*(b-c)+(b-c)*d的DAG a:=b*-c+b*-c的语法树 a:=b*-c+b*-c的DAG
第八章 符号表
3、与后缀式的关系:表达式的抽象语法树形式的中间代码与后 缀式等价,后缀式是抽象语法树的线性表现形式,是树的结点 序列(每个结点都在其所有子结点之后立即出现 )。
第八章 符号表
符号表的作用和地位 符号的主要属性及作用 符号表的组织
第八章 符号表
一、符号表的作用和地位
一、本章主要内容: 静态语义检查和翻译中间代码; 二、静态语义检查的内容: 类型检查、控制流检查、一致性检查、相关名字检查、 名字的作用域分析等; 三、翻译产生中间代码的优点: 便于进行与机器无关的代码优化工作、使编译程序改变目标 机更容易、使编译程序的结构在逻辑上更为简单明确; 四、静态语义检查和中间代码产生在编译程序中的地位:
第08章 符号表

7
概括地说,符号表的每一项 (或称入口) 包含 两大栏(或称区段、字域),即名字栏 信息栏 名字栏和信息栏 名字栏 信息栏。 表格的形式如下:
信息栏 (INFORMATION)
名字栏(NAME) 第1项(入口1) 第2项(入口2)
…
第(入口n)
8
信息栏包含许多子栏和标志位,记录相应 名字的种种不同属性。由于查填符号表一般是 通过匹配名字来实现的,故名字栏也称主栏 主栏, 主栏 其内容称为关键字 关键字(keyword) 。 关键字 符号表中每一项都是关于名字的说明。因 为所保存的关于名字的信息取决于名字的用途, 所以各表项的格式不一定统一,为使表中的每 个记录格式统一,可采用指针技术,在记录中 设置指针,把某些信息放在表的外边,用指针 指向存放另外信息的空间。
22
INCWAP(M, PROCEDURE INCWAP(M,N:INTEGER); LABEL START; VAR K:INTEGER; BEGIN START: K:=M+1; M:=N+4; N:=K; 表 0.2 常数表 CT END. 值 (VALUE) (1) 1 (2) 4
23
INCWAP(M, PROCEDURE INCWAP(M,N:INTEGER); LABEL START; VAR K:INTEGER; BEGIN START: K:=M+1; M:=N+4; N:=K; 表 0.3 入口名表 ENT END.
表 0.4 标号表 LT NAME INFORMATION (1)START 四元式:(4)
26
INCWAP(M, PROCEDURE INCWAP(M,N:INTEGER); LABEL START; VAR K:INTEGER; 表 0.5 四元式表 QT BEGIN START: OPR OPN1 OPN2 RESULT K:=M+1; (1) link M:=N+4; N:=K; (2) par INCWAP 1 M END. (3) par INCWAP 2 N (4) + M 1 K (5) + N 4 M (6) := K N (7) return
编译原理课件 第8章 符号表与错误处理

8.2 常用符号表结构 由于在整个编译过程中需不断地访问符
号表,因而如何构造符号表以及如何查填符 号表就成为编译程序设计的重要问题之一。 除了上述介绍的用于嵌套结构程序语言的栈 式符号表外,还有其它常用符号表结构。
1.线性符号表 符号表中最简单且最容易实现的数据结 构是线性表,它是按程序中标识符出现的先 后次序建立的符号表,编译程序不做任何整 理次序的工作。
⑦定义性出现或引用性出现标志(指标号); ⑧是否对该变量进行过赋值的标志,等等。 (2)过程名: ①是否为程序的外部过程; ②若为函数,应指出它的类型; ③是否处理过相应的过程或函数定义; ④是否递归定义; ⑤指出过程的形参,并按形参顺序将其种属、
类型等信息与过程名相联系,以便其后检查实 参在顺序、种属及类型上是否与形参一致。
对于编译程序所用的符号表,它涉及的 基本操作大致可归纳为五类:
(1) 判断一个给定的名字是否在表中; (2) 在表中填入新的名字; (3) 对给定名字访问它在表中的有关信息; (4) 对给定名字填入或更新它在表中的某
些信息; (5) 从表中删去一个或一组无用的项。
8.1.2 符号表的组织 符号表有多种组织方式。按处理对象的
为实现上述查填表, 按如下方式组织符号表: (1) 分层组织符号表的登记项,使各分程
序的符号表登记项连续地排列在一起,不允 许被其内层分程序的符号表登记项所分割。
(2) 建立一个分程序表,记录各层分程序 符号表的有关信息。分程序表中的各登记项 在自左至右扫描源程序中按分程序出现的自 然顺序依次填入,且对每一分程序填写一个 登记项。因此,分程序表各登记项的序号隐 含地表征了各分程序的编号。
符号表中的每一项包括两部分:名字、与
名字有关的信息,这些信息全面反映各个语法 符号的属性及它们在编译过程中的特征,如名 字的种属、名字的类型、特征(定义性还是使 用性出现等)、给此名字分配的存储单元地址 及与此名字语义有关的其它信息等。
编译原理第八章 符号表

8.3 名字的作用范围(Fortran)
• Fortran 局部、全局
• 执行时过程(函数)不
Name
Information
嵌套,局部区域只有一
···
局
个现行段;
···
部 • 编译时,尽管查填符号
表过程只限于局部,但
考虑到地址分配的全局
性,需将每个程序段符
号表保存在外存中,采
• 定长方式 • 间接方式 (1)名字的间接存储 (2)信息的间接存储
Name ● ●
Information
如何组织
方式
6 S A MP L E 3 S U M
Name
Information ● ●
数组信息表 维数 首地址 维1
内情向量表
··· ···
以数组为例 维n
如何组织
• 对于名称:把所有标识符都存放在一个 独立的字符串数组,主栏只放一个指示 器和一个整数(名字的长度)
var f, g: real; procedure B3(y:real) const b=5; procedure B4 … end B4 end B3
end B2 end B1
8.3 名字的作用范围 (Pascal)
top
(14)…
B4 (13)…
0
h (12)… 13
sp b (11)…
12
y (10)…
最近使用优先查找 (链头)
较难
中 排序整理 折半查找
二叉树
较难
中 构造排序树,查找时 依子树次序逼近。
杂凑(哈希
难
表)
高 杂凑函数: 名称于位置的映射 基于计算的查找。
数据结构的知识
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 2 3 4 5
图8.12 图8.10的另一种符号表结构
8.4.2 程序块结构符号表的其他实现
将符号所属程序块的编号放在符号表表项中。 查找某个符号的名字name时,只有当name和 符号表中的名字字符串完全匹配,且符号表 表项中的块编号和当前处理的块编号完全相 同时才算查找成功,否则要新建一个名字为 name且块号为当前块编号的符号表表项。
2014-7-6
10
8.1.2 符号表中的属性
建立多个符号表来管理源程序中出现的各种符 号,如常数表、变量表、函数表、数组表等
可能出现不同种类符号出现重名的问题
建立一张共用的大表来管理各种符号,此时需 要在符号表中增设一个标志来表明符号的种属
不同种类符号所需存放属性信息在数量上的差异 将会造成符号表的空间浪费
程序块编号可以通过在语法制导定义中的块开始 处和块结束处添加适当的语义规则计算得出。
2014-7-6
22
8.4.2 程序块结构符号表的其他实现
程序块满足最近嵌套原则
内层程序块中的局部变量只有全部处理完成之后才进 入外层块 一旦进入外层程序块,内层块的局部变量就不会再使 用了,可以从符号表中将这些符号删除 符号表中最前面的符号一定是当前正在处理的块中的 局部变量 符号表表项中可以不用存放块编号,而是根据符号表 表项在符号表中的位置来判断。
a
b
c
i
m
a
i
n
(a)标识符长度放在符号表中
2014-7-6 7
8.1.1 符号表中的名字
名字 符号表表项1 符号表表项2 符号表表项3 ... ... 属性
3
a
b
c
1
i
4
m
a
i
n
...
(b) 标识符长度放在字符串中
2014-7-6
8
8.1.1 符号表中的名字
名字 符号表表项1 符号表表项2 符号表表项3 ... ... 属性
如栈式存储分配时,i的地址是以栈指针sp为基址 加上i相对于活动记录起始地址的偏移量offseti
符号表中各符号的地址属性就是该符号相对于 第一个符号的偏移地址 14 2014-7-6
8.3 符号表的组织结构 8.3.1 符号表的线性表实现
用线性表实现符号表较为直观
数组实现:插入n个符号、执行e次查找操作的时 间复杂度为T(n, e) = O(n(n+e)) 有序数组实现:插入n个符号、执行e次查找操作 的时间复杂度为T(n, e) = elog n+ (log i) + i ≤ (n+e)log n+O(n2)
开散列表表头数组 0 1 13 ... 37 ... 108 NULL i NULL NULL NULL ... 名字 abc 属性 myarray NULL
2014-7-6
图8.6 一个符号表的散列表实现
16
8.3.2 符号表的散列表实现
引入散列表不仅可以提高lookup操作的效率, 同时也可号表实现中均采用了散列 技术
名字 符号表表项1 符号表表项2 符号表表项n
2014-7-6
属性 ... ... ... ...
5
abc i ... ...
...
图8.1 符号表的基本格式
8.1.1 符号表中的名字
名字字段长度固定
名字项的长度大小取决于标识符允许的最大长度 不适于标识符长度变化范围较大的语言 空间浪费 标识符的长度没有限制 符号表上的操作复杂而低效
2014-7-6
11
8.1.2 符号表中的属性
名字 符号种类 符号表表项1 符号表表项2 符号表表项3 abc i myarray ... 变量 变量 数组 int int int ... 基本属性 类型 地址 扩展属性指针 0 4 8 NULL NULL 维数 2 各维维长 3 4 扩展属性
图8.3 多种符号共用符号表的一种实现结构
n
n
i 1
i 1
有序符号表结构只有在下面的情况下才能取得较 好效果:和插入操作次数相比,符号表表项上的 查找操作次数占绝对多数,即e>>n。
15
2014-7-6
8.3.2 符号表的散列表实现
引入散列表不仅可以提高lookup操作的效率, 同时也可以提高insert操作的效率,所以在许 多实际编译器的符号表实现中均采用了散列 技术
图8.11 图8.10中的程序所对应的符号表
20
8.4.2 程序块结构符号表的其他实现
将所有块的符号表放在一个大数组中,然后再引入 一个程序块表来描述各程序块的符号表在大数组中 的位置及其相互关系
名字 a b b b a 符号表
21
属性
外层块 符号个数 起始指针 0 1 2 3 -1 0 1 1 2 1 1 1 程序块表
插入n个符号,查找e个符号的lookup操作和insert 操作的时间复杂度T(n,e)还将与m有关,记为 T(n,e,m) ,T(n,e,m)≈n(n+e)/m S(n,m)=O(n) b n 散列函数应在满足 的前提下,使 b (b 1)/2 达到最小
m
m
j 1 j
readarray header 4 i,integer,0
exchange header 0
partition header i,integer,0 j,integer,4
2014-7-6
8
28
本章小结
符号表用来存放编译器各阶段收集来的各种名字的 类型和特征等有关信息,并供编译程序用于语法检 查、语义检查、生成中间代码及生成目标代码等; 源程序中会出现各种各样的名字,如函数名、函数 参数名、函数中的局部变量名、全局变量名、数组 名、结构名、文件名等,相应的属性可以是种属、 类型、地址等。 根据符号所需的属性个数和类型的不同,可以组成 不同的符号表,也可以组成统一的符号表,在组成 统一符号表时,需要采用恰当的组织结构,以便可 以对其进行高效处理。 29 2014-7-6
2014-7-6
3
8.1 符号表的作用
符号表是以名字为关键字来记录其信息的数据 结构,其上支持的两个最基本操作应该是填加 表项和查找表项,这两个操作必须是高效的
2014-7-6
4
8.2 符号表中存放的信息
记录源程序中出现的各种名字及其属性信息是 符号表的首要任务。 显然同一个名字在一段程序中应该表示同一个 对象,即同一个符号表中不能出现相同的名字, 因此名字可以作为符号表的关键字。于是,每 一个符号表表项中需要存放的基本信息就是符 号的名字及其属性 。
名字 表项1 可用 指针 可用 指针 表项3 表项2 表项1
2014-7-6
属性 局部名字表 (当前函数)
abc i
表项2
quicksort main g_array 全局名字表
图8.16 一个完整C程序的符号表
26
8.4.4 嵌套过程的符号表
Pascal等允许在过程中嵌套定义其它过程
program sort(input, output); procedure readarray; begin … end{ readarray }; procedure exchange( i, j : integer ); begin … end{ exchange }; procedure quicksort( m, n : integer ); function partition( x, y : integer ); begin … end{ partition }; begin … end{ quicksort }; begin … end{ sort };
8.4.1 程序块结构的符号表
变量的作用域满足最近嵌套原则
(1) int main() (2) { (3) int a=0; (4) int b=0; (5) { (6) int b=1; (7) { (8) int a=2; (9) printf(“%d %d\n”, a, b ); (10) } (11) { (12) int b=3; (13) printf(“%d %d\n”, a, b); (14) } (15) printf(“%d %d\n”, a, b); (16) } (17) printf(“%d %d\n”, a, b); (18) }
School of Computer Science & Technology Harbin Institute of Technology
第8章 符号表管理
重点:符号表的作用,符号表的组织结构,符号
表与作用域。
难点:符号表的组织结构及其性能评价。
第8章 符号表管理
8.1 符号表的作用 8.2 符号表中存放的信息
j 1 j
j
2014-7-6
17
8.4 符号表与作用域
int main() { 运行结果为: abc is 2 int abc; abc is 1 abc = 1; 说明abc在不同的范围内有效。 { 这个有效范围就是符号的作用域 int abc; abc = 2; printf(“abc is %d\n”, abc); } printf(“abc is %d\n”, abc); } 2014-7-6 18 图8.8 一个具有程序块结构的C语言程序
2014-7-6 27
8.4.4 嵌套过程的符号表
nil header a,array,0 x,integer,40 readarray exchange to readarray to exchange quicksort header k,integer,0 v,integer,4 partition