编译器由分析和综合两部分组成:
分析部分(前端):把源程序分解成多个组成要素,并在这些要素之上加上语法结构,利用这个结构创建该源程序的一个中间表示;收集有关源程序的信息,并存放于符号表中。
综合部分(后端):根据中间表示和符号表中的信息构造用户期待的目标程序。
上图为一个编译器的各个步骤
1.2.1 词法分析
词法分析(扫描):读入组成源程序的字符流,并将它们组织成为有意义的词素序列。对每个词素,词法分析器产生如下形式的语法单元作为输出:<token-name, attribute-value>
token-name:是一个由语法分析步骤使用的抽象符号。
attribute-value:指向符号表中关于这个词法单元的条目。(符号表条目的信息会被语义分析和代码生成步骤使用)
e.g.
position = initial + rate * 60; //赋值语句
①词素:position,被映射成词法单元 <id, 1>,其中id是表示标识符的抽象符号,1指向符号表中position对应的条目(如名称和类型)。
②词素:=,被映射成词法单元 < = >。因为这个词法单元不需要属性值,所以省略第二个分量,也可以使用 assign 作为词法单元的名字,为了方便,选择词素本身作为抽象符号的名字。
③词素:initial,被映射成词法单元 < id,2 >。
④词素:+,被映射成词法单元 < + >。
⑤词素:rate,被映射成词法单元 < id,3 >。
⑥词素:*,被映射成词法单元 < * >。
⑦词素:60,被映射成词法单元 < 60 >。(从技术上讲,应建立形如 <number, 4> 的词法单元,后续在讨论)
分隔词素的空格被词法分析器忽略掉。
< id, 1> < = > <id, 2> < + > <id, 3> < * > < 60 >
上图为一个赋值语句的翻译。
1.2.2 语法分析
语法分析(解析):语法分析器使用词法分析器产生的各个词法单元的第一个分量来创建树形的中间表示。该中间表示给出了词法分析产生的词法单元流的语法结构。一个常用的表示方法是语法树。
1.2.3 语义分析
语义分析: 语义分析器使用语法树和符号表中的信息来检查源程序是否和语义定义的语义一致;同时也收集类型信息,并将其存放在语法树或符号表中,以便在随后的中间代码生成过程中使用。(类型检查,自动类型转换)
1.2.4 中间代码生成
在把一个源程序翻译成目标代码的过程中,一个编译器可能构造出一个或多个中间表示。这些中间表示可以有多种形式(语法树是一种中间表示形式,它们通常在语法分析和语义分析中使用;三地址代码)。在源程序的语法分析和语义分析完成之后,很多编译器生成一个明确的低级的或类机器语言的中间表示。该中间表示有两个重要的性质:①易于生成;②能够轻松地翻译为目标机器上的语言。
1.2.5 代码优化
机器无关的代码优化步骤试图改进中间代码,以便生成更好的目标代码。(更快,更短或能耗更低)。
1.2.6 代码生成
代码生成器以源程序的中间表示形式作为输入,并把它映射到目标语言