第五章 语义分析和中间代码的表示

45
第第第 语语语语语语语语语语语语 语语语语语语语 语语语语语语语语 语语语语 语语语语语语语语语语语

description

第五章 语义分析和中间代码的表示. 语义分析的概念 语法制导翻译方法 属性文法 几种常见的中间代码表示. 第一节 语义分析的概念. 语义分析: 即审查每个语法成分的静态语义。 在早期的一些编译程序中,是在语法分析的基础上根据源程序中各语法成份的语义,直接产生机器语言或汇编语言形式的 目标代码 。 现在的编译系统一般都将经过语法分析的源程序先翻译为某种形式的 中间语言代码 ,然后再将其翻译为目标代码。 优点 : 使编译程序各组成部分 功能更单一 ; 使得编译程序的 逻辑结构更为清晰 ,从而使编译程序更 易于编写与调整 ; 同时为代码优化和程序的 可移植性 提供了条件. - PowerPoint PPT Presentation

Transcript of 第五章 语义分析和中间代码的表示

Page 1: 第五章  语义分析和中间代码的表示

第五章 语义分析和中间代码的表示

语义分析的概念语法制导翻译方法属性文法几种常见的中间代码表示

Page 2: 第五章  语义分析和中间代码的表示

第一节 语义分析的概念 语义分析:即审查每个语法成分的静态语义。 在早期的一些编译程序中,是在语法分析的基础上根据

源程序中各语法成份的语义,直接产生机器语言或汇编语言形式的目标代码。

现在的编译系统一般都将经过语法分析的源程序先翻译为某种形式的中间语言代码,然后再将其翻译为目标代码。

优点优点: 使编译程序各组成部分功能更单一 ; 使得编译程序的逻辑结构更为清晰,从而使编译程

序更易于编写与调整 ; 同时为代码优化和程序的可移植性提供了条件

Page 3: 第五章  语义分析和中间代码的表示

在语义分析时也要进行语义检查,编译时的语义检查是静态语义检查,包括: 类型检查,如参与运算的操作数的类型应相

容。 控制流检查,用以保证控制语句有合法的转

向点。如 C 语言中不允许 goto 语句转入 case 语句流。

一致性检查,如 case 语句的标号不能相同。

Page 4: 第五章  语义分析和中间代码的表示

第二节 语法制导翻译 对文法中的每个产生式都附加一个语义动作

或语义子程序 , 在语法分析过程中,每当需要使用一个产生式进行推导或归约,语法分析程序除执行相应的语法分析动作外,还要执行相应的语义动作或调用相应的语义子程序。

这种模式实际上是对前后文无关文法的一种扩充。

Page 5: 第五章  语义分析和中间代码的表示

例如 , 文法 G[E]: 产生式产生式 语义动作 语义动作E→E(1)+T {E.Val=E(1).val+T.val;}E→T {E.Val=T.Val;}T→digit {T.Val=digit;} 为了能在语法分析过程中平行地进行

语义处理,可在语法分析栈旁边并行地设置一个语义信息栈。语义信息栈。

语法分析栈

语义分析栈

T T.Val

+ ‘+’

E

… …

#  

Page 6: 第五章  语义分析和中间代码的表示

产生式的语义是由组成该产生式的文法符号的语义所决定的。

我们可将这些语义以“属性属性”的形式附加到各个文法符号上,再根据产生式所蕴含的语义,给出每个文法符号的属性的求值规则,从而形成一种附带有语义属性的前后文无关文法,即属性文法属性文法。

第三节 属性文法

Page 7: 第五章  语义分析和中间代码的表示

属性文法 = 上下文无关文法 + 属性 + 求值规则 属性是用来描述文法符号的语义特征,如 常量的“值”、变量的类型和存储位置等。 求值规则(属性计算规则) 与产生式相关联的反映文法符号属性之间关系的 “ 规则”。 求值规则还可进一步扩展为语义规则(语义动作)。

1 、定义

Page 8: 第五章  语义分析和中间代码的表示

例:简单表达式的属性文法。

语 义 规 则 L→ E

E → E ( 1 ) +T

E → T T →T ( 1 ) * F

T → F

F → (E)F → digit

Print(E.val)

E.val:=E ( 1 ) .val+T.val

E.val:=T.val

T.val:=T ( 1 ) .val F.val T.val:=F.valF.val:=E.val

F.val:=digit.lexval

产 生 式

Page 9: 第五章  语义分析和中间代码的表示

若产生式 AX1X2…Xn ,与之相关的属性计算规则 b := f ( c1, c2, … ) ,

其中 f 是函数, b 和 c1, c2, …, ck 是该产生式文法符号的属性,-如果属性 b 是产生式左部符号 A 的属性, c1 , c2 , …, ck 是产

