Compiler construction 编译结构

Compiler construction 编译结构,compiler-construction,compilation,compiler-errors,compiler-warnings,compiler-optimization,Compiler Construction,Compilation,Compiler Errors,Compiler Warnings,Compiler Optimization,我在做编译器设计和构造。我一直在想为什么编译器中需要六个阶段。有人能指出在编译过程中有几个阶段的优点吗 简单地说,模块化。因此,当您想为不同的语言或目标机器编写编译器时,您只需更改这些模块。编写单通道编译器是绝对可能的。这可能不是一个好主意,但这是可能的,所以不,我们不“需要”六次传球 正如@transporter_room_3正确指出的那样,拥有多个过程(并且让这些过程与定义良好的接口一起工作,通常是通过让所有中间过程接收和发出相同的IR)只会使编译器更易于阅读,从而更容易设计和编写以及更改和

我在做编译器设计和构造。我一直在想为什么编译器中需要六个阶段。有人能指出在编译过程中有几个阶段的优点吗

简单地说,模块化。因此,当您想为不同的语言或目标机器编写编译器时,您只需更改这些模块。

编写单通道编译器是绝对可能的。这可能不是一个好主意,但这是可能的,所以不,我们不“需要”六次传球

正如@transporter_room_3正确指出的那样,拥有多个过程(并且让这些过程与定义良好的接口一起工作,通常是通过让所有中间过程接收和发出相同的IR)只会使编译器更易于阅读,从而更容易设计和编写以及更改和维护编译器


至于为什么只有六个——我不认为在这个数字上有任何一致意见,而且肯定有人会将每个不同的优化模块作为一个单独的过程来计算,因此,在他们自己的计算中,会高兴地经常更改过程的数量。我假设你目前正在学习编译器课程,你的老师刚刚告诉你你使用了六个阶段?那么,你的答案是:为了让学习更容易,我们通常不从一开始就学习/教授完整的概貌。我们首先查看一些限制区域,然后检查哪些边界仅用于学习,哪些边界是问题固有的。或者,在开始计数之前,你会教一个四到六岁的孩子关于集合和幺半群吗?

正如德尔南所说,你应该明确地说出你所谈论的阶段。它们不是那么标准化,以至于我们完全知道你所说的六个。编译器仍然是一个普通程序,与普通程序一样,它可能反映其作者的风格

部分答案是,因为编译是一个非常困难的问题。我曾经有一个完全相同的问题,但是在你所考虑的6阶段方案中,可能只考虑了一个阶段:解析。为什么每个人总是首先将输入流划分为标记(词法分析),然后只为标记序列提供结构(解析)?为什么人们认为这是唯一的方法?有没有一个定理说必须这样做

回想起来,答案是可能有其他方法可以做到这一点,但这一种被发现是可行的,而且因为仅仅将线性文本转换为结构化AST是一个非常困难的问题(当抽象地考虑时,没有我们积累的知识),将初始问题细分为明确的子任务会有所帮助。如果某个分部过去工作过,为什么不继续这样做呢


当然,解析本身只是将文本转换为可执行代码这一极其困难的问题中的一个子任务。我怀疑在编译器设计的每个层次上都使用了相同的经验方法。我们现在这样做的方式反映了过去尝试解决该问题的历史。

您具体谈论的是哪个阶段?有无数个稍有不同的列表。这是一个程序(一种将大任务分解成小任务的方法…只有六个?荒唐的应该比六个多得多。请看这篇文章以获得灵感:谢谢你的回答。这个特殊的问题(词法分析,然后解析)长期以来被认为远远不是最优的,甚至是不合理的。而且,不,编译是一个可笑的琐碎问题,它主要是琐碎的,因为与大多数其他编程问题不同,可以(并且很容易)将它划分为几个完全分离的阶段。编译器的复杂性被大大高估了。@PascalCuoq,我知道,无词法与传统解析有点像一场圣战,但无论如何,你必须承认,无词法近年来得到了更广泛的接受。谢谢你的回答。这并不能解释为什么会有六个。为此,您只需要两个(可能三个):前端为新语言而更改,后端为新目标而更改。(第三个是中间端,在两种情况下都是一样的。)请允许我引用安德鲁·阿佩尔的话:“如果设计者注意基本的抽象和接口,任何大型软件系统都更容易理解和实现。”“将编译器分解成这么多的部分可以重用组件。例如,要更改编译器为其生成机器语言的目标机器,只需替换帧布局和指令选择模块就足够了。要更改正在编译的源语言,只需更改经过翻译的模块。编译器可以连接到抽象语法接口处的面向语言的语法编辑器。”谢谢回答。