Post

中间代码生成

中间代码生成

声明语句的翻译

主要任务:分析所声明id的种属、类型和地址,在符号表中为id建立一条记录

  • 类型表达式:kind + type
  • 类型的宽度:从类型表达式可以知道该类型在运行时刻所需的存储单元数量
  • 所以,在编译时刻,可以使用类型的宽度为每一个名字分配一个相对地址
    • 名字的类型和相对地址信息保存在相应的符号表记录中

类型表达式

  • 基本类型表达式
    • integer、real、char、boolean、type_error、void
  • 可以为类型表达式命名,类型名也是类型表达式
  • 类型构造符作用于类型表达式可以构成新的类型表达式
    • 数组构造符array
      • int[3]的类型表达式为array(3, int)
      • int[2][3]的类型表达式为array(2, array(3, int))
    • 指针构造符pointer
      • pointer(T),表示一个指向类型T的指针的表达式
    • 笛卡尔乘积构造符x
    • 函数构造符 →
      • T1, T2, ..., Tn, R是类型表达式,则T1 x T2 x...x Tn → R是类型表达式
    • 记录构造符record
      • 若有标识符N1, N2, ..., Nn与类型表达式T1, T2, ..., Tn,则record((N1 x T1) x (N2 x T2) x...x (Nn x Tn))是一个表达式

变量声明语句的SDT

1
2
3
4
5
6
7
8
9
① P → { offset = 0 } D
② D → T id; { enter(id.lexeme, T.type, offset); offset = offset + T.width; }D
③ D → ε
④ T → B   { t =B.type; w =B.width;} C { T.type = C.type; T.width = C.width; }
⑤ T → ↑T1 { T.type = pointer(T1.type); T.width = 4; }
⑥ B → int { B.type = int; B.width = 4; }
⑦ B → real { B.type = real; B.width = 8; }
⑧ C → ε { C.type = t; C.width = w ; }
⑨ C → [num]C1 { C.type = array(num.val, C1.type); C.width = num.val * C1.width; }
  • 之所以采用综合属性来积累维度信息是因为整个类型表达式的生成是采用右结合的形式
  • 设置临时表两t和w,直接将B的type属性传递给空产生式对应的结点,以减少复制的次数
  • 变量offset是下一个可用的偏移地址

赋值语句的翻译

  • 主要任务:生成对表达式求值的三地址码

简单赋值语句的翻译

增量翻译:gen()不仅要构造出一个新的三地址指令,还要将它添加到至今为止已生成的指令序列之后,不需要code属性

数组引用的翻译

主要在寻址

控制语句的翻译

略…

This post is licensed under CC BY 4.0 by the author.