编译原理绪论

引言

编译原理旨在介绍编译程序构造的一般原理和基本方法。内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成,本节主要是对这门课有一个整体把握。

什么叫编译程序

编译程序(编译器),它读入用某种语言编写的 源程序,并翻译成一个与之等价的另一种语言编 写的源程序。

编译过程概述

编译程序的工作,从输入源程序开始,到输出目标程序结束,与自然语言之间的翻译有很多相似之处。

一段英文翻译成中文,需经下列步骤: I am a experienced teacher.

  • 识别出句子中的单词:词法分析
  • 分析句子的语法结构:语法分析
  • 根据句子的含义进行初步分析:语义分析及中间代码生成
  • 对译文进行修饰:代码优化
  • 写出最后的译文:目标代码生成

词法分析

计算圆柱体表面积的程序片断如下:

float r,h,s;
s = 2*3.1416 * r *(r+h);

上述源程序通过词法分析识别出如下单词符号:

  • 关键字: float
  • 标识符: rhs
  • 常数:3.14162
  • 算符: *+
  • 界符 :();=

词法分析是对构成源程序的字符串从左到右进行扫描和分解,根据语言的词法规则识别出一个一个具有独立意义的单词(也称单词符号, 简称符号)。

词法规则是单词符号的形成规则,它规定了哪样的字符串构成一个单词符号。

语法分析

语法分析的任务是在词法分析的基础上, 根据语言的语法规则单词符号串中识别出各种语法单位(如表达式、说明、语句等) ,并进行语法检查, 即检查各种语法单位在语法结构上的正确性。

语言的语法规则规定了如何从单词符号形成,语法规则是语法单位的形成规则。

具体地说,语法分析是在单词流的基础上建立一个层次结构–建立语法树。

语义分析和中间代码生成

语义分析的任务是首先对每种语法单位进行静态的语义审查,然后分析其含义,并用另一种语言形式 (比源语言更接近于目标语言的一种中间代码或直接用目标语言 ) 来描述这种语义。

它利用语法分析阶段确定的层次结构来识别表达式和语句中的操作信息及类型信息。

代码优化

代码优化的任务是对前阶段产生的中间代码进等价变换,以期获得更为高效即省时间和空间的目标代码。将$s=23.1416r*(h+r)$翻译成如下形式的四元式经局部优化后得:

(*,6.28,r,T2)
(+,h,r,T3)
(*,T2,T3,s)
(=,T4, ,s)

代码优化试图改进中间代码,以产生执行速度较快的机器代码。

t1 = c * d;
t2 = b + t1;
a = t2;

对上面中间代码进行优化处理后,产生如下的代码:

t1 = c * d;
a = b + t1;

目标代码生成

主要任务:将中间代码变换成特定机器上的绝对指令代码或可重定位的汇编指令代码。主要与硬件系统结构和指令含义有关。

代码生成会生成可重定位的机器代码或汇编代码:

Movf R2,c
Mult R2,d
Movf R1,b
Addf R2,R1
Movf a,R2

符号表管理

变量声明

int a,b;
float e,f;
char ch1,ch2;

为什么要先声明?定义了变量的类型,也就规定了变量在内存中的存放形式以及在其上所能进行的运算,解决了符号地址到存储地址上的映射。

编译器的一个基本功能是记录源程序中使用的标识符并收集与每个标识符相关的各种属性,并将它们的属性信息记载到符号表中。

符号表是一个数据结构,每个标识符在符号表中都有一条记录。

例如:

int a,b;

名字记号类型种属……
aid1(25)int简单变量
bid2(25)int简单变量

符号表接口

符号表的作用就是存放字符串或词素。当一个字符串或词素被保存时,与之相对应的记号也被保存。

符号表操作

  • Insert(s,t):将符号串s和记号t插入符号表,返回相应表项的指针
  • Lookup(s):在符号表中查找字符串s,查找成功返回相应指针,否则返回0

关键字处理

通常情况下,将关键字存在符号表中,作为符号表的初值。

当此法分析程序识别出一个标识符s后,用Lookup(s)查找符号表:如果是关键字,返回相应的记号;如果是变量名,返回记号id。

符号表实现

编译各阶段的分组

前端与后端

前端

前端包括词法分析、语法分析、语义分析以及相关的错误处理和符号表的建立。

前端依赖于源程序并在很大程序上独立于目标机器。

后端

后端主要包括代码优化、代码生成和相关错误处理。

后端的处理对象是由前端产生的结果即中间代码,并且依赖于目标机器。

前后端比较

Java语言的编译采用的是前端后端方式,也就是我们经常提到的JVM(Java虚拟机)。

  • 前端生成与平台无关的字节码
  • 后端是由与平台有关的解释器对所生成的字节码文件进行解释执行

编译次数

编译的若干阶段通常是以一遍来实现的,每遍读一次输入文件,产生一个输出文件。

错误检测与报告

在编译的各个阶段都会发现源程序中的错误,为了使编译器能继续运行以检测出源程序中更多的错误,在检测到错误后必须以合适的方式进行错误处理。