我最近为了好玩读了整本龙书(编译器原理),结果留下了一个大问题。
编写编译器和解释器之间有什么不同?
对于我来说,编译器由以下组成:
- 词法分析器
- 解析器(构建语法树)
- 生成中间代码(比如3地址码)
- 进行各种疯狂的优化(如果需要的话)
- 从3地址码生成“汇编”或“本机代码”。
当然,解释器也有与编译器相同的词法分析器和解析器。
但是它在这之后做了什么呢?
它是否直接“读取”语法树并执行它?(有点像指令指针指向树中当前节点,并且执行是一次大型树遍历加上调用栈的内存管理)(如果是这样,它是如何实现的?我希望执行方式比巨大的 switch 语句要好)
它是否生成3地址码并解释执行?(如果是这样,它是如何实现的?再次强调,我希望看到比一英里长的 switch 语句更优雅的东西)
- 它是否生成真正的本机代码,将其加载到内存中并运行?(此时我想它不再是解释器,而更像 JIT 编译器)
此外,“虚拟机”这个概念在什么时候出现?编程语言中需要虚拟机用来做什么?(为了使我的无知清晰明了,对我来说,虚拟机就是 VMWare,我不知道它如何应用于编程语言/程序执行)。
可以看出,我的问题相当广泛。我主要想了解的不仅是使用哪种方法,而是先理解大体概念,然后深入了解其详细工作原理。我想要那些丑陋、原始的细节。显然,这更像是寻找需要阅读的参考资料,而不是期望你在这里回答所有这些细节。
谢谢!
丹尼尔
编辑:感谢您迄今为止提供的答案。但我意识到我的标题有误导性了。我理解编译器和解释器之间的“功能”差异。
我想知道的是如何实现解释器与编译器的区别。
我现在明白了编译器是如何实现的,问题是解释器与之不同之处。
例如,VB6显然既是编译器又是解释器。我现在理解了编译器部分。然而,我无法理解它在IDE中运行时如何让我在任意点停止程序、更改代码并使用新代码继续执行。 这只是一个微小的例子,不是我要找的答案。如下所述,我试图理解的是,在我拥有解析树后发生了什么。编译器会在“目标”语言中从中生成新代码。那么解释器会做什么呢?
谢谢您的帮助!