编译原理-绪论
编译的过程
编译的本质其实就是翻译的过程。 输入高级语言程序,输出汇编或者机器语言程序。那么编译器是如何翻译的呢?我们可以参考人工翻译的过程。
eg.翻译句子In the room, he broke a window with a hammer
这里英语就是源语言,汉语就是目标语言,怎么翻译呢?翻译的过程大体分为2步,首先分析源语言(英语)表达的含义,也就是句子的语义;接下来,根据句子的语义使用目标语言(中文)的方式说一遍。这样就完成了翻译的过程。
通过分析源语言获得句子语义的过程就叫语义分析(semantic analysis),那么语义分析又是如何进行的呢?通常是从划分句子成分入手,对于前面的例子,就是抓住核心的谓语动词,因为谓语动词知道了,句子一半的意思就知道了。找到了break(打),我们自然就想知道是谁打的,打的什么,为什么要打,怎么打的等等,这些都可以通过break的上下文来获得。通过划分句子成分,可以得到以break这个动作为核心节点的图,周围的四个节点对应着句子里的四个实体,这个图就是一种中间表示,独立于具体的语言(可以转化为任何语言)。
中间表示很重要,起到了一个桥梁的作用。
根据前面的分析,我们知道了要想进行语义分析,首先要划分句子成分(根据什么划分句子成分呢?),主语和宾语通常是名词短语,状语和补语通常是介词短语,因此,要想划分句子成分,关键是要识别句子中的各类短语,这一过程称为语法分析(syntax analysis), 那么,我们又是通过什么来识别句子中的各类短语呢?我们说是通过词性,比如说冠词加名词(a window)可以构成名词短语,一个代词本身也可以构成一个名词短语,因此要想识别句子中的各类短语,就要确定句子中各个单词的词性,而这一过程叫做词法分析(lexical analysis)。
综上所述,我们可以得到句子分析的过程,也就是首先进行词法分析,在词法分析的基础上,进行语法分析,在进行语义分析。具体一点就是首先确定各个单词的词性,或者说词类;接下来进行语法分析,识别句子中的各类短语,从而获得句子的结构;接下来进行语义分析,根据句子的结构分析出各个短语在句子中充当什么成分,从而确定各个名词性成分同核心谓语动词之间的关系。最后给出中间表示形式。
事实上,编译器也要经历类似的几个阶段,我们称为phase,
词法分析概述
词法分析是编译的第一个阶段,主要任务是从左到右逐行扫描源程序的字符,识别出各个单词,确定单词的类型,将识别出的单词转换成统一的机内表示——— token形式(<种别码,属性值>)。
单词类型 | 种别 | 种别码 | |
---|---|---|---|
1 | 关键字 | if else then program | 一词一码 |
2 | 标识符 | 变量名,数组名,记录名,过程名 | 多词一码 |
3 | 常量 | 整形,浮点型,字符型,布尔型 | 一型一码 |
4 | 运算符 | 算术(+,-,*,/,++)关系(>,<,>=,==)逻辑(&,|,~) | 一词一码或一型一码 |
5 | 界限符 | ; ( ) = | 一词一码 |
种别码可以理解为英语单词的词性或词类,那么在程序设计语言里都有哪些词类呢? 大体上分为5类
标识符是一个开放的集合,也就是说不能枚举出全部,所以所有的标识符统一成一类。分配同一个种别码,为了区分不同的标志符,token的属性值存放不同标识符的字面值。
常量也不能枚举出全部,但是对于每个常量我们都可以确定其类型,所以一型一码
语法分析概述
语法分析器的主要任务是从词法分析器输出的token序列中识别出各类短语,并构造语法分析树。语法分析树描述了句子的语法结构。
![屏幕快照 2019-06-01 下午9.18.17](/Users/mac/Nutstore Files/我的坚果云/ecnu/编译原理/新建文件夹/图/屏幕快照 2019-06-01 下午9.18.17.png)
eg.赋值语句的分析树
position = initial + rate * 60;
![屏幕快照 2019-06-01 下午9.10.29](/Users/mac/Nutstore Files/我的坚果云/ecnu/编译原理/新建文件夹/图/屏幕快照 2019-06-01 下午9.10.29.png)
eg2.变量声明语句的分析树
声明语句D是由一个类型T连接一个标识符序列再连接一个分号构成的,
![屏幕快照 2019-06-01 下午9.19.27](/Users/mac/Nutstore Files/我的坚果云/ecnu/编译原理/新建文件夹/图/屏幕快照 2019-06-01 下午9.19.27.png)
假如输入int a, b, c;根据上述规则即可判断是声明语句
语义分析概述
对于高级语言程序中的语句大体分为两类,一类是声明语句,一类是可执行语句。声明语句中声明一些数据对象和过程并分别起名字--标志服。
那么语义分析的任务就是收集标识符的属性信息
对于声明语句,语义分析主要是收集标识符的属性信息
标志服有哪些属性呢?首先是种属(kind),就是说一个标识符是简单变量还是符合变量(array,typedef),过程。其次是类型(type),也就是标志符对应的变量与过程是整型的还是实型的,字符型,布尔型,指针型。。。
另两个是存储位置和长度(在内存中的位置和大小),eg. int变量占4字节
另外,变量的值和过程的作用域也是两个重要的属性,对与过程来说,它的属性还包括参数和返回值信息
语义分析阶段分析的这些标志符的属性信息都会存放在一个称为符号表(Symbol Table)的数据结构里。每一个标志符都对应着符号表中的一条记录,每个字段对应一个属性。
符号表通常带一个字符串表,用来存放程序中用到的标志符和字符常数。这样的话,name字段就被分割成两个部分,其中一部分用来存放标志符在字符串表中的起始位置,另一部分存放长度。
语义分析的另一个任务就是语义检查
中间代码生成和编译器后端
源程序的中间表示可以有多种形式,比如说三地址码(three-address code)和语法结构树(Syntax Trees)chapter8。
三地址码由类似于汇编语言的指令序列组成,每个指令最多有3个操作数(oprand)