编译原理-第二章 一个简单的语法指导编译器-2.8 生成中间代码

Posted 方知有

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译原理-第二章 一个简单的语法指导编译器-2.8 生成中间代码相关的知识,希望对你有一定的参考价值。

生成中间代码:

  • 两种中间表示形式:
    • 树形结构:语法分析树、抽象语法树
      • 抽象语法树的构造:
        • 可以为任意的构造创建抽象语法树,每个构造用一个结点表示,其子结点代表此构造中具有语义含义的组成部分
        • 在语法分析过程中,将创建抽象语法树的结点来表示有意义的程序构造,随着分析的进行,信息以与结点相关的属性的形式被添加到这些结点上
        • 例:
          • 树节点:类Node
          • 子类:expr(代表各种表达式)、stmt(代表各种语句)
          • 语句的语法树:
            • 一个叶子结点null表示一个空语句序列
            • 运算符seq表示一个语句序列
    • 线性结构:三地址代码
      • 三地址代码:由一个基本程序步骤(如将两个值相加)组成的序列,无层次化的结构,
        • 组成:由x = y op z形式的指令组成的序列,x、y和z可以是名字,常量或由编译器生成的临时量,而op表示一个运算符
        • 语句的翻译:
          • 通过跳转指令实现语句内部的控制流,就可以将语句转换成为三地址代码
          • 使用一些跳转指令在语句的各个组成部分对应的代码之间进行跳转
          • 例:
            • 对 if expr then stmt1 的翻译:
              • 跳转指令:if False x goto after
              • 类if是类stmt的一个子类,stmt的每一个子类都有一个构造函数及一个为此类语句生成三地址代码的函数gen
              •  构造函数if构建了if语句的语法树特点,有两个参数,一个表达式结点x和一个语法树结点y,分别被存放在属性E和S中
              • 同时,构造函数调用了函数newlable()给属性after赋予一个唯一的新标号
              • 一旦源程序的整个抽象语法树被创建完毕,函数gen在此抽象语法树的根结点处被调用
        • 表达式的翻译:
          • Access(y,z)表示数组操作:y数组名,z数组下标
          • 例:
          • 改进:
            • 优化阶段减少拷贝指令的数目
            • 充分考虑上下文的情况
        • 作用:优化代码,可以将组成程序很长的三地址语句序列分解为基本块,“基本块”就是一个总是逐个顺序执行的语句序列,执行时不会出现分支跳转
  • 静态检查:
    • 作用:编译器前端会检查源程序是否遵循源语言的语法和语义规则,确保一些特定类型的程序错误,包括类型不匹配,能在编译过程中被检测并报告
    • 组成:
      • 语法检查:语法要求比文法中的要求多,它们并不包括在用于语法分析的文法中
      • 类型检查:
        • 确保一个构造的类型符合其上下文对它的期望
        • 一种语言的类型规则确保一个运算符或函数被应用到类型和数量都正确的运算分量中
        • 类型检查规则按照抽象语法中运算符/运算分量的结构进行描述

 

参考——《编译原理(第二版)》

以上是关于编译原理-第二章 一个简单的语法指导编译器-2.8 生成中间代码的主要内容,如果未能解决你的问题,请参考以下文章

编译原理-第二章 一个简单的语法指导编译器-2.4 语法制导翻译

编译原理-第二章 一个简单的语法指导编译器-2.2 词法分析

三万五千字长文!让你懂透编译原理——第六章 属性文法和语法制导翻译

编译原理实战入门:用 JavaScript 写一个简单的四则运算编译器语法分析

编译原理系列 实验二自上而下语法分析

编译原理系列 实验二自上而下语法分析