编译原理 笔记 4

静态语义分析与中间代码生成

静态语义分析

本章可以对应实验中的:namertyper

静态语义检查指在编译期间所进行的语义检查,包括但不限于:

  • 静态类型检查
  • 符号的作用域分析
  • 控制流检查
  • 唯一性检查
  • 符号的上下文相关性检查

类型检查

验证语言结构是否匹配上下文所期望的类型,实现某个类型系统,分为静态和动态两大类,

类型系统的严格定义较为复杂,在此不做赘述,可以简单理解为C语言等强类型语言中类型定义的部分

我们可以借助翻译模式来设计类型检查程序,将类型表达式作为属性值赋给程序的各个部分(如实验中的Expression基类所拥有的type成员),利用类型系统的给出的形式化定义来设计相应的翻译模式

借助翻译模式描述类型检查算法举例
借助翻译模式描述类型检查算法举例

当然,如果语法上有一些修改,那么相应的翻译模式也需要进行修改,例如如果规定breakcontinue只能出现在循环体内,则需要添加一个继承属性用来记录当前语句是在在循环内

作用域分析

  • 静态作用域:通过符号表来实现
  • 动态作用域:通过运行时活动记录实现,下一讲会详细介绍

中间代码生成

本章可以对应实验中的:tacgen及其相关部分

中间代码的作用是:

  • 对源语言和目标语言进行语义上的过渡
  • 有利于重定向和机器无关优化

在实验中,一共有AST和TAC两种中间代码,AST由yacc库生成,TAC由tacgen包生成

详细的利用翻译模式重写python的结果参考pdf

  • 对于数组类型,在处理的过程中通常会将其有关的信息记录在一些单元中,称之为数组的内情向量,例如数组的维度、每一维的大小等等
  • 对于布尔表达式,我们可以直接使用bool值进行计算,也可以通过转移到程序中的位置来表示表达式的求值结果
    ,也即E = (a < b) or ((c < d) and (e < f))类似:
1
2
3
4
5
6
7
8
    if (a < b) goto E.true
goto label1
label1:
if (c < d) goto label2
goto E.false
label2:
if (e < f) goto E.true
goto E.false
利用控制流对布尔表达式进行短路翻译
利用控制流对布尔表达式进行短路翻译

同理,我们可以将tacgen中生成条件语句的代码也写成类似的形式,详细写法参考ppt

拉链与代码回填

显然,上面的翻译模式是L-翻译模式,那如果我们希望使用S-翻译模式甚至S-属性文法是否可以做到呢

我们定义真链与假链,分别代表当布尔表达式为真/假时,需要跳转到的标号,这样我们在处理布尔表达式的时候只需要维护着两条链

S-翻译模式的bool表达式
S-翻译模式的bool表达式

通过这两条链,我们可以将条件语句、循环语句等写成S-翻译模式,如:

S-翻译模式的if条件语句
S-翻译模式的if条件语句

但是在上述的布尔表达式中,我们可以看出其实生成的goto语句是不完整的,这是因为我们在利用综合属性处理布尔表达式的时候,我们没有办法得知当这个式子为真/假的时候究竟要跳到哪里,也即我们不知道E.trueE.false所代表的具体标号,而这个过程需要通过backpatch(p, i)函数完成,这个函数会将链p中每一条跳转语句的目的标号置为i

我认为,这个通常用于处理布尔表达式用于跳转的情况,例如if(a) {} else {},但是这个正好是布尔表达式最常用的情况