编译原理概述
编译器与解释器
编译器将程序员编写的源文件编译称可执行的目标程序(如.exe, .class)。像C++、Java这种高级语言(又称编译型语言)都有自己的编译器。
除了编译器之外还有一种叫做解释器,对应的就是解释性语言,最著名的例如Python,JavaScript。
各自特点
- 编译器:工作效率高,时间快、空间省;交互性与动态性差,可移植性差。
- 解释器:工作效率低,时间慢、空间费;交互性与动态性好,可移植性好。
几种程序的区别
三种级别的语言
编译程序:将源程序的语句一次全部翻译成机器语言程序(先翻译成汇编),而后再执行机器语言程序(只需翻译一次) 。
解释程序:将源程序的语句翻译一句执行一句(每次执行都要翻译),不会生成目标程序 。
汇编程序:把汇编语言源程序翻译为机器语言程序,只能翻译汇编程序。
翻译程序:把高级语言源程序翻译成机器语言程序(目标代码)的软件,编译、汇编、解释程序,可统称"翻译程序"。
任何高级语言最终都会归结到某一具体机器上的具体机器码序列,编译器便是中间的译者
⭐️编译器阶段划分
编译器的阶段划分: 词法分析、语法分析、语义分析、中间代码生成、代码优化和代码生成。
实际上编译的各个阶段都可以看成完成一定的翻译工作:词法分析是将代码文件的字符流翻译成单词流( 空格和注释将在这一阶段被滤过),语法阶段是将单词流按照语言语法规则翻译成语法树,语义分析则是在语法树的基础上按照语义规则完成语义操作( 类型检查、一致性检查、类型转换以及标识符符号表管理等工作)。
符号表管理器和出错处理贯穿编译器工作的各个阶段。
1. 词法分析
将源代码的字符流翻译成单词流,空格和注释将在这一阶段被略过。
2. ⭐🤔语法分析
将单词流按照语法规则翻译成语法树。语法分析是程序设计语言有限的规则空间和程序实现的无限功能空间映射的关键(用有限数目的规则把语言的全部可能语句描述出来,是用有穷的集合映射无穷空间)。
💡就好比英语的语法规则其实就那几种,但是却可以有无穷中应用。
这一步的关键在于尽可能快速地判断某一语句是否符合语法规则,若符合,则在完成规约成功的同时,将语法树补全,以供后续语义操作(或者语义分析和语法分析同步交替进行);若失败,则根据进行判断并提供compiler error
信息,供程序员调试。
💡你代码语法拼错了,就是在这一步检查然后给你报syntax error
的。
3. 语义分析
在语法树的基础上按照语义规则完成语义操作( 类型检查、一致性检查、类型转换以及标识符符号表管理等工作)。
4. 中间代码生成
生成一种既接近目标语言,又与具体机器无关的表示,便于代码优化与目标代码生成。
5. 中间代码优化(可选)
包括局部优化、循环优化、全局优化等;优化实际上是一个等价变换,变换前后的指令序列完成同样的功能,但可以减少占用的空间和程序执行的时间。例如删除多余运算、删除无用赋值等。
6. 目标代码生成
不同形式的目标代码包括:汇编语言形式、可重定位二进制代码形式、内存形式。
💡所以说有的编译器是直接翻译成二进制代码,有的是先翻译成汇编。
符号表管理
合理组织符号,以便于各阶段查找/填写等。
出错处理
- 动态错误:源程序中的逻辑错误,发生在程序运行的时候,也称为动态语义错误。
- 静态错误:静态错误分为语法错误和静态语义错误。
- 语法错误:有关语言结构上的错误,例如:单词拼写错误、表达式缺少操作数、begin和end不匹配。
- 静态语义错误:分析源程序时可以发现的语言意义上的错误,如加法的两个操作数一个是整形变量,另一个是数组名。