编译原理
  • 编译原理
  • 一些简答题
  • 绪论
    • 编译器简介
    • 程序设计语言
    • 静态与动态
    • 参数传递机制
  • 词法分析
    • 词法单元、模式、词素
    • 串和语言
    • 正则表达式
    • 状态转换图
    • 不确定有穷自动机NFA
    • 确定有穷自动机DFA
    • 算法:正则表达式转NFA
    • 自动机到词法分析器
  • 语法分析
    • 语法分析器
    • 上下文无关文法
    • 二义性和左递归
    • 递归下降语法分析
    • 算法:求解FIRST集和FOLLOW集
    • 算法:LL(1)
    • 自底向上语法分析
    • 移入-归约语法分析
    • 算法:LR(0)
    • 算法:SLR(1)
    • 算法:LR(1)
    • 算法:LALR
    • LR分析器和LALR分析器
  • 语法制导
    • 语法制导定义(SDD)
    • 综合属性和继承属性
    • 语法树上的SDD求值
    • 依赖图
    • L属性的SDD
    • 类型
    • SDD的应用
  • 中间代码生成
    • 三地址代码
    • SSA(静态单赋值)
    • 类型和声明
    • 表达式的翻译
    • 类型检查
    • 控制流
    • 回填
  • 运行时刻环境
    • 存储组织
    • 栈式分配
    • 栈中非局部数据的访问
    • 堆管理
    • 垃圾回收
  • 代码生成
    • 代码生成器的设计
    • 目标语言
    • 目标代码中的地址
    • 基本块和流图
    • 基本块的优化
Powered by GitBook
On this page
  • 将表达式代码的SDD
  • 数组元素的寻址
  • 数组引用的翻译
  1. 中间代码生成

表达式的翻译

Previous类型和声明Next类型检查

Last updated 4 months ago

将表达式代码的SDD

以上是将表达式翻译成三地址代码的SDD;

  • code 表示代码

  • addr 表示存放表达式结果的地址

  • new Temp() 生成临时变量

  • gen() 生成指令

为每一次计算引入一个临时变量存储计算结果。

增量式翻译方案:类似于边扫描边生成,gen 不仅构造新的三地址指令,还要将它添加到至今为止已生成的指令序列之后。不需要code 指令保存已有的代码,而是对gen 的连续调用生成一个指令序列。

数组元素的寻址

一维数组A[i] 的寻址:假设数组元素被存放在连续的存储空间中,元素从0到n-1编号,第i个元素的地址为:base + i*w

k维数组A[i1][i2]..[ik] 寻址:假设数组按行存放,首先存放A[0][i2]..[ik] ,然后存A[1][i2]...[ik] ...,那么A[i1][i2]...[ik] 的地址为:base + i1*w1 + i2*w2 + ... + ik*wk

其中base和w的值可以从符号表中找到:

数组引用的翻译

为数组引用生成代码要解决的主要问题是:数组引用的文法和地址计算相关联。假定数组编号从0开始,基于宽度来计算相对地址。

数组引用相关文法:非终结符号L生成数组名,加上一个下标表达式序列

非终结符号L的三个综合属性:

  • L.array是一个指向数组名字对应的符号表条目的指针(L.array.base为该数组的基地址)

  • L.addr指示一个临时变量,计算数组引用的偏移量

  • L.type是L生成的子数组的类型。对于任何(子)数组类型L.type,其宽度由L.type.width给出,L.type.elem给出其数组元素的类型。

以上L的代码只计算了偏移量,数组元素的存放地址应该根据偏移量进一步计算,即L的数组基址加上偏移量,使用三地址指令x = a[i] 。

L→L[E]∣id[E]L\rightarrow L[E]|id [E]L→L[E]∣id[E]
表达式翻译成三地址代码的SDD
增量式翻译方案,把code去除
例子