本章要解决的问题
声明以及语句的语义效果的实现(三地址指令或四元式的生成)
主要的知识点:
- 声明语句的翻译
- 符号表的建立和使用
- 变量的类型声明语句的翻译,主要工作是
- 将类型表达式填入变量表
- 计算各变量的相对偏移地址
- 类型推导(忽略)
- 类型推导(inference)、类型综合(synthesis)、
- 类型合一(unification):求最大公共子集
- 表达式翻译及数组元素的寻址
- 在语义规则中利用类型表达式计算数组下标
- 两种方法
- 主要使用第一种:
- 主要使用第一种:
- 两种方法
- 在语义规则中利用类型表达式计算数组下标
- 控制流语句的翻译
- 以if then else语句为代表,其他的控制流问题比如布尔表达式的短 路计算、循环语句,case语句等在概念上都是一样的。
- 主要了解“.true” 、 “.false”尤其是“.next”的作用。
- 并链与回填
- 这个问题的产生在于语句标号和语句序号的不同。三地址语句使用 的是语句标号,四元式使用的是语句序号。语句标号是可以任意指 定的,不重复就可以,而语句序号是严格依序递增的。当一个跳转 语句向序号更大的语句(程序末尾方向)跳转时,无法得知跳转目 的地的序号(不知道离目的地有多远),需要等待跳转目的地的中 间指令生成时才能知道这个序号。并链就是跳到同一个目的地的跳 转语句手拉手排队,一起等通知。
- 对一个跳转语句,如果当前产生式中无法得知跳转目的地的序号, 那么就需要等待回填,等待回填的话再问问自己,当前有人和我去 同一个地方吗?如果有,那么咱们就并链等待回填,等待回填的语 句记录在truelist、falselist和nextlist里,truelist和falselist分别是条 件为真或为假时的等待回填的跳转语句(的链头),nextlist是其 他语句(主要是复合语句)的跳转语句的链头。
- .true, .false, .next要么产生是自己决定,要么继承自环境。
- .truelist, .falselis, .nextlist,都是下级向上级汇报。
- 并不是所有指向小序号的goto都不回填(例如while循环体的
- nextlis)。序号的大小不是决定因素,目的地是否由当前产生式决
- 定才是决定因素。
- 做题时注意保留修改痕迹,给出尚未回填的list。
1.三地址代码-Three-address Code(TAC)
地址可以具有的形式:
- 名字,A name(source-program names).
- 常量,A constant.
- 编译器生成的临时变量,A compiler-generated temporary.
1.1TAC类型和形式
二元算术和逻辑操作 | |
一元操作 | |
复制 | |
unconditional jump无条件转移
| |
条件转移 | |
函数调用 | |
返回return | return y |
Indexed copy instructions
索引的复制指令
| |
取地址 | |
解引用 |
1.2(语句标号与语句序号)Symbolic Labels vs. Position Numbers

1.3四元式Quadruples
2.类型和声明Types and Declarations
类型的应用可以分为:
- 类型检查,&&左右两边应该是bool
- 翻译时的应用,根据类型确定所需内存空间大小
2.1类型表达式type expression
类型表达式包括:
- 基本类型
- 类型构造算子作用域类型表达式
上面的笛卡尔积的部分用来表示如函数参数
其中上箭头表示指针
2.2类型等价Type Equivalence
2.2.1按结构等价
及具有相同的实现方式
2.2.2按名称等价
3.表达式翻译Translation of Expressions
- 表达式翻译及数组元素的寻址
- 在语义规则中利用类型表达式计算数组下标
- 两种方法
- 基于类型表达式的方法(龙书第二版,简单)
- 基于矩阵结构的方法(龙书第一版,复杂)
- 两种方法
- 在语义规则中利用类型表达式计算数组下标
3.1表达式中的运算
SDD使用S.code & E.addr & E.code, code代表三地址代码, addr代表值地址
3.2增量翻译Incremental Translation
简单来说,放弃了使用code属性拼接三地址指令,每生成一个新的三地址指令就将其输出。增量的输出。
3.3数组元素寻址Addressing Array Elements
这里默认下标从0开始。
其中 是已经计算好的,存放在符号表中的数值,所以在生成三地址代码时不应该再次计算
注意:当下标不从0开始时,
3.4数组引用翻译Translation of Array References
gen()代表产生三地址语句
例子 :
4.控制流
4.1布尔表达式
用途:
- 改变控制流,如if(E) S; 执行到S说明E为true
- 计算逻辑值,将true or false赋值给其他变量
注意B的结合律和op的优先级,
4.1.1 short circuit code 短路代码(跳转代码)
两个例子:
B1是false的时候应该继续计算B2,所以B1.false是一个newlabel()
疑问 :什么是translation scheme
答 : L-SDD 或 S -SDD
你可能会有疑问:为什么,中间要接上一个label(B1.false),因为在B1.code中最后有一个goto B1.false,而B1.false是新分配的标签也就是newlabel()。
例子:
4.2控制流语句(flow of control statements)
注意whlie循环中等于begin,以及每一个语句中标签的附加位置
5.并链和回填
有在同一个list中的跳转指令具有相同的目标标号。主要看产生式行为
其中merge(p1,p2)是将p2尾指向p1头,并返回p2头,同时需要更新接收的goto 0;
做题时需要将goto 0中的0划去然后回填,保留修改痕迹。