The Decaf Book
  • Introduction
  • 语言规范
  • Java 框架分阶段指导
    • 本章导引
    • PA1-A:语法分析器的自动构造
      • 阶段任务
      • 词法分析
      • 抽象语法树
      • 文法分析
    • PA1-B:基于 LL(1) 的语法分析器半自动构造
      • 阶段任务
      • LL(1) 文法分析
      • 错误恢复
    • PA2:语义分析
      • 阶段任务
      • 类型、符号和作用域
      • 访问者模式
      • 符号表构建
      • 类型检查
    • PA3:中间代码生成
      • 阶段任务
      • TAC 程序
      • 面向对象机制
      • 控制流的翻译
    • PA4:中间代码优化
      • 实验内容
      • 基本块
      • 数据流分析概述
      • 数据流优化概述
      • 公共表达式提取
      • 复写传播
      • 常量传播
      • 死代码消除
  • Scala 框架分阶段指导
    • 本章导引
    • PA1:语法分析器的自动构造
      • 阶段任务
      • 词法分析
      • 抽象语法树
      • 文法分析
      • 访问者模式
    • PA2:语义分析
      • 阶段任务
      • 类型、符号和作用域
      • 符号表构建
      • 类型检查
    • PA3:中间代码生成
      • 阶段任务
      • TAC 程序
      • 面向对象机制
      • 控制流的翻译
    • PA3-JVM:JVM 字节码生成
      • 阶段任务
      • JVM 字节码简介
      • 翻译过程
    • PA4:中间代码优化
      • 实验内容
      • 基本块
      • 数据流分析概述
      • 数据流优化概述
      • 公共表达式提取
      • 复写传播
      • 常量传播
      • 死代码消除
  • Rust 框架分阶段指导
    • 本章导引
    • PA1-A:语法分析器的自动构造
      • 实验内容
      • lalr1使用指导
        • 编写lexer
        • impl块的可选属性
        • 产生式和语法动作
        • 解决冲突
        • 一个完整的例子
      • 抽象语法树
      • 框架中部分实现的解释
      • 文件结构
    • PA1-B:基于 LL(1) 的语法分析器半自动构造
      • 实验内容
      • lalr1使用指导
      • 错误恢复
      • 文件结构
    • PA2:语义分析
      • 实验内容
      • 语义分析
      • 符号表
      • visitor模式
    • PA3:中间代码生成
      • 实验内容
      • 中间代码
      • 中间代码中的类型信息
      • 运行时存储布局
      • 面向对象机制
      • tacvm简述
    • PA4:中间代码优化
      • 基本块
      • 数据流分析概述
      • 数据流优化概述
      • 公共表达式提取
      • 复写传播
      • 常量传播
      • 死代码消除
    • PA5:寄存器分配
      • 实验内容
      • 图着色基本原理
      • 着色算法
      • 预着色节点
      • 干涉图节点合并
      • 调用约定
Powered by GitBook
On this page

Was this helpful?

  1. Rust 框架分阶段指导
  2. PA2:语义分析

实验内容

本阶段的内容是对pa1中生成的ast进行语义分析。

语义分析的目的是理解输入程序的含义,即弄清楚输入中所出现的每个标识符所指的内容以及明确输入中所出现的各种语句的含义,从而检查那些符合语法规定的程序可能出现的语义错误,以及提供信息以辅助中间代码生成。

对于标识符所指的内容,我们往往借助符号表来进行处理:随着语义分析过程的进行,当遇到符号定义的时候,我们需要往符号表中加入适当的记录信息;当遇到对符号的引用的时候,我们在符号表中查找这个符号的名字,并确定这个引用所指的是什么符号。如果引用一个没有定义的符号的话,我们将没法知道这个引用的具体含义,后面的翻译阶段也没法正常工作,因此需要把不合法的符号引用筛选出来。同样,如果有两个同样名字的符号在同一个作用域里面被定义,那么在引用这个名字的时候我们将不知道引用的到底是哪一个符号,因此这样的符号声明冲突也需要筛选出来。

对于语句的含义,我们需要根据语言规范中的规定对每一个语句或者表达式进行检查,看其是否合法。由于不符合语言规范的语句或者表达式所导致的执行效果是没有定义的,因此如果我们不把这样的不合法语句和表达式排除掉的话,那么在后面的翻译过程中编译器将不知道应该把它们翻译成什么。一般情况下,编译器对于语句和表达式进行的最基本的语义检查为类型检查,即检查这些语句和表达式的各个参数的数据类型是否符合规定,并且推断出它们执行结果的数据类型。

在具体实现中,我们把语义分析分为ast的两趟扫描进行:第一趟扫描的时候建立符号表的信息,并且检测符号声明冲突以及跟声明有关的符号引用问题;第二趟扫描的时候检查所有的语句以及表达式的参数的数据类型。在pa2中我们将借助ast结点的附加属性信息来进行语义分析。

为了规避rust对于可变引用的许多限制,框架中ast节点的附加属性一般都用Cell或者RefCell包裹起来。这的确不是一种很优雅的方式,另一种可行的做法是保持ast节点的不可变性,在原始的ast节点定义中不包含这些附加属性,需要添加属性的时候就创建新ast节点。这有一点函数式编程的思想,不过在rust中这样实现会不可避免地需要更大的代码量和更大的运行时开销,为了简单起见我们还是使用前一种看起来比较丑陋,但是实现起来相对容易的方法。

实验框架中已经实现了decaf语言的基本语法的语义分析,大家的任务是实现新语法的语义分析,同时也有可能需要修改既有的实现。新语法的具体语义可以参考专门的文档。如果有什么特别需要注意的地方,之后会在这里补充。

PreviousPA2:语义分析Next语义分析

Last updated 5 years ago

Was this helpful?