本文主要是介绍1.2 编译器的高层结构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
编译器的高层结构
编译器是一个具有非常 模块化 的高层结构。
input---->[C]---->out -->
前端:处理和输入相关部分,比方语言,语法规则约束条件。(词法分析,语法分析
后端:目标机器指令集,约束,前端语法结构怎么映射到指令集。(指令生成,指令优化
input --> [前端 ---> 后端] ---> out
抽象的多个阶段(phase)
编译器可以堪称多个阶段构成的“流水线”结构
input --> [中间语言/阶段]--> [中间语言/阶段]--->[中间语言/阶段] ...out
每个 阶段/中间语言 完成相关的一个任务,把输入翻译成另一个等价的输入。
为什么要分成多个阶段:
- 现在的高级语言对于机器来说都比较高层,如果要通过一遍,直接到达目标机器码难度会比较大一些,所以通过把这样的过程切分成不同阶段可以使得抽象一层一层向下降,逐步靠近目标机器结构。
- 任何一个编译器系统在实际当中都可能是规模庞大的复杂。如果把所有功能都写到一个模块种,从功能上来说就比较复杂,所以把它通过阶段划分,使得每一个模块相对来说容易实现和维护。
典型的编译器结构:
因为没有涉及到编译器优化,所以又叫 没有优化的编译器结构。
符号表:在整个过程中,每个模块都需要和符号表进行交互,它是存取了程序编译过程中相关的重要信息,可以对每个阶段进行支持。
更复杂的编译器结构:
动作:语法动作。
指令选择:在中间树上做操作,对每一个高层的语法结构选择合适的汇编指令来对它进行实现,是完成语法结构到汇编的一个映射
小结:
编译器由多个阶段组成,每个阶段都要处理不同的问题,在处理这些问题的过程中需要使用不同的理论、数据结构和算法、软件工程的思想等。
编译器设计中最重要的问题是 如何合理的划分组织各个阶段,使得接口清晰,编译器容易实现和维护。
示例:
源语言:加法表达式语言Sum
两种语法形式:
整型数据n
加法 e1+e2
1. 3 可以看到 3 是一个整形数据,所以结果就直接是3
2. 3+5 从高层看是加法,3 和 5 也分别是加法表达式,因为3和5都是整型数据,也满足规则1
3. 3+4+5 这里有个集合性的概念 理论上是 3+4 结合 3+4的结果和+5结合
目标机器:栈式计算机Stack
两条指令:
push n
add
栈顶
push 3 | 6 |
push 4 | 5 |
push 5 | 4 |
push 6 | 3 | 栈底
add /| x = pop
add - | y = pop| z = x + y\ push z 此时堆栈 应该 弹出 5,6 然后将 5,6 相加后压入堆栈
--- > 进行了 add 操作后 堆栈变化栈顶
| 11 |
| 4 |
| 3 | 栈底
编译器实现:
任务1: 编译器程序 1+2+3到栈式计算机上
1. 输入: 1 + 2 + 3
在前端中,进行语法分析
2. 输出: [+]2/ \[+]1 [3]/ \[1] [2]3.抽象语法树 AST , 核心作用是对这样一个运算的内部结构做一个清晰的表示代码生成:
4.stack: 使用树的后续遍历,先遍历树的左子树节点,然后遍历右子树,最后回到根,遍历根节点1.n : push n
2.[+] : add
顺序:
push 1 -> 回到 [+]1
push 2 -> 回到 [+]1
add -> 回到 [+]1 这个节点遍历完成了,生成 add 指令
push3 -> 回到 [+]2 节点
add -> 回到 [+]2 节点遍历完成 生成 add 指令
任务2:
已知:
编译器的构造和具体编译目标相关
--> 前端 --> 中间表示AST --> 后端
接口: 中间表示的语法树
前端: 负责把输入变成语法树
后端: 负责把语法树的数据结构变成目标代码
目标:
增加一个代码优化阶段:
input --> [前端] ---> [中间表示(语法树)]--->[优化]---> 语法树--->后端
代码:
https://download.csdn.net/download/Tiantangbujimo7/12351585
这篇关于1.2 编译器的高层结构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!