第八章 语法制导翻译法
This presentation is the property of its rightful owner.
Sponsored Links
1 / 59

第八章 语法制导翻译法 PowerPoint PPT Presentation


  • 88 Views
  • Uploaded on
  • Presentation posted in: General

第八章 语法制导翻译法. 语法制导翻译概述. 语法制导翻译是继词法分析和语法分析后 , 对编译程序进行语义分析和翻译 ( 产生中间代码 ) 。 在语法分析过程中 , 随着分析的步步进展 , 根据每个产生式所对应的语义子程序 ( 或语义规则描述的语义动作 ) 进行翻译的办法称为语法制导翻译。. 本章学习的主要内容. 本章我们将主要讨论语法制导翻译的基本思想及其在在中间代码生成中的应用。主要包括:属性文法、各种常见中间语言形式、赋值语句的翻译,布尔表达式的翻译,控制语句的翻译、说明语句的翻译等。通过本章的学习,要求掌握语法制导翻译的基本思想和翻译方案。. 语义处理程序的两个功能.

Download Presentation

第八章 语法制导翻译法

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


3606092

第八章 语法制导翻译法


3606092

语法制导翻译概述

语法制导翻译是继词法分析和语法分析后,对编译程序进行语义分析和翻译(产生中间代码)。

在语法分析过程中,随着分析的步步进展,根据每个产生式所对应的语义子程序(或语义规则描述的语义动作)进行翻译的办法称为语法制导翻译。


3606092

本章学习的主要内容

  • 本章我们将主要讨论语法制导翻译的基本思想及其在在中间代码生成中的应用。主要包括:属性文法、各种常见中间语言形式、赋值语句的翻译,布尔表达式的翻译,控制语句的翻译、说明语句的翻译等。通过本章的学习,要求掌握语法制导翻译的基本思想和翻译方案。


3606092

语义处理程序的两个功能

第一,审查每个语法结构的静态语义,即检查语法结构合法的程序是否真正有意义。也称静态语义分析。(类型检查、控制流的检查、一致性检查、相关名字的检查)

第二,如果静态语义正确,语义处理则要执行真正的翻译,要么生成中间代码,要么生成实际的目标代码。(说明性语句:填符号表;可执行性语句:生成中间代码)


3606092

属性文法

  • 属性文法主要用来描述和说明程序设计语言语义的。

  • 属性:一般用来描述客观存在的事物或人的特征,编译技术中用属性来描述计算机要处理的对象的特征。

  • 属性文法:每个上下文无关文法的产生式,配以相关联的属性,属性的处理过程也就是语义的处理过程,为文法的每条规则配以相应的语义规则构成的文法称为属性文法。


3606092

