编译原理三——语义分析

语义分析和中间代码生成

1、概述

1、和语法分析、词法分析的同时进行进行词法检查、语法检查一样,语义分析也伴随语义检查。

  1. 动态语义检查需要生成相应的目标代码,它是在运行时进行的。
  2. 静态语义检查是在编译时完成的,主要涉及类型检查(与参与运算的操作数类型相容)、控制流检查(保证控制语句有合法的转向点)、一致性检查(如图标识符在同作用域只说明一次,case语句标号不能同等)(语义是上下文有关的,故形式化困难,目前用属性文法和语法制导翻译)

2、语法制导翻译:为每个产生式配上一个翻译子程序,并在语法分析同时执行这些子程序。

  • 自底向上语法制导翻译:(规约时调用翻译子程序,每个产生式语义子程序执行之后,某些结果必须作为产生式左部符号语义值暂时保存下来),原LR分析栈扩充一项为语义值。
  • 可以轻易画出语法树,但是语义分析和计算过程不太会

2、属性文法

1、文法符号的属性:(可以根据语法树找,注意复习

  • 继承属性 :从上向下传递,由父节点属性计算得到,由根节点到分支子结点,反映对上下文依赖的特性。(方便地表示程序上下文结构关系)
  • 综合属性 :自底向下传递,由子节点属性计算得到,传递方向与综合属性相反。

3、常见的中间语言

1、抽象语法树

  • 叶节点表示诸如常量或变量这样的运算对象,其它内部节点表示运算符
  • 语法规则中非本质部分去掉,得到抽象语法规则,举例如下。


    yfs.jpg

2、逆波兰表示法

  • 表达式的逆波兰表示:书106


    nbl.jpg
  • 程序语句的逆波兰表示:

    1. 赋值语句:x=a+b*c 逆波兰:xabc*+= (左部,表达式,=)
    2. GOTO语句:GOTO<语句标号> <语句标号>BL
    3. 条件语句:<顺序号>BR表示无条件转移到BR,BT和BF则是条件e真或假转移到顺序号。<布尔表达式e的逆波兰式><顺序号>BT
    4. 循环语句:转换为条件语句

    练习:
    pracnbl.jpg

3、 三地址代码:三地址代码是中间代码的一种抽象形式。通常有四元式、三元式和间接三元式三种表示方法。(三地址代码通常包含三个地址,两个存运算对象,一个存运算结果)

  • 四元式:(op,arg1,arg2,result),op是运算符,arg和result是指针,可以空缺,单变量只用arg1。

常用:


四元式.jpg
  • 三元式:(op,arg1,arg2)没有结果地址,三元式标号代表结果地址
  • 间接三元式:只记录不同的三元式,运算顺序用间接码表表示

举例:
三元式.jpg

4、表达式及赋值语句的翻译

  • 为了实现由表达式到四元式的翻译,需要给文法加上语义子程序,以便在规约的同时执行对应的语义子程序,语义子程序所涉及的语义变量、语义函数说明如下:
    1. 非终结符E.place表示存放E值的变量名在符号表中的入口地址或临时变量名的整数码。
    2. 语义函数newtemp(),调用后回送一个代表新临时变量的整数码,临时变量名按顺序可设为T1、T2......
    3. emit(op,arg1,arg2,result)产生四元式并填入四元式表中。
    4. 定义lookup(i.name)是审查i.name是否出现在符号表中,是返回i.name在符号表中的入口指针,否则返回NULL

一套语义翻译:
ytyyfx0.jpg

ytyyfx1.jpg
ytyyfy2.jpg

注意语义栈与规约同步,状态栈转换斜对角法


ytyyfy3.jpg

最后再进行手写演算
  • 布尔表达式的翻译
    1. 布尔表达式一般由运算符与运算对象组成,运算符为布尔运算符,(非,与,或)。运算对象也可以为布尔变量,也可为常量或关系表达式。关系表达式的运算对象为算术表达式
    2. 确定一个表达式的真假出口:
    3. 例子:
      布尔表达式四元式.jpg
    4. 自己试试:
      自己尝试.jpg
    5. 尝试理解:
      819759651.jpg

控制语句的翻译

推荐阅读更多精彩内容