【编译原理系列】编译及流程概述

语言分类

  • 面向机器
    • 机器语言:最基本的计算机语言
    • 汇编语言:用符号表示的指令的集合
  • 面向人类
    • 通用程序设计语言
      • 演变:过程->模块(抽象数据类型、ADT)->类
      • 共同特点:声明+操作
        • 声明:提供所操作对象的性质,生成相应的环境,一般是配置存储空间
        • 操作:确定操作的计算次序【过程头+过程体】,生成可执行的代码序列
    • 数据查询语言
    • 形式化描述语言E:E'+'E|E'*'E|id,核心部分是基于数学基础的产生式,例如:YACC

按照范型划分的程序设计语言

  • 过程式语言、面向对象语言
  • 函数语言:递归特性,如Lisp
  • 说明性、非算法式语言:浓厚的数学特征,如:LEX/YACC、SQL
  • 脚本式语言:仅是一种安排,没有复杂的逻辑关系,如:shell语言

语言之间的翻译

汇编语言->机器语言:

  • 汇编(如果是A2到M1这种叫交叉汇编)

程序设计语言->汇编语言或机器指令:

  • 编译(或解释)

高级语言之间:

  • 转换(或预编译)

逆向:

  • 反汇编、反编译

编译器与解释器

编译器

解释器:

特点

编译器:

  • 工作效率高(目标程序运行效率高),即时间快,空间省
  • 交互性与动态性差、可移植性差

解释器:

  • 工作效率低,即时间慢(但是执行时间快,总时间慢)、空间费

  • 交互性与动态性好

    可移植性好

    • 数据对象的类型可以动态改变,并允许用户对源程序进行修改,且提供较好的出错诊断,从而为用户提供了交互式的跟踪调试功能【数据库中的动态查询语句】
    • 解释器也是用某种程序语言编写的,因此,只要对解释器进行重新编译,就可使解释器执行在不同环境中,如Java虚拟机

主要区别:

  • 运行目标程序时的控制权在解释器而不在目标程序

工作过程

词法分析

输入是源程序,输出是记号流

根据词法规则识别出源程序中的各个记号;每个记号代表一个单词线性

  • 关键字/保留字
  • 标识符:即类型名、变量名、过程名、常量名等
  • 字面量
    • 数字字面量
    • 字符串字面量
  • 特殊符号
    • 运算符
    • 分隔符,", '

语法分析

  • 输入是词法器返回的记号流,输出语法树

根据语法规则识别出记号流中的结构,并构造出一颗能够正确反映该结构的语法树(一般采用二叉树)

语义分析

根据语法分析器构造的语法树,进行适当的语义处理

  • 例如:类型检查和转换等,其目的在于保证语法正确的结构在语义上也是合法的

声明性语句将相应的环境信息记录在符号表中

操作性语句提供符号表中的信息判断各操作数是否合法

中间代码生成(可选)

对语法树进行遍历,并生成可以顺序执行的中间代码序列

  • 最常用的形式是四元式(序号)(op操作符/算符, arg1左操作数, arg2右操作数, result结果),也是三地址码

  • 操作数:算子

在此之前,解释器和编译器仍然是相同的

中间代码优化(可选)

局部优化、循环优化、全局优化等;

等价变换:

  • 变换前后的指令序列完成同样的功能,但在占用的空间上和程序执行的时间上都更省、更有效

目标代码生成

不同形式:

  • 汇编语言形式(还需要再进行一次汇编)
  • 可重定位二进制代码形式【相对寻址】
  • 内存形式(Load-and-Go,编译后马上运行,运行一次就需要编译一次);

一直贯穿的操作

符号表管理

甚至要保留到程序的运行阶段

出错处理

动态错误:

  • 逻辑错误/动态语义错误,如除以0,数组下标越界等

静态错误:

  • 又分为语法错误和静态语义错误

语法错误:

  • 语言结构上的错误,如单词拼错、缺少操作数,begin和end不匹配等

静态语义错误:

  • 语言意义上的错误,如前后类型不一致,参数不匹配

工作模式

前端:

  • 语言结构和意义的分析,输出与机器无关

后端:

  • 综合;语言意义处理

中间代码:

  • 前端与后端的分界

划分有利于编译器的开发、维护与移植

扫描

每个阶段将程序完整分析一遍的工作模式称为一遍扫描

原理上希望扫描的遍数越少越好,则需要

  • 编译器具有足够大的空间
  • 语言的设计上和编译技术上提供支持
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟 返回首页