编译器执行原理
词法分析器
词法分析器的作用,是“分词”,将代码“一段一段“的切割,生成计算机可识别的代码,这些代码叫做“词法单元
”。
var a = 3; // 会被解析器器识别为 var; a; =; 3
语法分析器
💡JavaScript语法分析器阶段,如果发现词法无法构造,就会提示语法错误、并结束构建语法树。
语法分析器的作用,是将词法单元
转换成AST抽象语法树
,“词法分析器”到“语法分析器”这个步骤是连续的。也就是说,“语法分析器”不需要等待“词法分析器”完成工作后在进行转换。“语法分析”的过程,就是把“词法分析”的结果生成“语法树”,且最终存储在内存中。
代码编译过程中的数据结构有两种,“语法树
”、“符号表
”。
- 语法树:程序语法的树表示,用来生成中间代码。
- 符号表:程序中用来存储所有符号的表,包括所有的字符串变量、直接量字符串、函数、类等。
语义检查器
语义检查器的作用,是负责对代码进行进一步的分析,以确保代码的逻辑正确性和一致性,例如类型匹配、参数匹配等。在强类型语言中,这种类型检查会更加严格,因为类型系统在编译期间会进行静态类型检查,而在弱类型语言(例如 JavaScript)中,类型检查通常是动态的,在运行时发生,所以JavaScript没有这个步骤。
中间码生成器
中间码生成器的作用,是将“AST抽象语法树
”转换成“中间码
” 。以下罗列中间码带来的好处👍:
- 中间码与平台架构无关,中间码可以为多种环境的目标机、目标代码服务。
- 生成中间码,可以进行与平台架构无关的代码优化,提高目标代码质量。
- 源程序映射成中间代码表示,再映射成目标代码的工作分在几个阶段进行,使编译算法加清晰。 对于中间语言,要求其不但与机器无关,而且有利于代码生成。
代码优化器
代码优化器的作用,是精简、优化AST抽象语法树
。以下罗列代码优化器步骤常见的优化点:
- 🙋♂️ 常量折叠(Constant Folding):
计算常量表达式的值,并用结果替换表达式。
- 🙋♂️ 死代码消除(Dead Code Elimination)
删除不会被执行的代码,例如无法达到的分支或者未使用的变量。
- 🙋♂️ 循环优化(Loop Optimization)
优化循环结构,例如循环展开、循环不变式外提等。
- 🙋♂️ 内联函数(Function Inlining)
将函数调用处用函数体替换,减少函数调用开销。
- 🙋♂️ 数据流分析(Data Flow Analysis)
分析数据在程序中的流动,以便进行进一步的优化。
代码生成器
代码生成器的作用,是生成可执行的目标代码,通常代码有两种,机器码
、字节码
。
- 🤖 机器码(Machine Code)
机器码是直接针对特定硬件架构的二进制指令,可以直接在该硬件上执行。生成机器码的编译器通常称为本地编译器,因为它们生成的代码可以在本地硬件上运行。
- ⚙️ 字节码(Bytecode)
机器码是一种中间形式,通常不是直接由硬件执行的。相反,它通常由一个虚拟机(如Java虚拟机)来解释或者编译成机器码。字节码的好处是它可以跨平台运行,因为它不依赖于特定的硬件架构,而是依赖于虚拟机的实现。例如,Java编译器会将Java源代码编译成字节码,然后在Java虚拟机上执行。