声明 该翻译来自于simviso团队,原视频地址:www.bilibili.com/video/av683…
目录
一、什么是词法分析
二、什么是语法分析
三、什么是语义分析
四、优化和代码生成
编译器有五个阶段:词法分析、语法分析、语义分析、优化和代码生成
一、什么是词法分析
我们后面将通过人类是如何对英语进行理解来类比编译器是如何理解这些的
对于程序理解的第一步,无论是编译器还是人,首先都是对单词的理解。
例如:This is a sentence
在上面的英语句子中,存在四个单词“this is a”和“sentence”
我们需要注意的是:识别分隔符(如空格,诸如句号之类的标点符号),以及大写字母等单词和符号,因为这些可以帮助我们将这组字母分成一堆你可以理解的单词
我们来看另外一组比较复杂的句子:ist his ase nte nce
对于上面的语句我们很难将他们一下子辨认出来。
词法分析的目的就是将程序代码文本按照它规定的方式进行分词,换句话说就是编译器对词的区分。
例如程序代码:if x==y then z=1;else z=2;
我们可以看到上面有一些关键字(词法单元):if、then、else;变量名称:x、y、z;常量:1、2;
标点符号,以及分隔符都是词法单元,目的是用来将程序代码分成一堆编译器可以理解的单词;
二、什么是语法分析
对于大家来说理解了单词,就会进一步理解句子的结构。
让我们来看一下这个例子:This line is a longer sentence.
语法分析的第一步是去确认每个单词在这个句子中所担任的角色,如:
This --> article line --> noun(名词) is --> verb(动词) a --> article longer --> adjective(形容词) sentence -->noun
语法分析之后的实际工作就是将这些单词组合在一起,变成更加高级的结构。
例如,在这个句子中,它包含了(subject),动词(verb)以及宾语(object)
通过上面所有的这些组成了一句完整的话。
对英文句子进行语法分析和对程序代码进行语法分析的过程是非常相似的。
现在我们回到之前的代码:if x==y then z=1;else z=2;
对它进行语法分析,简单的来看,它就是一个if-then-else语句;因此if-then-else就是我们的解析树树根。
首先是分析if判断语句,里面存着两个变量x、y,然后就是比较运算符‘==’;这些组合在一起就形成了一个关系表达式。通过对x、y进行判断就得到了一个对应的布尔值。然后通过该布尔值进入到对应的then和else中,该结构对应的语法分析树结构如下:
三、什么是语义分析
一旦我们理解了这句话的结构,下一步我们就要去尝试理解这句话写了什么内容。其实对句子进行词法解析和语法分析相对来说比较容易,但是对于句子的理解难度相对来说非常大。所以我们必须知道对于语义分析,计算机只能做少数有限的语义分析。
对于编译器来说,语义分析简单来说就是去纠正语法错误,找到语义中存在矛盾的地方。如果程序存在矛盾,编译器通常能够发现这些信息,不过编译器并不知道程序真正要做的是什么。
我们继续拿一个英语句子进行解释
Example:Jack said Jerry left his assignment at home.
在这个句子中就存在着矛盾的地方,“his assignment”中的his既可以指Jack也可以是Jerry,所以说,我们在没有更多信息的情况下,我们不知道“his”指的是谁。
更糟糕的情况:Jack said Jack left his assignment at home?
在这个里面Jack可能是一个人也可能有两个Jack,“his”可能是Jack也可能是另外一个人。
在程序中就是变量绑定的问题,例如下面这段代码。在编写代码程序的时候,就会在你定义第二个jack的时候,报错,告诉你jack已经定义了。因为在进入到语义分析的时候,打印jack的时候它就会存在两个jack,编译器不知道你到底打印的是哪个jack。
在编译器中会有严格的规范要求,去防止出现上述的变量绑定问题。
四、优化和代码生成
编译器的第四个阶段——优化,在日常英语用法中没有一个非常合适的对于参考,但它有点像编辑。事实上,这很像一个专业的编译在一定的字数限制范围内对一篇文章的长度做删减。
例如:But a little bit like editing
如果我们认为这句话太长了,可以使用两个单词来替换:But akin to editing
程序优化的目标是修改代码使之使用更少的资源。优化的目的可能是我们希望用更少的时间,使得程序运行得更快,也许我们希望它使用更少的空间,使得我们能够存储更多的数据。
例子:X=Y*0 is the same as X=0
这句话的意思就是X=Y0 等同于X=0。这个优化方式看起来好像没有什么问题。但是非常遗憾,这不是一个正确的规则。事实证明,该优化只对Interger有效。对于任意非number和0相乘都不会等于0:NAN0=NAN;
所以你进行了这个优化,你将会彻底破坏掉这个重要的算法逻辑。
编译器的最后一个阶段是代码生成,通常被称为Code Gen。Code Gen可以产生汇编代码,这是编译器最基本的功能。也就是说它可以将目标语言翻译为别的语言。