编译原理入门及编译阶段概述

特别说明

这是一个由simviso团队进行的关于编译原理入门内容分享的翻译文档,内容并不是直译,其中有一些是译者自身的思考。
因为专业视频翻译难度也比较大,咱们内部本着翻译质量,也有一系列的规范,也因这些规范,消耗的时间更多,同时咱们本身时间也是有限的,做为公益组织,当下也没什么收益,都是小伙伴天天晚上熬夜在作事情,请勿催更,望理解
视频翻译文字版权归 simviso全部,未经受权,请勿转载:
第一集:https://b23.tv/av65512165
第二集:https://b23.tv/av65673080
图片描述
参与人员名单
图片描述前端

1. 为何要学习编译器

图片描述
编译器涉及了计算机科学领域的不少方面。包括高级和低级的编程范式,上下文无关的文法定义,栈(Stack)、链表、哈希表(hash table)、图和树这些动态数据结构的应用,以及计算机内存的访问和管理方式。对于计算机专业的学生而言,可能会去开发属于他们本身的高级编程语言以及配套的编译器。好消息是了解这些是一条很好的成长捷径。经过这个文档展现了咱们即将开始的细节,若是你想的话,里面涉及的不少工具能够帮助你走的更远。程序员

这是关于编译原理入门的第一部分。如你所见,编译器涉及了计算机科学领域的不少方面。的确,这个主题所涉及的范围实在太广。以致于你们可能会产生比视频所给出的(内容)更多的疑问(译者注:即基于给定内容产生更多想法)。尽管如此,这些视频将会让你深刻了解许多常见编译器的一些概念以及功能。经过这个系列的第一部分来对各个编译阶段进行概述。编程

2. 编译阶段概述

图片描述
编译指的是将程序员用某种高级语言编写的源代码转换成目标代码,即计算机可以认识的可执行机器代码。编译是由一个叫编译器的程序完成的。最初,没有一种方式能够用来编译源代码。也就是说,新的编程语言和它的编译器一般是一块儿开发的。一个编译器的内部工做方式很大程度取决于被编译源代码的语言。同时由于程序须要被编译运行在特定类型的处理器上,因此,具体如何实现编译器还取决于目标机器的体系结构。
图片描述
因此该怎样开发一个好的编译器?编译器设计之初就是为了必须让高级语言所写的程序正确运行。并且必须检测到全部的静态错误,也就是说它应该识别全部的不符合编程语言规则的错误。不要期望编译器来捕获动态错误,这些错误只能在运行时检测到,若是没有被捕获到可能会致使程序崩溃。也不要期望编译器去发现代码逻辑上的错误。也就是说这些错误不会使程序运行时崩溃,但会致使程序输出结果有误。后端

一个编译器应该作出明确的有意义的诊断。若是程序在编译时错误就被发现,那么输出的错误信息就应该是明确的,而且精准地指出源代码错误的位置。一个好的编译器不会一遇到错误就中止处理。在一次尝试对源代码进行编译的过程当中,编译器应尽量的发现并报告更多的错误。一个好的编译器会生成最佳的机器码。这里,最佳意味着完美。虽然任何编译器都不可能生成完美的机器码,可是一个好的编译器会尽最大努力优化编译出来的机器码。为了可让机器执行的效率更高,它会寻找语句和构造方法的替代方案。编译速度必需要快。这样,程序员在敏捷开发过程当中屡次编译和测试他们的源代码的时候,彻底没必要由于一次次改变而一次次等待编译。编译器应当易于使用。许多编译器能够从命令行启动,并提供大量选项来控制与目标代码一块儿生成的调试信息量。还有一些其余编译器在集成开发环境下加入了一个内置的简单菜单选项。当尝试从IDE中运行一些新代码时,编译器甚至可能会自动启动。在各个组件之间创建一个耦合度尽量小的模块化编译器须要不少的知识储备。这种方式容许编译器的各个部分能够被多种编程语言和多种目标机器架构平台进行重用。最后,就如同好的软件同样,一个好的编译器必需要有一个详细的文档,并且易于维护。
图片描述
当咱们对一个程序进行编译的时候,会经历以下三个过程。词法分析就比如是,咱们写了一个简单的英文句子,而后将它分割成一个个的单词和标点符号。语法分析器就是用来检查这个句子是什么意思。机器码生成的这个过程就是将一句话翻译成另外一种语言。编译器生成了能被处理器所理解的0和1的机器码,但它同时也对该机器码进行了速度和空间上的优化。所以,代码生成以及优化一般被做为一个阶段来认知。从理论上而言,编译器的一个阶段会跟着下一个阶段,但你很快就知道实际并不是如此。
图片描述
例如,词法分析和语法分析是一块儿进行的。在高级编程语言编译的时候,要进行词法和语法分析。但咱们的目标机器所处架构平台是独立的,所以,词法和语法分析被称为编译器的前端操做。另外一方面,代码生成与优化仅在根据目标机器的指令集生成机器代码时使用。这个阶段在编译过程当中被称之为后端操做。
图片描述
词法分析是由编译器中的词法分析器来执行的。这一般也被称为Lexer(词法分析器)或者说scanner(扫描器)。语法分析则是由语法分析器来执行,一般也叫parser(语法分析器)。这里,程序源码将做为一个文本流来输入到词法分析器中。词法分析器将源程序的各个单词转换成词法单元流并输出。并在请求时,将词法单元流一个一个送入到语法分析器中。语法分析器会构建出用于表明源程序的抽象语法树。抽象语法树是一种动态数据结构,用来表示源程序的层级结构。当语法树构建完毕,编译器会使用它检查源代码是否听从了编程语言的语法规则。(编译时)词法分析器同时会建立一个符号表,符号表在编译过程的全部阶段都会被频繁的访问和修改。符号表包含了程序员在源代码中使用的名称的信息,例如变量和函数名。对于某些编译器,抽象语法树是源代码到机器码的惟一中间表现形式。抽象语法树是语法分析器的输出,也是编译器前端的最终输出。
图片描述
接下来抽象语法树将被直接转换为机器码。然而,有些编译器在前端作了更多的工做。在构造抽象语法树以前,编译器可能会先构建一棵简易的树。咱们称它为解析树(语法分析树),它是源程序的一种轻量表示。经过遍历抽象语法树得到的信息与符号表的信息进行组合。生成源代码的另外一种中间表示形式。解析这颗树的一系列步骤,看起来像汇编代码。三位址码是中间代码的一种表现形式。一些编译器在构建抽象语法树后会建立更低级的代码。其余的一些编译器在构建抽象语法树时会省略中间的代码。实际上,一些编译器会经过构建语法树来完成它所容许的语法检测和语义检测。但最终只会留下中间代码,低级的中间代码一样能够被优化。在独立的目标机器架构上进行优化。低级的中间代码更易生成机器码(借助目标机器所支持的指令集来生成机器码)。对于部分编译器来讲,这是编译过程的最后阶段。但有些编译器还会尝试在这上面进行改进,在接下来的视频中会对这些编译阶段所作的事情进行深刻讲解。数据结构