生式右部文法符号的属性或 A 的其它属性 , 则称其为 A 的综合属性;

-如果属性 b 是产生式右部符号 Xi 的属性, c1 , c2 , …, ck 是产生式右部文法符号的属性或 A 的属性则称其为 Xi 的继承属性;

- 终结符仅有综合属性 , 如 digit.lex_val 。通常由词法程序提供。而开始符号没有继承属性。

2 、属性的分类

Page 10: 第五章  语义分析和中间代码的表示

继承属性用于“自上而下”传递信息。 继承属性由相应语法树中结点的父结点和 /

或兄弟结点属性计算得到,它反映了对上下文依赖的特性。

继承属性可以很方便地用来表示程序设计语言上下文的结构关系。

几点说明:

Page 11: 第五章  语义分析和中间代码的表示

几点说明(续): 综合属性用于“自下而上”传递信息。 综合属性由相应语法树中结点的分枝结点属

性计算得到,即沿语法树向上传递,从分枝(子)结点到根结点。

思考:简单表达式文法中的属性各是什么类型的?

Page 12: 第五章  语义分析和中间代码的表示

A.b

X1.c1 X2.c2 Xn.cn…

综合属性 A.b 的计算

A

X1.c1 X2.c2 …

继承属性 Xk.b 的计算

Xk.b Xn.cn

Page 13: 第五章  语义分析和中间代码的表示

在语法树中 , 将每个结点均视为由若干个域组成的结构结构 ,则可将其中的一些域用来存放相应文法符号诸属性之值,并可用属性属性来为这些域命名。通常我们将每个结点都标注相应属性值的语法树称为注释分析树( Decorated Syntax Tree )。

属性求值的过程:在注释分析树中,一个文法符号 X在相应结点的综合属性之值,由其子结点的属性和(或) X的其它属性,通过相关属性规则经计算而得,故综合属性的求值在语法树中是按自下而上自下而上的方式进行的; X 的继承属性之值则由 X 的父结点和 ( 或 ) 其它兄弟结点来定义 ,故继承属性的求值将按自上而下自上而下的方式进行。

注释分析树注释分析树

Page 14: 第五章  语义分析和中间代码的表示

例: 8+5*2 的注释分析树。(综合属性)

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 15: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 16: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 17: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 18: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 19: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 20: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 21: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 22: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 23: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 24: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 25: 第五章  语义分析和中间代码的表示

分析树各结点属性的计算可以自下而上地完成

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 26: 第五章  语义分析和中间代码的表示

注释分析树 : 结点的属性值都标注出来的分析树

digit.lexval = 2

L

E.val = 18

T.val = 10E.val = 8

T.val = 8

F.val = 8

digit.lexval = 8

T.val = 5

+

*

F.val = 5

F.val = 2

digit.lexval = 5

Page 27: 第五章  语义分析和中间代码的表示

例:语句 int id,id,id 的语义分析。(继承属性)

产 生 式 语 义 规 则 D TL L.in := T.type T int T. type := integer T real T. type := real L L1, id L1.in := L.in;

addtype (id.entry, L.in ) L id addtype (id.entry, L.in )

Page 28: 第五章  语义分析和中间代码的表示

1 、 int id1, id2, id3 的注释分析树

D

int

T.type = integer

, id3

L.in = integer

L.in = integer

L.in = integer id2

id1

,

Page 29: 第五章  语义分析和中间代码的表示

2 、 int id1, id2, id3 的分析树的属性依赖图

D

int

T

, id3

L

L

L id2

id1

,

entry

entry

entry

in

in

intype

Page 30: 第五章  语义分析和中间代码的表示

对结点进行拓扑排序,按拓扑排序的次序计算属性。

拓扑排序:结点的一种排序,使得边只会从该次序中先出现的结点到后出现的结点。

3 、属性计算次序

Page 31: 第五章  语义分析和中间代码的表示

D

int

T

, id3

L

L

L id2

id1

,

1 entry

10 2 entry

3 entry

in 9

8in 7

6in 54 type

属性计算次序为 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ,10

Page 32: 第五章  语义分析和中间代码的表示

在上例中,按照拓扑排序可以得到下面的程序段(用 an来代表依赖图中与序号 n的结点有关的属性): 4) a4:=int 5) a5:=a4 6) addtype(id3.entry,a5) 7) a7:=a5 8) addtype(id2.entry,a7) 9) a9:=a7 10) addtype(id1.entry,a9)

Page 33: 第五章  语义分析和中间代码的表示

思考:如何通过对注释分析树进行树遍历的方法计算属性值?最常用的是深度优先、从左到右的遍历方法。

