1.1 简述

我们平时所书写的源码,是无法被计算机直接执行的,因此需要一个过程,来将源码转化成机器可以执行的代码,这个转化的过程,就是编译。

综合现在所有的编程语言实现来看,并不是只有编译为机器码的语言,比如 C语言,才能称为编译型的语言。这是因为原本看上去是解释执行的语言,在其内部也大都引入的编译的环节,比如 PHP 和 Lua,它们都会将源程序编译为中间代码,称之为 Opcode,然后交由引擎或者虚拟机来执行 Opcode。因此,编译主要是强调的源码转化的过程,笼统地将语言一分为二为编译型和解释型、在当下显得有些不严谨了。

编译的步骤可以被大致简单地划分为:

  1. 词法分析

  2. 语法分析

  3. 语义分析

  4. 生成中间代码

  5. 生成目标代码

词法分析「Lexical Analysis」通过词法分析器「Lexer」来完成。词法分析器的作用就是扫描字符串,并输出作为语法单元的词素「Token」,因此它也被称为扫描器「Scanner」。

语法分析「Syntax Analysis」通过语法分析器「Parser」来完成。语法分析器的作用就是根据给定的语法「Grammar」来对词素进行分析,生成抽象语法树「AST, Abstract Syntax Tree」,抽象语法树用来描述程序的结构。

语义分析「Semantic Analysis」用来保证代码中的语义规则的完整性。比如类型检查「Type Checking」。语义分析过程中还会生成符号表「Symbol Table」并生成中间代码「Intermediate Code」。中间代码的作用就是进一步将词法分析的结果进行完善,方便接下来在生成目标代码时的工作。

之所以将编译的步骤进行这样的划分,是希望简化编译器的结构,加快编译的过程。并不是对所有语言而且,上述的环节都是必须的,比如语义分析,可以移到程序运行期间来完成。在 JavaScript 中,当我们引用一个未定义的变量时,会在运行阶段进行报错「ReferenceError」,这也是由于 JavaScript 的动态性,无法在编译环节发现这个错误。

我们在接下来的章节中,都会尽量地将一些特定中文词汇所对应的英文列出来,方便大家使用搜索引擎来进一步深入了解它们。

Last updated