中间代码

  • 语法分析之后,编译的任务是由已识别为正确的源程序生成一组规格一致,便于计算机加工的指令形式。

一、 中间代码生成方法

语法制导翻译,属性文法制导翻译

二、中间代码

中间代码:不是机器语言便于生成机器语言,便于代码优化。

  • 逆波兰式
  • 树形表示
  • 三元式
  • 四元式(最常用)

翻译方法

语法制导翻译

  • 在语法分析的基础上进行边分析边翻译

注:

  1. 语法制导翻译时会根据文法产生式右部符号串的含义,进行翻译,翻译的结果是生成相应中间代码。

  2. 语法制导翻译的依据是语义子程序

  3. 具体做法:为每个产生式配置一个语义子程序,当语法分析进行归约或推导时,调用语义子程序,完成一部分翻译任务。

语法制导翻译种类

  1. 自上而下语法制导翻译:对每个文法符号配以语义动作
  2. 自下而上语法制导翻译:我们主要讨论LR语法制导翻译。

语义子程序

语义子程序写在该产生式后面的花括号内。X→α{语义子程序1}

注:在一个产生式中同一个文法符号可能出现多次,但他们代表的是不同的语义值,要区分可以加上角标

如:E->E^1^ +E^2^

语义值

为了描述语义动作,需要为每个文法符号赋予不同的语义值:类型、地址、代码值等。

代表了符号表入口地址,如变量名、变量类型、变量地址

语义栈

各个符号的语义值放在语义栈中

  • 当产生式进行归约时,需对产生式右部符号的语义值进行综合,其结果作为左部符号的语义值保存到语义栈中。

下推栈包含3部分

  • 状态栈、符号栈和语义栈
  • 注:语义栈与状态栈和符号栈是同步变化的。

注:1)若把语义子程序改成产生某种中间代码的动作,就能在语法分析制导下,随着分析的进展逐步生成中间代码

image-20220605094905603

得到如下结果

image-20220605094911259

举例

image-20220605100701535

(1)第一步,将E->E+E归约并将语义相加

image-20220605100746936

对应的表

image-20220605101027643

  • 步骤7、8,由E+E归约为E,并且将top=9与top+2=7相加,求出16

中间代码形式

四元式形式

(操作符,操作数1,操作数2,结果)

image-20220605101427309

  • 变量采用符号表入口地址,因为语义分析中,需要变量的类型

三元式

(操作符,操作数1,操作数2)

image-20220605101628165

后缀表示

(操作数1,操作数2,操作符)

如:abc*+,得出a+(b*c)

树形表示

image-20220605101844089

赋值语句的翻译

  • 仅含简单变量的表达式和赋值语句的翻译赋值语句的文法

image-20220605102047654

image-20220605102139417

举例

image-20220605103154793

  • T是临时产生的,用来保存结果

image-20220605103300003

  • A入栈,A是个变量,

布尔表达式翻译

布尔表达式作用

一、布尔表达式在程序设计语言中的作用

  • 用作控制语句中的条件表达式;
  • 用于逻辑赋值语句中布尔表达式演算。

布尔表达式组成

image-20220605135920482

布尔表达式文法

image-20220605140012354

逻辑演算中的翻译

语义子程序

由于布尔表达式演算与算术表达式计算非常类似,可以仿照算术表达式的翻译方法,为每个产生式写出语义子程序:

在语法栈中,和语义栈中进行计算,结果还是放到T中

image-20220605140209642

举例

image-20220605140512596

语法栈 语义栈 读头
x+y>zV x入栈
E x +y>zV +入栈,语义栈中用-表示
E+ x- y>zV y入栈
E+E x-y >zV 遇到>,先进行算符运算,(+,x,y,T1)
Ea T1 >zV >入栈
Ea> T1- zV z入栈
Ea>E T1-z V 遇到V,先进行关系运算,(>,T1,z,T2)
Eb T2 V

image-20220605141457596

控制语句中翻译