程序设计语言编译原理第三版第7章
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
N→ Є
D →id: T { enter(top(tblptr), , T.type, top(offset)); top(offset):= top(offset) +T.width } 24
§7.2
说明语句
2.含嵌套说明的翻译模式:
(1)语义规则中的操作: Mktable (previous): 创建一张新符号表,并返回指向新表的一个指针; Enter (table, name, type, offset):
(2)置相对地址为当前offset之值, (3)使offset加上该名字所表示的数据对象的域宽。
20
§7.2 说明语句
3. 相应的翻译模式:
PD { offset:=0 } { enter (, T.type,offset);
DD;D
Did:T
offset:=offset+t.width } Tinteger
(0) (1) (2) (3) (4) (5)
(2) (3) (4)
16
§7.1 中间语言
4.间接三元式:便于代码优化处理
方法:间接码表+三元式表
按运算的先后顺序列出有关三元式在三元表中的位置 例: 语句X:=(A+B)*C;Y:=D↑(A+B)的间接三元式表示如下所示: 间接代码 三元式表 (1) (2) (3) (1) (4) (5)
30
已归约串
PLACE
输入串
语义动作
# #X # X:= # X:= # X:= # X:= # X:=
X:= -B*(C+D)# X := -B*(C+D)# X_ -B*(C+D)# X__ B*(C+D)# -B X__B *(C+D)# -E X__B *(C+D)# { E.place:=p=<B>} E1 X_T1 *(C+D)# {E1.place:=newtemp=T1; 生成四元式(1) } … … … … # X:=E*(C X_T1__C +D)# # X:=E*(E1 X_T1__C +D)# { E1.place:=p=<C> } … … … …
12
§7.1 中间语言
2.四元式:带有四个域的记录结构 (op,arg1,arg2,result) 内容均是指针, 指向有关名字的符号表入口
13
§7.1 中间语言
例子: 三地址语句a:=b*-c+b*-c的四元式表示 四元式表示
Op (0) (1) (2) (3) (4) (5) uminus * uminus * + := arg1 c b c b T1 T2 arg2 T1 T3 T4 result T1 T2 T3 T4 T5 a
语义分析和中间代码产生
中间代码:即中间语言,独立于机器的,复杂性介于源
语言和机器语言之间的一种表示形式。
采用中间语言的好处:
(1)便于进行与机器无关的代码优化工作; (2)使编译程序改变目标机更容易; (3)使编译程序的结构在逻辑上更为简单明确。
3
第七章
语义分析和中间代码产生
7.1 中间语言
7.2 说明语句 7.3 赋值语句的翻译 7.4 布尔表达式的翻译 7.5 控制语句的翻译 7.6 过程调用的处理(略)
Treal Tarray[num] of T1 T↑T1 { T.type:=integer; T.width:=4 } { T.type:=real; T.width:=8 } { T.type:=array(num.val,T1.type); T.width:=num.val×T1.width } { T.type:=pointer(T1.type);T.width:=4 }
在指针table指示的符号表中为名字name建立一个新顶,并
把类型type、相对地址offset填入到该项中;
25
§7.2
(1)语义规则中的操作: Addwidth (table, width):
说明语句
在指针table指示的符号表表头中记录下该表中所有名字
占用的总宽度; Enterproc (table, name, newtable): 在指针table指示的符号表中为名字name的过程建立一个 新顶。参数newtable指向过程name的符号表。
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
第七章
语义分析和中间代码产生
语义处理分两步:
1.静态语义分析,即验证语法结构合法的程序是否真正有意义。
2.若静态语义正确,语义处理则要执行真正的翻译。 即要么生成程序的一种中间表示形式(中间代码),
要么生成实际的目标代码。
静态语义检查包括:
(1)类型检查; (2)控制流检查; (3)一致性检查; (4)相关名字检查。
2
第七章
op (1) (2) (3) (4) (5) + * := ↑ := arg1 A (1) X D Y arg2 B C (2) (1) (1)
17
§7.2
说明语句
编译过程中,对“说明语句”要做的工作:
对一个过程或分程序的一系列说明语句,考察时:
(1)需要为局部于该过程的名字分配存储空间; (2)对每个局部名字,都需在符号表中建立相应的表项, 并填入有关的信息如类型、在存储器中的相对地址 等。
28
§7.3 赋值语句的翻译
2. 说明: -id所代表的名字本身 lookup()-检查符号表中是否存在相应 此名字的入口≠nil:返回一个该表项的指针 =nil:未找到 emit(--)-将生成的三地址语句发送到输出文件中 E.place-存放E值的名字 newtemp-产生“临时变量”
21
§7.2
说明:
说明语句
(1) offset: 全程变量,代表变量在过程数据区中的相对地址, 用来跟踪下一个可用的相对地址的位置. (2) enter(name,type,offset): 把名字name符号表,并给出此名字的类型type及在
过程数据区中的相对地址offset.
(3)综合属性: T.type-名字的类型; T.width-名字的域宽(即该类型名字所占用 的存储单元个数)
18
§7.2
一、过程中的说明语句
说明语句
1. 产生“说明语句”的文法:
PD DD;D
Did: T
Tinteger
Treal
Tarray[num] of T1 T↑T1
19
§7.2
2.处理方式:
说明语句
处理第一条说明语句之前,先置offset为0,以后每次 遇到一个新的名字,则:
(1)将该名字填入符号表中,
27
§7.3 赋值语句的翻译
一、简单算术表达式及赋值语句
1.产生“赋值语句”三地址代码的翻译模式:
Sid:=E { p:=lookup(); if p≠nil then emit(p‘:=’E.place) else error } EE1+E2 { E.place:=newtemp; emit(E.place‘:=’E1.place‘+’E2.place) } EE1*E2 { E.place:=newtemp; emit(E.place‘:=’E1.place‘*’E2.place) } E-E1 E(E1) Eid { E.place:=newtemp; emit(E.place‘:=’‘uminus’E1.place) } { E.place:=E1.place} { p:=lookup(); if p≠nil then E.place:=p else error}
7.7 类型检查 (略)
4
§7.1 中间语言
中间语言形式: 后缀式 三地址代码
间接三元式 DAG 抽象语法树
图表示法
三元式 四元式
5
§7.1 中间语言
一、后缀式—逆波兰式: 规则: (1)E-常量/变量: (2)E-E1 op E2: (3)E-(E1) : (4)E-op E1: 后缀式为E本身 E1’ E2’ op (E1’) E1’ op
语法树
§7.1 中间语言
(2) a:=b*-c+b*-c 的抽象语法树的两种表示法
assign
id + a
* id uminus id c b id
* b
uminus id c
0 id 1 Id 2 uminus 3 * 4 id 5 id 6 uminus 7 * 8 + 9 id 10 assign
b c 1 0 2
b
c 5 4 3 6 7 8
11
a
9
§7.1 中间语言
三、三地址代码 1.三地址代码:下面一般形式的语句构成的序列:
x:=y op z T1:=y*z, T2:=x+T1
x,y,z: 名字,常数,编译时产生的临时变量
op: 运算符号(如定点运算符,浮点运算符,逻辑运算符等) 称为三地址代码的原因: 每条语句通常包含三个地址,两个用来表示操作数,一 个用来存放结果。 具体实现:用记录表示,其中包含运算符和操作数的域。
14
§7.1 中间语言
3.三元式:
为了避免把临时变量填入符号表,可通过计算该临 时变量值的语句的位置来引用该临时变量。
(op,arg1,arg2)
或是指向符号表的指针—对程序中的名字而言 或是指向三元式表的指针—对临时变量而言
15
§7.1 中间语言
例子: 三地址语句a:=b*-c+b*-c的三元式表示 op uminus * umins * + assign arg1 c b c b (1) a arg2 (0)
6
§7.1 中间语言
例子: a*(b+c)— abc+* ab+cd+*
(a+b)*(c+d)—
x+y≤z∨a>0∧(8+z)>3— xy+z≤a0>8z+3>∧∨
7
§7.1 中间语言
二、图表示法
1.DAG(无循环有向图)
与抽象语法树对比 相同点:对表达式中的每个子表达式,它们都有一个结 点,一个内部结点代表一个操作符,它的孩子 代表操作数; 不同点:在一个DAG中代表公共子表达式的结点具有多个 父结点,而在一棵抽象语法树中公共子表达式 被表示为重复的子树。
22
§7.2 二、保留作用域信息
说明语句
1.嵌套过程中的说明语句 (1)相应的文法: PD DD;D | id: T | proc id; D; S (2)程序举例:
23
§7.2 说明语句
2.含嵌套说明的翻译模式:
P→M D M→ Є D → D1; D2 D → proc id; N D1;S { t:= top (tblptr); addwidth (t,top(offset)); pop(tblptr); pop(offset); enterproc ( top(tblptr), , t) } { t:= mktable (top (tblptr)); push(t,tblptr); push(0,offset) } { addwidth (top(tblptr), top(offset)); pop (tblptr); pop(offset) } { t:= mktable(nil); push(t,tblptr); push(0,offset) }
26
§7.2
(2)栈:
说明语句
tblptr:存放指向符号表的指针,栈顶为指向当前正在处理过 程的符号表指针. offset:存放变量在数据区中的相对地址,栈顶为当前正在处 理过程的下一个变量的相对地址。 (3) top(…):取当前栈顶元素 push(a,B):将a推进B栈栈顶 pop(A):将A栈栈顶元素出栈
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