Page 34: 第五章  语义分析和中间代码的表示

小结:语法制导翻译的一般过程

语义规则和产生式联系起来: 对翻译给出高级说明 根据属性和计算规则,进行语义分析 输入单词符号串 构造注释分析树

构造属性依赖图,对结点进行拓扑排序根据语义规则的进行计算和处理

Page 35: 第五章  语义分析和中间代码的表示

第四节 中间代码的形式 抽象语法树 逆波兰式 三地址代码(四元式、三元式)

Page 36: 第五章  语义分析和中间代码的表示

语法树是分析树的浓缩表示:算符和关键字是作为内部结点。

语法制导翻译可以基于分析树,也可以基于语法树。 在抽象语法树表示中,每一个叶结点都表示诸如常量

或变量这样的运算对象,而其他内部结点则表示运算符。

1 、抽象语法树

Page 37: 第五章  语义分析和中间代码的表示

语法树的例子:

if-then-else

B S1S2

+

*

25

8

Page 38: 第五章  语义分析和中间代码的表示

2、逆波兰表示 波兰逻辑学家 J.Lukasiewicz于 1929 年提出的一种表示

表达式的方法。按此方法,每一运算符都置于其运算对象之后,故称为后缀表示。

表达式 E 的后缀表示递归定义如下: ( 1 )如果 E 是变量或常数,则 E 的后缀表示即 E自身。 ( 2)如果 E 为 E1 op E2形式,则它的后缀表示为 E1’E2’op;其中 E1’、 E2’分别是 E1 和 E2的后缀表示。若 op是一元运算符,则视 E1 和 E1’为空。

( 3)如果 E 为 (E1) 形式,则 E1 的后缀表示即为 E 的后缀表示。

特点 : 操作数出现的顺序与原来一致,而运算符则按运算先后的顺序放到相应的操作数之后,即运算符先后的顺序发生了变化,表达式中各个运算是按运算符出现的顺序进行的,故无须使用括号来指示运算顺序。

Page 39: 第五章  语义分析和中间代码的表示

例:中缀表示中缀表示 后缀表示后缀表示

A+B AB+A+B*C ABC*+(A+B)*(C+D) AB+CD+*x/y^z-d*e xyz^/de*-

程序语句的逆波兰表示略去。

Page 40: 第五章  语义分析和中间代码的表示

3、三地址代码(四元式和三元式) 四元式是一种更接近目标代码的中间代码形式,由于这

种形式的中间代码便于优化处理,因此,在目前的许多编译程序中得到了广泛的应用。

四元式是一种“三地址语句”的等价表示。 它的一般形式为: (op,arg1,arg2,resultresult) 其中, op为一个二元 ( 也可是一元或零元 ) 运算符 ; arg

1,arg2分别为它的两个运算对象,它们可以是变量、常数或系统定义的临时变量名;运算的结果将放入 resresultult 中。四元式还可写为类似于 PASCAL语言的赋值语句的形式: result := arg1 op arg2

Page 41: 第五章  语义分析和中间代码的表示

每个四元式只能有一个运算符,所以,一个复杂的表达式只能由多个四元式构成的序列表示。

例如,表达式 A+B*C 可写为序列 T1:=B*CT2:=A+T1

当 op为一元、零元运算(如无条件转移)时, arg2甚至 arg1 应缺省,即 result:=op arg1 或 op result ;对应的一般形式为:

(op,arg1,-,result)或

(op,-,-,result) 。

Page 42: 第五章  语义分析和中间代码的表示

例 赋值语句 a=b*(c+d) 相应的四元式代码为: (1) (+,c,d,t1) (2) (*,b,t1,t2) (3) (=,t2,_,a)

Page 43: 第五章  语义分析和中间代码的表示

为了节省临时变量的开销,有时也可采用一种三元式结构来作为中间代码,其一般形式为: (i) (op,arg1,arg2)

其中, (i) 为三元式的编号,也代表了该式的运算结果; op,arg1,arg2的含义与四元式类似。

区别在于 arg 可以是某三元式的序号,表示用该三元式的结果作为运算对象。

Page 44: 第五章  语义分析和中间代码的表示

例如,对于赋值语句 a:=-b*(c+d) ,若用三元式表示,则可写成

① (U_minus, b, - )② ( + , c, d )③ ( * , ①, ② )④ ( := , ③, a )

式①中的运算符 U_minus 表示一元减运算。

Page 45: 第五章  语义分析和中间代码的表示

除前面所述的抽象语法树、逆波兰式、四元式、三元式外,常见的中间语言还有接近PASCAL形式的 P-P- 代码代码,接近 C格式的 C-C- 代码代码等等。

4、其它表示法