编译原理 第9章 语义分析和代码生成(Modified)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
➢1、可移植性:如果花很小的代价,就能将一个 程序移植到另一台机器上,那么称该程序是可移植 的。
➢2、可适应性:如果一个程序能够容易地进行修
改就能满足不同的用户和系统的需求,那么称该程
序是可适应的。
精品课件
9.2 中间代码
要将一个给定的编译程序从X机移植到Y机,如果给定 的编译程序已分成前端和后端两部分,而且这两部分之 间定义有良好接口,那么移植的主要工作仅仅是重写现 有编译程序的代码生成程序以产生Y机的代码。一种较 理想的接口形式是抽象机的汇编程序,即能够将源语言 的各种语法结构映射到该抽象机的伪操作上。
17.AND 将栈顶两单元做逻辑与运算,并将结果真或假(1
或0)置于栈顶
18.OR 将栈顶两单元做逻辑或运算,并将结果真或假(1
或0)置于栈顶
19.NOT 将栈顶的逻辑值取反
20.IN 从标准输入设备(键盘)读入一个整型数据,并
入操作数栈
21.OUT 将栈顶单元内容出栈,并输出到标准输出设备(显
示器)
9.3 声明的处理
不同的程序设计语言,声明语句的结构也不一 样。 ➢有的语言类型说明在实体前,有的在实体后。 ➢有的语言要求每一个实体都要用一个独立的声 明语句进行声明(Ada语言即属于此类),有的语 言在一个独立的声明语句中可声明多个类型相 同的实体。
精品课件
9.3 声明的处理
C语言声明语句的类型说明是在实体前,而且,允许 一条声明语句可声明多个类型相同的实体,如“int a,b,c;”。在自左向右扫描和处理C语言声明语句时, 编译器首先知道类型,在扫描到后面的实体后,就可 为该实体建立符号表的记录,并可将类型及其它信息 填入符号表中。
<常量声明>→const <ID>↑n=<常量表达式>↑c,s@插入↓n,c,s <常量表达式>↑c,s→<int constant>↑c,s|<real constant>↑c,s
|<string co常ns量t>声↑c明,s 的处理流程: ➢1)首先识别常量的名字,将其赋给属性n; ➢2)识别综合常量表达式,将其值放在c中,并将表达式 的类型赋给属性s。 ➢3)调用动作程序@插入,其功能是调用符号表管理程序, 将名字n、类型s及表达式的值c填入符号表中。
精品课件
9.2 中间代码
构建抽象机模型的基本原则:
➢1)与源语言的操作和数据的良好对应:编译程 序的前端将源程序中的每一个原始操作和原始数 据模式翻译成抽象机指令。
➢2)在目标机上的高效实现:抽象机的伪操作能 够迅速转换成目标机的机器指令。
➢3)虚拟体系结构:需要为抽象机体系构建一个 运行环境,以便在该环境中模拟语言的数据模式 和操作的相互作用。 精品课件
➢2)语义分析的另一个重要功能是要分析由语法分 析所识别出来的语句的意义并作相应的语义处理。 例如,对声明语句,用户通过这类语句声明程序中 要使用的变量,并说明其种类和类型等特性。语义 分析程序就要将变量名及其有关属性填入符号表, 以备后面使用。对于程序中的可执行语句,则要根 据该语句的语义生成相应精品的课件中间代码或目标代码。
TEST机 汇编代码 TEST编译器
精品课件
TEST机
运行 结果
9.2 中间代码
为了提高可读性、简化代码生成过程,我们的目标 平台所采用的机器是一台抽象的栈式计算机,它用 一个栈来保存操作数,并有足够的内存空间,该抽 象机(TEST机)的常用汇编指令(P173)如下:
1. LOAD D 将D中的内容加载到操作数栈。
例(P175) const SYM精B品S课I件ZE=1024
9.3 声明的处理
如果一个标识符声明为常量,在程序中不能对该 标识符进行赋值,只能引用。因为符号常量名虽然 也保存在符号表中,但符号表中记录了符号常量的 名字、类型及符号常量的值,并没有为其分配内存 地址,这是符号常量与变量的关键区别。
精品课件
9.2 中间代码
波兰后缀表示的特点: 操作符位于操作数之后。
例(P170) 算术表达式:F*3.1416*R*(H+R)
波兰后缀表示: F3.1416*R*HR+* 赋值表达式:S=F*3.1416/R*(H+R)
波兰后缀表示: SF3.1416*R/HR+*=
精品课件
9.2 中间代码
精品课件
12.NOTEQ 将栈顶两单元做不等于比较,并将结果真或 假(1或0)置于栈顶
13.GT 次栈顶大于栈顶操精品作课件数,则栈顶置1,否则置0
9.2 中间代码
14.LES 次栈顶小于栈顶操作数,则栈顶置1,否则置0
15.GE 次栈顶大于等于栈顶操作数,则栈顶置1,否则置
0
16.LE 次栈顶小于等于栈顶操作数,则栈顶置1,否则置0
精品课件
9.2 中间代码
精品课件
9.2 中间代码
精品课件
9.2 中间代码
三元式的一般表示: <操作符>,<操作数1>,<操作数2>
例(P171)
表达式W*X+(Y+Z)可用如下三元式序列 表示:
(1) *,W, X
(2) +,Y, Z (3) +,(1),(2)
对每一个三元式都 编上号码,且对前面三元式 的计算结果的引用可用三元 精式品课的件 编号来表示。
9.2 中间代码
用一个抽象机的汇编语言作为TEST编译器的目标语 言。TEST机的指令仅能作为TEST语言的目标。TEST机 的模拟程序直接从一个文件中读取汇编代码并执行它, 因此避免了由汇编语言翻译为机器代码的过程。但是, 这个模拟程序并非是一个真正的汇编程序,它没有符 号地址或标号。
TEST程序
9.3 声明的处理
从代码生成和语义分析的要求出发,处理声明时编 译程序的主要任务: ➢1)分离出每一个被声明的实体,并将它的名字填入 符号表。 ➢2)尽可能多地将要保留在符号表中的有关该实体的 信息填入符号表。
一旦声明了一个实体,编译器就可使用符号表中的信 息进行如下的分析和处理: ➢1)检查对所声明实体的引用是否正确。 ➢2)利用已声明实体的属性信息,例如类型和已分配 的目标地址,为其它执行精语品课句件 生成正确的目标代码。
PASCAL声明语句的类型说明是在实体后且允许一次声 明多个实体,如“VAR age,day:integer”,那么, 在自左向右扫描和处理这样的声明语句时,编译器分 离出实体后,不知道该实体的类型,填符号表时,无 法填写类型信息,因此,必须记住这些未填类型的实 体在符号表中的位置,以便在扫描到类型之后,将声 明语句中有关实体的全部精信品课息件 回填到符号表中。
9.2 中间代码
例(P171)条件语句if (X>Y) Z=X;else Z=Y+1;
可以用如下三元式序列表示:
(1) >,X,Y
(2) BMZ,(1),(5)
(3) =,Z,X
(4) BR, ,(7)
(5) +,Y,1
(6) =,Z,(5)
(7) …
注意:操作符BMZ和BR分别表示零转移和无
条件转移。
精品课件
例(P173) 有下段程序: int a,b; a=10; b=20*a; 假设记录a、b属性信息符号 表为:
名类维地 字型数址
a100
b102
则相对应的抽象机汇编程序如下: LOADI 10 //将常量10入栈 STO 0 //将栈顶内容10存入地址0 LOADI 20 //将常量20入栈 LOAD 0 //将地址0的内容10加载到操作数栈 MULT //将次栈顶单元与栈顶单元内容出栈并相乘,积 置于栈顶。 STO 2 //将栈顶内容20精0品存课件入地址2
C语言没有符号常量的概念,但C语言提供了宏定 义,如#define PI 3.14159,其功能与符号常量差 不多,但概念不一样。C语言的宏定义是在预处理 中完成的,在预处理中将C源程序中的所有PI替换 成3.14159,因此,C编译系统实际编译的源程序并 没有PI这个符号,自然PI也不会出现在符号表中。
精品课件
9.2 中间代码
精品课件
9.2 中间代码
波兰后缀表示除可用来表示表达式类的语言结构以外, 也能够通过操作符的扩充来表示其他的语言结构。
例(P171) 条件语句:if <expr> then <stmt1> else <stmt2> 可转换成波兰后缀表示:
<expr><label1>BZ<stmt1><label2>BR<stmt2> 注意:在该波兰表示中,引入了BZ和BR操作符。
精品课件
第9章 语义分析和代码生成(P169)
9.1 语义分析的概念 9.2 中间代码 9.3 声明的处理 9.4 表达式语句 9.5 if语句 9.6 while语句 9.7 for循环语句 9.8 write语句 9.9 read语句 9.10 过程调用和返回 9.11 语义分析及精代品课码件 生成实现
+,A,B, T1 +,C,D,T2 *,T1,T2,T3 -,T3,E,T4
注意:T1、T2、精T品3课和件 T4均是临时变量。
9.2 中间代码
要开发出可移植又适用的编译程序的一种方法是 使编译程序产生一种作为源程序中间形式的抽象机 的代码。而该抽象机的指令应当尽可能模仿所编译 的源语言的结构,且具备下列特点:
7. MULT 将次栈顶单元与栈顶单元内容出栈并相乘, 积置于栈顶。
8. DIV 将次栈顶单元与栈顶单元内容出栈并相除, 商置于栈顶。
9. BR lab 无条件转移到lab
10.BRF lab 检查栈顶单元逻辑值,若为假(0)则转移到 lab
11.EQ 将栈顶两单元做等于比较,并将结果真或假(1 或0)置于栈顶
例(P169) 考虑下段程序,有哪些语义错误? 1. { int a; 2. int b; 3. real a,c; 4. d=a+b; 5. }
精品课件
9.1 语义分析的概念
语义分析主要借助符号表记录的信息来实现语义 分析动作。常见的语义分析动作有:
➢1)对表达式中的操作数进行类型的一致性检查。 当发现类型不一致时,则强制或自动作相应的类型 转换。
9.2 中间代码
将中缀表达式转换成波兰后缀表示的算法实现: 设置一个操作符栈,当扫描到操作数时,就立
即输出该操作数。当遇到操作符时,则要与栈顶操 作符比较其优先级,若栈顶操作符优先级高于栈外 操作符,则输出该栈顶操作符;反之,则栈外操作 符入栈。而对于赋值表达式,只需定义赋值操作符 “=”的优先级低于可在表达式中出现的其他操作 符。
精品课件
9.2 中间代码
四元式的一般形式: <操作符>,<操作数1>,<操作数2>,<结果
>
其中,<结果>表示操作符操作的结果,该结 果通常是一临时变量,在以后可以由编译程序分配给 一个寄存器或者一个主存地址。四元式的优点是便于 进例行(优P1化72处)理表。达式(A+B)*(C+D)-E能够由下列四元式序 列表示:
2. LOADI 常量 将常量压入操作数栈
3. STO D 将操作数栈栈顶单元内容存入D,且栈顶 单元内容保持不变。
4. STI D 将操作数栈栈顶单元内容存入D,且栈顶 单元出栈。
5. ADD 将次栈顶单
9.2 中间代码
6. SUB 将次栈顶单元减去栈顶单元内容并出栈,差置 于栈顶。
9.3 声明的处理
符号常量在程序的执行期间不发生改变,其优 点是:符号常量名声明一次,在程序中就可以 多次使用;若要改变符号常量的值只需修改符 号常量声明中符号常量的定义值。符号常量标 识符被看作是全局的,因此要存放在符号表的 全局部分。
精品课件
9.3 声明的处理
PASCAL语言定义符号常量的属性翻译文法:
学习重点
声明的处理 表达式语句 if语句 while语句 for循环语句 write语句 read语句 过程调用和返回精品课件
9.1 语义分析的概念
语义错误:在语法分析中,严格按文法(上下文 无关文法)来检查语句的语法是否正确,但有些语 句单看语法结构并没有错误,但考虑该语句所处的 上下文会引起错误,称这种错误为语义错误。在语 义分析时会处理语义错误。
9.2 中间代码
使用中间代码的优点: ➢不考虑机器的特性,使生成的中间代码较为简单。 ➢生成中间代码的编译程序移植性好,只需为该中 间代码开发一个解释器或者将中间代码翻译为目标 机指令就能在目标机上运行。 ➢在中间代码上更便于做优化处理。
常见的中间代码: ➢(1)波兰后缀表示 ➢(2)N-元表示
三元式 四元式