属性文法

  • 属性文法的形式定义:

  • AG: AG=(G,V,E)

  • G:上下文无关文法;

  • V:属性的有穷集合;每一个属性与某一个文法符号相关联;用文法符号.属性表示

  • E:表示属性的断言或谓词的有穷集合(语义规则);每一个断言与文法的某个产生式相关联)

  • 属性:综合属性(自下而上)、继承属性(自上


3606092

语法制导翻译的基本思想

  • 对文法中的每个产生式都附加一个语义动作或语义子程序,在执行语法分析的过程中,每当使用一条产生式进行推导或规约时,就执行相应产生式的语义动作。

  • 这些动作不仅指明了该产生式所生成的符号串的意义,而且还根据这种意义规定了对应的加工动作.(如查填各类表格、改变编译程序的某些变量之值、打印各种错误信息以及生成中间代码等)从而完成预定的工作。


3606092

算术表达式求值

  • 语法分析分析的语法成分是简单算术表达式,所完成的语义的处理不是将它翻译成中间代码或目标代码,而是计算表达式的值。


3606092

算术表达式的属性文法

  • 简单算术表达式求值的语义描述。

  • 产生式 语义规则

  • (0) L→ E Print(E.val)

  • (1)E→E1+T E.val=E1.val+T.val

  • (2)E→T E.val= T.val

  • (3)T→T1*F T.val=T1.val * F.val

  • (4)T→ F T.val=F.val

  • (5)F→ (E) F.val=E.val

  • (6)F→digit F.val=digit.lexval(0~9)


3606092

翻译步骤

  • 首先,为文法的每条规则设计相应的语义子程序;

  • 增加一个语义信息栈;

  • 在语法分析的同时做语义处理:即在用某一个产生式进行规约的同时,调用相应的语义子程序完成所用规则的语义动作,并将每次动作后的值保存在语义栈中


2 3 5

计算表达式2+3*5


3606092

G[E]:

1 E→E+T

2 E→T

3 T→T*F

4 T→F

5 F→(E)

6 F→i

i+i*i


2 3 51

表达式2+3*5的归约过程


3606092

注意

  • 句柄归约在先,语义动作调用在后

  • 归约时,栈内句柄各符号的语义信息与句柄及同时出栈,整个句柄所表示的语义信息则赋给相应产生式左部非终结符号的语义变量,并让该非终结符号及语义信息同时入栈


3606092

中间代码

  • 中间代码是介于源程序和目标程序之间,用来表述源程序并与之等效的一种编码方式.

  • 生成中间代码的作用

  • (1)中间代码与具体机器无关,便于语法分析和语义加工,便于编译程序移植.

  • (2)易于对中间语言进行优化,有利于提高中间代码的质量.

  • (3)有利于编译程序的设计与实现,使编译各阶段的开发复杂性降低.

  • 常用的中间代码形式:逆波兰式、三元式、四元式、树代码等


3606092

逆波兰表示法(后缀式)

特点:运算符直接写在其运算对象之后。

  • 不再有括号

  • 运算对象出现的次序未变

  • 求值过程简单,宜于用栈实现

  • 例: a+b ab+

    a*b+c ab*c+

    a*(b+c/d) abcd/+*

    a*b+c*d ab*cd*+

    a:=b*c+d*e abc*de*+:=


3606092

三元式

一般形式:

(编号)〈运算符〉〈运算对象1〉〈运算对象2〉

i op arg1 arg2

  • 出现的次序是对应语法成分的计算次序

  • 无需引进临时工作变量,用三元式的编号代替之,节省了存贮空间

  • 其中的编号代表某个三元式的位置编号和代表某个三元式的值

  • 之间的联系靠编号进行,因此,三元式的移动较困难,不便于优化


A b c

表达式a+(-b)*c的三元式

  • (1) (@,b,_);单目运算,运算对象2为空

  • (2) (*,(1),c)

  • (3) (+,a,(2))


3606092

X=a+b*c

Y=d-b*c

三元式表

(1)(*,b,c)

(2)(+,a,(1))

(3)(=,x,(2))

(4)(_,d,(1))

(5)(=,y,(4))

三元式


3606092

四元式(三地址代码)

一般形式:

〈运算符〉〈运算对象1〉〈运算对象2〉〈结果〉

(op , arg1, arg2 , result)

例: X=a*b+c*d的四元式序列 三地址代码

(1)(* ,a,b,T1) (1)T1=a*b

(2)(*, c,d,T2) (2)T2=c*d

(3)(+,T1,T2,T3) (3)T3=T1+T2

(4)(=,T3,_,X) (4)X=T3


3606092

属性翻译文法的应用

综合属性与自下而上定值

每个非终结符的属性值都是根据位于其下面那些符号的属性值来确定的,即按一种自下而上的方式来确定的。

继承属性和自上而下定值

非终结符的属性值或者根据其上层非终结符的属性来确定或者根据产生式右部其它符号的属性来确定。这种属性值是根据自上而下方式确定的。


3606092

自底向上的语法制导翻译

  • 自底向上的语法制导翻译方法是在自底向上的语法分析过程中逐步实现语义规则的翻译方法。在实现时注意以下几点:

    (1)自底向上的翻译的特点,栈的操作,对产生式的要求等

    (2)各种程序语句的目标结构

    (3)从源结构到目标结构的变换方法(包括对产生式的改造等)


3606092

算术表达式和赋值语句的翻译

  • 翻译步骤:

  • (1)分析文法的特点;

  • (2)设计一系列的语义变量、定义语义过程、语义函数;

  • (3)设计每一条规则的语义子程序;

  • (4)增加一个语义信息栈,构造LR分析表;

  • (5)语法分析同时语义处理.


3606092

  • 例: 有文法G[A]:

  • 1. A→i:=E

  • 2. E →E+T∣T

  • 3. T →T*F∣F

  • 4.F →-P

  • 5.P →i ∣(E)

    简单算术表达式的计值顺序与四元式出现的顺序相同,因此目标代码的顺序(结构)为:

    (1)先生成E的代码(一系列顺序执行的四元式)

    (2)把E的值赋给变量i(表达式的结果赋给赋值语句的左变量)


3606092

  • 引入语义变量,语义过程和语义函数

  • (1)E.place:表示存放E值的变量名或在符号表中的入口地址;

  • (2)函数newtemp():申请一个临时单元,存放中间结果;

  • (3)过程emit(T=arg1 op arg2):产生一条四元式,并添入四元式表中;

  • (4)lookup(i.name):审查i.name是否出现在符号表中,在:返回地址,不在:返回NULL;

  • (5)函数entry(i):回送标识符i在符号表中的入口地址.


3606092

表达式的语义动作设计

  • 1. A→i:=E{emit(entry(i)=E.place}

  • 2. E →E1+T{E.place=newtemp(), emit(E.place)=E1.place+T.place}

  • 3.E →T {E.place=newtemp(), emit(E.place=T.place)}

  • 4. T →T1*F{T.place=newtemp(), emit(T.place)=T1.place*F.place}

  • 5. T →F {T.place=newtemp(), emit(T.place=F.place)}


3606092

  • 6.F →_P {F.place=newtemp(), emit(F.place)[email protected]}

  • 7.P →(E) {P.place=newtemp(), emit(P.place=E.place)}

  • 8.P →i{P.place=newtemp(), emit(P.place=Entry(i))}


X a b c d

K+1: T1:=c-d

K+2: T2=b*T1

K+3: T3:=a+T2

K+4: X:=T3

(-,c,d,T1)

(*,b,T1,T2)

(+,a,T2,T3)

(:=,T3,_,X)

例如:表达式X:=a+b*(c-d)的翻译


3606092

布尔表达式的翻译

  • 布尔表达式

    是由布尔运算符(and,or,not)作用于布尔变量(或常数)或关系表达式而形成的。

  • 布尔表达式的作用:

  • 用作控制语句中的条件:if-then、 while、repeat等

  • 逻辑赋值句中的逻辑运算


3606092

布尔表达式到四元式的翻译

  • 文法:EEEEEE(E)idE rop E

    其中,(and)、(or)、(not)为布尔(逻辑)运算符;rop为关系运算符(>,≥,,≤,=,≠);id为布尔(逻辑)变量或布尔(逻辑)常数;E rop E为关系表达式。

  • 布尔表达式的求值方法:

    ① 通过逐步计算出各部分的值来计算整个表达式。

    ② 利用布尔运算符的性质计算其值


3606092

布尔表达式作为控制语句中的条件式

  • 作用是用于选择下一个执行点

  • while E do S1

  • E的作用是选择S1执行,还是跳过S1语句,执行S1后面的语句

  • E有两个出口:

  • 真:S1语句

  • 假:S1后面的语句


While

whille

W.head

E的代码 真

do

S1的代码

JMP W.head

While语句的目标结构


3606092

布尔初等量(布尔变量和关系表达式)的目标结构

  • 由两个转移四元式构成,一个表示真出口Li,另一个表示假出口Lj,设E是一布尔变量, 它的目标结构为:

  • (1) if E goto Li (jumpt , E,_, Li )

  • (jnz,A,_, Li)

  • (2) if E1 rop E2 goto Li (jumpθ ,E1 ,E2 ,Li)

    (jrop,E1,E2, Li) 例:(j<,a,b,p)

  • (3) goto Lj (jump Lj ) (j,_,_, Lj )


If a b then a x y

if a<b goto Li (真出口)

goto Lj (假出口)

Li:S的第一个四元式

S的最后一个四元式

Lj:S 后面的语句

(1) if a<b goto (3)

(2) goto (5)

(3)T1:=x+y

(4)A:=T1

(5)

举例:if a<b then A:=x+y的四元式序列


3606092

多因子组成的布尔表达式的翻译

  • 例: if a<b ∨c then S1 else S2

  • 分析结果如下:

  • 当a<b为真,执行S1,不需要计算c的值

  • 当a<b为假,计算c的值,c为真:执行S1,为假:执行S2

  • 当a<b与c分别为真时,程序转向一致,真出口相同(S1)

  • 当a<b与c分别为假时,程序转向一致,假出口相同(S2)


  • If a b c then s 1 elses 2

    (1) if a<b goto S1的第一条语句 (5)

    (2) goto (3)

    (3) if c goto S1的第一条语句 (5)

    (4) goto S2的第一条语句 ( p+1

    (5) 关于S1的四元式序列

    (p) Goto q

    (p+1)关于S2的四元式序列

    (q)后继四元式

    目标结构

    if a<b ∨c then S1 elseS2的四元式序列

    E的代码 T

    F

    S1的代码

    JUMP S

    S2的代码

    S(后继语句)


    If e then s 1 else s 2

    if E then S1 else S2的四元式序列

    • (1) if E goto (3)

    • (2) goto (S2的第一个四元式) (p+1)

    • (3)关于S1的四元式序列

    • ……

    • (p) goto r (执行完S1后转出)

    • (p+1)关于S2的四元式序列

    • ……

    • (r) 后继四元式


    While e do s 1

    while E do S1的四元式序列

    • (1) if E goto (3)

    • (2)goto ( S1后面的语句) (p+1)

    • (3)关于S1的四元式序列

    • ……

    • (p) goto (1)

    • (p+1) 后继四元式


    Backparch

    真出口链、假出口链、回填(Backparch)

    • 在多个因子组成的布尔表达式中,可能有多个因子的真出口或假出口的转移去向相同,但又不能立刻知道具体转向位置。

    • 把转移方向相同的四元式链在一起,一旦发现具体转移目标,就回填。

    • 真出口用Etrue来表示。

    • 假出口用Efalse来表示。

    • 回填Backparch(g,t)将t填入由g所指向的四元式的结果部分


    If a b c then s 1 elses 21

    if a<b ∨c then S1 elseS2的真假出口回填描述

    (1) if a<b goto 0 /E的真出口Etrue有待回填

    (2) goto (3) /*回填E的第一个假出口

    (3) if c goto (1)/* (3)是E的真出口链

    (4) goto 0 /*E的假出口Efalse有待回填

    (5) 关于S1的四元式序列/*此时回填真出口Etrue

    (p) goto 0 /*有待回填q的位置

    (p+1)关于S2的四元式序列/*此时回填假出口Efalse

    (q)后继四元式/*此时回填q


    3606092

    语法制导翻译中使用的公共变量、过程和函数

    • guad:四元式指针 (表示四元式的编号或地址)

    • GEN(X):生成一条四元式,把它放到四元式表的尾部,(和前面介绍的emit功能相同)

    • Nextguad:指向下一个即将形成的四元式的编号,其初值为1,执行一次GEN(X),Nextguad自动加1;

    • merg(p1,p2)函数将以 p1,p2为链首的两个四元式合并为一,返回合并后的链首


    3606092

    条件语句的翻译

    基本思路:

    • ① 先对定义它的文法进行改造,以便能在相应处添加上语义子程序;

    • ② 根据它的语义,设计出相应语义子程序的动作。


    3606092

    if语句的文法

    • S→ if E then S1

    • S→ if E then S1 else S2 (E是转移条件)

    • 对if E then S1 else S2,其Etrue直到扫描到then,产生S1的第一个四元式序号时,才能将该标号作为E的真链填入到Etrue,而Efalse

      直到扫描到else,产生S2的第一个四元式序号时,才得到Efalse的值。


    3606092

    (1) C→ if E then

    (2) T→ C S1 else

    (3) S →T S2

    (4) S → C S1

    目标结构如右图

    If

    E.true

    E.false

    E的代码

    then

    C.chain

    S1.chain

    S1的代码

    JUMP 0

    T.chain

    else

    S2.chain

    S2的代码

    S.chain

    if语句文法的改造


    3606092

    if语句的语义动作

    • (1) C→ if E then

    • {backpatch(Etrue,Nextguad),C.chain=Efalse}

      当用产生式if E then 进行归约时,生成了条件E的代码,E的假出口不能回填,通过非终结符C向后传递,所以引入C.chain链.


    3606092

    if语句的语义动作

    • (2) T→ C S1 else

    • {q:=Nextguad,emit(goto 0)

    • Backpatch(C.chain,Nextguad),

    • T.chain=merg(S1.chain,q)}

    • 当用产生式T→ C S1 else 归约时,S1的代码已经形成,回填E的 假出口即C.chain。此时S2的代码尚未形成,S1的转出链和JMP转向相同,合并为一,通过T向后传递.


    3606092

    if语句的语义动作

    • (3)S →T S2

    • {S.chain:=merg(T.chain,S2.chain)}

    • (4) S → C S1

    • {S.chain:=merg(C.chain,S1.chain)


    If a b c d then if a b then f 1 else f 0 else g g 1

    采用then 与else的最近匹配原则(三地址指令)

    (1)if A goto (3)

    (2)goto 0 (13)

    (3)if B goto (5)

    (4)goto (2) (13)

    (5) if C>D goto (7)

    (6)goto (4) (13)

    (7)if A<B goto (9)

    (8)goto 0 (11)

    (9)F:=1

    (10) goto 0 (15)

    (11) F:=0

    (12) goto (10) (15)

    (13) T:=G+1

    (14) G:=T

    (15)

    If A∧B ∧C>D then if A<B then F:=1 else F:=0 else G:=G+1


    If a b c d then if a b then f 1 else f 0 else g g 11

    四元式形式代码

    (1)(jnz,A,_,(3))

    (2)(j,_,_,0) (13)

    (3)(jnz,B,_,(5)

    (4)(j,_,_,(2)) (13)

    (5)(j>,C,D,(7))

    (6)(j,_,_,(4)) (13)

    (7)(j<,A,B,(9))

    (8)(j,_,_,0) (11)

    (9)(:=,1,_,F)

    (10)(j,_,_,0) (15)

    (11)(:=,0,_,F)

    (12)(j,_,_,(10)) (15)

    (13)(+,G,1,T)

    (14)(:=,T,_,G)

    (15)

    If A∧B ∧C>D then if A<B then F:=1 else F:=0 else G:=G+1


    While1

    文法:G[S]

    S→ while E do S

    文法改造为:

    S→ CS1

    C→ W E do

    W→ while

    whille

    W.head

    Efalse

    E的代码

    Etrue

    S1chain

    do

    C.chain

    S1的代码

    JMP W.head

    While 语句的翻译


    While2

    While 语句的语义动作

    • (1)W→ while {W.head:=Nextguad;}

    • 当用W→ while 归约时, Nextguad记下E的第一个四元式的位置,保留在Wguad中。

    • (2)C→ W E do {backpatch(Etrue, Nextguad, C.chain=Efalse,C.head= W.head}

    • 当使用C→ W E do 进行归约时,E的代码已经生成有两个出口Etrue和Efalse,扫描完do后,可以回填Etrue,而Efalse要到S1语句全部生成后才能回填,因此为待填信息,由C向后传递。


    While3

    While 语句的语义动作

    (3)SC S1

    {Backpatch(S1chain,C.head);S.chain:= C.chain;GEN(goto,W.head);

    当用上式进行归约时,S1语句全部产生,while 语句结束应返回,因此产生四元式(goto w.head),同时回填Efalse


    While a 0 b 0 do if x y then b b 1 else a a 1

    假设四元式序列从100开始编号

    100(j>,a,0,102)

    101 (j,_,_,0) (112)

    102 (j>,b,0,104)

    103 (j,_,_,101) (112)

    104 (j>,x,y,106)

    105 (j,_,_,0) (109)

    106 (-,b,1,T1)

    107 (:=,T1,_,b)

    108 (j,_,_,100)

    109 (j,a,1,T2)

    110 (:=,T2,_.a)

    111 (j,_,_,100)

    112

    while a>0∧b>0 do if x>y then b:=b-1 else a:=a-1


    3606092

    • 文法G[S]: S→SaA︱A

    • A→AbB︱B

    • B→cSd︱e

    • (1)证明AacAbcBaAdbed是文法的一个句型.

    • (2)请写出该句型的所有短语、素短语及句柄。

      (3)为文法G[S] 的产生式构造相应的翻译子程序,使句型AacAbcBaAdbed经该翻译方案翻译后,输出为131042521430。


    3606092

    S→bTc {print”1”}

    S→a {print”2”}

    T→R {print”3”}

    R→R/S {print”4”}

    R→S {print”5”}

    对于输入符号串

    bR/bTc/bSc/ac,该符号串的输出是什么?

    输出为1453142431

    归约的次序为:

    (1) S→bTc (1)

    (2) R→R/S (4)

    (3) R→S (5)

    (4) T→R (3)

    (5) S→bTc (1)

    (6) R→R/S (4)

    (7) S→a (2)

    (8) R→R/S (4)

    (9) T→R (3)

    (10) S→bTc (1)

    文法及相应的翻译方案如下:


    3606092

    数组赋值语句的翻译

    • 数组的一般定义:

    • a[l1:u1,l2:u2,…lk:uk,…,ln:un]

    • a 数组名; lk数组下标下限,uk上限,k数组维数

    • 数组元素地址可以由两部分构成:

    • D=bap+vap

    • bap:不变部分 bap=b-c; b是数组的首地址;

    • 二维数组: c=l1d2+l2(其中d 是维长,dk= uk-lk+1)

    • vap: 可变部分 vap=i1d2+i2


    3606092

    数组赋值四元式

    • T:bap T1:vap 数组:T1[T]

    • 可变部分[不变部分]

    • (1)数组赋值:

    • T1[T]=X 四元式为: ([ ]=,X,_, T1[T])

    • (2)数组引用:

    • X= T1[T] 四元式为: (=[], T1[T],_,X)


    A 2 3 d 1 2 d 2 3

    X:=A[i,j]的四元式序列:

    (1)T1=i*3

    (2)T1=T1+j

    (3)T2=b-4

    (4)T3=T2[T1]

    (5)X=T3

    A[i+3,j+2]=X+Y的四元式序列:

    (1)T1=i+3

    (2)T2=j+2

    (3)T3=T1*3

    (4)T3=T2+T3

    (5)T4=B-4

    (6)T5=X+Y

    (7)T4[T3]=T5

    数组元素的表示方法数组A[2,3] d1=2,d2=3


  • Login