编译原理
  • 编译原理
  • 一些简答题
  • 绪论
    • 编译器简介
    • 程序设计语言
    • 静态与动态
    • 参数传递机制
  • 词法分析
    • 词法单元、模式、词素
    • 串和语言
    • 正则表达式
    • 状态转换图
    • 不确定有穷自动机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
  • 类型检查(Type checking)
  • 类型
  • 数组类型
  • 记录类型
  • 函数类型
  • 类型等价性
  • 类型的声明
  • 局部变量的存储布局
  • 声明序列的SDT
  • 记录和类中的字段
  • Env环境
  1. 中间代码生成

类型和声明

类型检查(Type checking)

利用一组规则来检查运算分量的类型和运算符的预期类型是否匹配。

类型信息的用途:查错、确定名字(对应的数据)所需的内存空间、计算数组元素的地址、类型转换、选择正确的运算符。

类型

基本类型:程序设计语言中的原子类型,如boolean、char、integer、float、void等,通常这些类型的运算都有对应的机器指令。

复合类型:由基本类型或其他复合类型复合而成,为语言提供更强的抽象和表达能力,如数组、结构体、函数等。

类型表达式(Type expression):表示类型的表达式,对于基本类型就是类型名字,对于复合类型是通过类型构建算子作用于类型表达式得到。

数组类型

表示同类型数据的聚合,类型构建算子array ,有两个参数:

  • 数组:表示数组的长度

  • 类型:表示数组元素的类型

如int[2][3] 对应类型表达式array(2, array(3, integer))

记录类型

表示不同类型数据的聚合(结构体、类)。类型构造算子record ,有多组字段:

  • 字段名:可用于在记录中引用该字段

  • 类型:字段对应数据的类型

记录的基本构造算子是笛卡尔积:

  • 如果s,t是类型表达式,那么笛卡尔积s x t也是类型表达式

  • 在记录类型的构造中起到组合作用,组合字段名与相应类型,组合多组字段

函数类型

类型构造算子->,接受参数类型与返回值类型,并构造出函数类型。

类型等价性

判断两个类型是否等价,这是类型检查的基础,不同的语言有不同的类型等价的定义。当语言允许为自定义类型命名时,主要有两种等价性判定方式:

  1. 名等价:类型表达式t与u等价当且仅当它们对应的类型名字相同

  2. 结构等价:对于基本类型,比较它们名字是否相同;对于复合类型,比较类型构造算子,若相同则递归比较构造算子的各参数分量。

类型的声明

处理基本类型、数组类型或记录类型的文法:

应用该文法及其对应的语法制导定义,除了得到类型表达式之外,还得进行各种类型的存储布局。

局部变量的存储布局

变量的类型可以确定变量需要的内存,即类型的宽度(该类型一个对象所需的存储单元的数量),函数的局部变量总是分配在连续的区间,因此给每个变量分配一个相对于这个区间开始处的相对地址(偏移量)。变量的类型信息保存在符号表中。

声明序列的SDT

在处理一个过程/函数时,局部变量应该放到该过程/函数对应的符号表中。这些变量的内存布局独立,相对地址从0开始,变量的放置和声明的顺序相同。

SDT的处理方法:

  • 变量offset记录当前可用的相对地址

  • 每分配一个变量,offset增加相应的值(宽度)

top.put(id.lexeme,T.type,offset) top指向当前函数的符号表,在符号表中创建条目,记录标识符的类型和偏移量。

记录和类中的字段

记录变量声明的翻译方案,约定:

  • 一个记录中各个字段的名字必须互不相同

  • 字段名的偏移量(相对地址),是相对于该记录的数据区字段而言的

记录类型使用一个专用的符号表,对其各个字段的类型和相对地址进行单独编码。

记录类型record(t) ,record是类型构造算子,t是符号表对象,保存该记录类型各个字段的信息。

Env环境

当程序中的作用域发生嵌套时,用一个栈Env辅助维护各作用域对应的符号表,栈中存储指向各符号表的指针。

  • 进入一个新作用域时,保存上一作用域(压栈)

  • 从一个作用域退出时,恢复上一作用域(出栈)

PreviousSSA(静态单赋值)Next表达式的翻译

Last updated 4 months ago

计算T的类型和宽度的SDT
实际的变量声明