学习编写编译器[关闭]
Posted
技术标签:
【中文标题】学习编写编译器[关闭]【英文标题】:Learning to write a compiler [closed] 【发布时间】:2010-09-05 07:48:40 【问题描述】:首选语言:C/C++、Java 和 Ruby。
我正在寻找一些关于如何编写自己的编译器的有用书籍/教程,仅用于教育目的。我最熟悉 C/C++、Java 和 Ruby,所以我更喜欢涉及这三者之一的资源,但任何好的资源都是可以接受的。
【问题讨论】:
ANTLR 一路。下面提出的所有资源对我来说都是多余的。 ANTLR 始终是编译器设计者最好的朋友。一个 如果您的主要重点是了解编译想法的一般工作原理 - 您可以查看 SICP 是基于 Scheme (List) 的计算机程序结构化解释的缩写,但会教授一般原则。 mitpress.mit.edu/sicp 。一位在公司工作的资深人士向我推荐了这本书,并以这些作品的编译和解释为生! 一个不要脸的插件:my answer on a similar question. 我在我的博客上写了一篇关于创建编译器的文章:orangejuiceliberationfront.com/how-to-write-a-compiler 它侧重于基础知识和入门,真的。那里还有更多与编译器/代码生成/解析器/语言设计相关的文章。 【参考方案1】:资源大清单:
A Nanopass Framework for Compiler Education ¶ Advanced Compiler Design and Implementation$ An Incremental Approach to Compiler Construction ¶ ANTLR 3.x Video Tutorial Basics of Compiler Design Building a Parrot Compiler Compiler Basics Compiler Construction$ Compiler Design and Construction$ Crafting a Compiler with C$ Crafting Interpreters [C 中的编译器设计]12 ¶ Compilers: Principles, Techniques, and Tools $ — 又名 "The Dragon Book";被广泛认为是编写编译器的“书籍”。 Engineering a Compiler$ Essentials of Programming Languages Flipcode Article Archive(查找“Jan Niestadt 的“实施脚本引擎”) Game Scripting Mastery$ How to build a virtual machine from scratch in C# ¶ Implementing Functional Languages Implementing Programming Languages (with BNFC) Implementing Programming Languages using C# 4.0 Interpreter pattern(在Design Patterns $ 中描述)指定了一种评估语言句子的方法 Language Implementation Patterns: Create Your Own Domain-Specific and General Programming Languages$ Let's Build a Compiler by Jack Crenshaw — PDF¶ 版本(示例使用 Pascal,但信息普遍适用) Linkers and Loaders$(Google 图书) Lisp in Small Pieces (LiSP)$ LLVM Tutorial Modern Compiler Implementation in ML $ — 还有 Java $ 和 C $ 版本 - 被广泛认为是一本非常好的书 Object-Oriented Compiler Construction$ Parsing Techniques - A Practical Guide Project Oberon ¶ - 看第 13 章 Programming a Personal Computer$ Programing Languages: Application and Interpretation Rabbit: A Compiler for Scheme¶ Reflections on Trusting Trust — 快速指南 Roll Your Own Compiler for the .NET framework — MSDN 的快速教程 Structure and Interpretation of Computer Programs Types and Programming Languages Want to Write a Compiler? - 快速指南 Writing a Compiler in Ruby Bottom Up Compiling a Lisp — 直接编译成 x86-64传说:
¶ 链接到 PDF 文件 $ 指向印刷书籍的链接【讨论】:
我读过Let's Build a Compiler
[compilers.iecc.com/crenshaw/] 系列,写得非常好,是一个很好的起点。
我认为值得一提的是 Coursera 的编译器课程。它有很好的视频,并介绍了如何创建类似 java 的语言/简单编译器。 Coursera Compilers Link
我想尽可能保持这个答案的原创性,所以我决定在这里发布这个参考:tutorialspoint.com/compiler_design/index.htm 我喜欢这个网站的是它不涉及实际写作任何用于创建编译器的代码,但它确实将编译器分解为几个部分:阶段和阶段。它确实描述了没有任何特定语言范式的逻辑和算法设计方法,因为它表达了任意语言和字母表的符号。这是一个快速阅读,但为您提供了每个部分所需的概念。
@TheVillageIdiot 的链接已损坏(由于评论中的格式错误),这有效:compilers.iecc.com/crenshaw【参考方案2】:
我认为这是一个非常模糊的问题;只是因为所涉话题的深度。但是,编译器可以分解为两个独立的部分;上半部分和下半部分。上半部分通常采用源语言并将其转换为中间表示,下半部分负责特定平台的代码生成。
尽管如此,解决这个主题的一种简单方法(至少我们在我的编译器类中使用的方法)是在上述两个部分中构建编译器。具体来说,您只需构建上半部分就可以很好地了解整个过程。
只做上半部分就可以让您获得编写词法分析器和解析器的经验,并生成一些“代码”(我提到的中间表示)。因此,它将获取您的源程序并将其转换为另一种表示形式并进行一些优化(如果您愿意),这是编译器的核心。然后下半部分将采用该中间表示并生成在特定架构上运行程序所需的字节。例如,下半部分将采用您的中间表示并生成一个 PE 可执行文件。
我发现对这个主题特别有帮助的一些书是Compilers Principles and Techniques(或龙书,因为封面上有可爱的龙)。它有一些很棒的理论,并且绝对以一种非常容易理解的方式涵盖了上下文无关语法。此外,为了构建词法分析器和解析器,您可能会使用 *nix 工具 lex 和 yacc。有趣的是,名为“lex and yacc”的书在这部分的龙书停止的地方接了过来。
【讨论】:
【参考方案3】:我认为Modern Compiler Implementation in ML 是最好的介绍性编译器编写文本。还有一个Java version 和一个C version,考虑到您的语言背景,这两者都可能更容易访问。本书包含大量有用的基础材料(扫描和解析、语义分析、激活记录、指令选择、RISC 和 x86 原生代码生成)和各种“高级”主题(编译 OO 和函数式语言、多态性、垃圾收集、优化和单个静态分配表单)到相对较小的空间(约 500 页)。
我更喜欢 Modern Compiler Implementation 而不是 Dragon 书,因为 Modern Compiler implementation 调查的领域较少——相反,它确实涵盖了编写一个严肃、体面的编译器所需的所有主题。读完本书后,如果需要,您将准备好直接处理研究论文以获得更深入的了解。
我必须承认,我对 Niklaus Wirth 的 Compiler Construction. 非常情有独钟,它是 PDF 格式的 available online。我发现 Wirth 的编程美学很漂亮,但是有些人觉得他的风格太少了(例如,Wirth 偏爱递归下降解析器,但大多数 CS 课程侧重于解析器生成器工具;Wirth 的语言设计相当保守。)编译器构建是一个非常简洁的提炼Wirth 的基本思想,不管你喜不喜欢他的风格,我都强烈推荐阅读这本书。
【讨论】:
编译器构造 PDF ethoberon.ethz.ch/WirthPubl/CBEAll.pdf 我强烈推荐反对 C 版本的“现代编译器实现”,由于 C 的原因,它被低级细节所削弱。它完全把书弄得一团糟。 Java 1st 不太好,因为它的 OO 设计很差,Java 2nd 不再是关于 Tiger 语言的。所以我强烈推荐 ML 一:不必精通 ML 就能理解它。 ML 绝对适合这项工作。【参考方案4】:我同意龙书参考; IMO,它是编译器构造的权威指南。不过,请为一些核心理论做好准备。
如果您想要一本理论较轻的书,Game Scripting Mastery 可能更适合您。如果您是编译器理论的新手,它会提供更温和的介绍。它没有涵盖更实用的解析方法(选择非预测递归下降而不讨论 LL 或 LR 解析),而且我记得,它甚至没有讨论任何类型的优化理论。另外,它不是编译成机器码,而是编译成一个字节码,该字节码应该在你也编写的 VM 上运行。
这仍然是一本不错的读物,尤其是如果您可以在亚马逊上以便宜的价格买到它。如果您只想简单介绍一下编译器,Game Scripting Mastery 是不错的选择。如果你想在前面硬核,那么你应该满足于龙之书。
【讨论】:
Game Scripting Mastery 是一个很好的学习资源,因为当您完成后,您将拥有一个可玩、可编写脚本的 2D 冒险游戏。这使得每个练习都专注于特定目的,并保持读者的积极性。 Dragon 有点过分关注基于语法的解析。如果您不尝试使用解析器生成器解析像 C++ 之类的完全不可能的东西,但可以使用例如一种手工制作的 LL 语法,您可能想要寻找处理除语法转换和证明之外的更高百分比编译器字段的东西【参考方案5】:"Let's Build a Compiler" 很棒,但有点过时了。 (我并不是说它会降低它的有效性。)
或查看SLANG。这类似于“让我们构建一个编译器”,但它是一个更好的资源,尤其是对于初学者而言。这附带一个 pdf 教程,它采用 7 步方法教您编译器。添加 quora 链接,因为它具有指向 SLANG 的所有各种端口的链接,包括 C++、Java 和 JS,还有 python 和 java 中的解释器,最初是使用 C# 和 .NET 平台编写的。
【讨论】:
我同意这个系列有点过时,尽管它仍然有用。然而,我对它最大的抱怨是它试图直接输出到汇编语言而不是构建任何类型的解析树,这意味着(与第一篇文章中所说的相反)它对编写不是很有用口译员。【参考方案6】:如果您希望使用功能强大、级别更高的工具,而不是自己构建一切,那么查看this course 的项目和阅读资料是一个不错的选择。这是 Java 解析器引擎 ANTLR 的作者的一门语言课程。您可以从the Pragmatic Programmers 获取 PDF 格式的课程书籍。
本课程介绍了您在其他地方会看到的标准编译器编译器内容:解析、类型和类型检查、多态性、符号表和代码生成。几乎唯一没有涉及的是优化。最终的项目是compiles a subset of C 的程序。因为您使用 ANTLR 和 LLVM 之类的工具,所以在一天内编写整个编译器是可行的(我有一个存在证明,尽管我的意思是大约 24 小时)。它重在使用现代工具进行实际工程,而在理论方面则轻一些。
顺便说一句,LLVM 简直太棒了。在很多情况下,您通常可以编译为汇编,最好编译为LLVM's Intermediate Representation。它更高级别,跨平台,LLVM 非常擅长从中生成优化的程序集。
【讨论】:
第一个链接失效了。【参考方案7】:如果你时间不多,我推荐Niklaus Wirth's "Compiler Construction" (Addison-Wesley. 1996),这是一本你可以在一天内阅读的小册子,但它解释了基础知识(包括如何实现词法分析器、递归下降解析器和你自己的基于堆栈的虚拟机)。在那之后,如果你想深入了解一下,就没有其他评论者建议的关于 Dragon book 的方法了。
【讨论】:
如果时间不多,就不要写编译器了。【参考方案8】:您可能想要研究 Lex/Yacc(或 Flex/Bison,无论您想如何称呼它们)。 Flex 是一个词法分析器,它将解析和识别您语言的语义组件(“标记”),而 Bison 将用于定义每个标记被解析时会发生什么。这可以是,但绝对不限于,打印出 C 代码,用于编译为 C 的编译器,或动态运行指令。
This FAQ 应该可以帮到你,this tutorial 看起来很有用。
【讨论】:
【参考方案9】:一般来说,编译器没有五分钟的教程,因为这是一个复杂的话题,编写编译器可能需要几个月的时间。您必须自己进行搜索。
Python 和 Ruby 通常会被解释。也许您也想从口译员开始。这通常更容易。
第一步是编写正式的语言描述,即您的编程语言的语法。然后你必须将你想要根据语法编译或解释的源代码转换为抽象语法树,这是计算机理解并可以操作的源代码的内部形式。这一步通常称为解析,解析源代码的软件称为解析器。解析器通常由解析器生成器生成,该解析器生成器将形式文法转换为源代码或机器代码。对于解析的一个好的、非数学的解释,我推荐 Parsing Techniques - A Practical Guide。 Wikipedia 对解析器生成器进行了比较,您可以从中选择适合您的解析器生成器。根据您选择的解析器生成器,您会在 Internet 上找到教程,并且对于非常流行的解析器生成器(如 GNU bison),还有书籍。
为您的语言编写解析器可能非常困难,但这取决于您的语法。所以我建议保持你的语法简单(不像 C++); LISP 就是一个很好的例子。
在第二步中,抽象语法树从树结构转换为线性中间表示。经常引用 Lua 的字节码作为一个很好的例子。但中间表示实际上取决于您的语言。
如果您正在构建解释器,则只需解释中间表示。您也可以即时编译它。我推荐 LLVM 和 libjit 用于即时编译。为了使该语言可用,您还必须包含一些输入和输出函数,可能还包括一个小型标准库。
如果你要编译语言,它会更复杂。您将不得不为不同的计算机架构编写后端,并从这些后端中的中间表示生成机器代码。我推荐 LLVM 来完成这项任务。
有几本关于这个主题的书,但我不推荐任何一本用于一般用途。他们中的大多数都过于学术或过于实际。没有“在 21 天内自学编译器写作”,因此,您必须购买几本书才能很好地理解整个主题。如果你在互联网上搜索,你会看到一些在线书籍和讲义。也许你附近有一个大学图书馆,在那里你可以借到关于编译器的书籍。
如果您打算认真对待您的项目,我还建议您具备理论计算机科学和图论方面的良好背景知识。计算机科学学位也会有所帮助。
【讨论】:
++ 你说得对,知道所有这些是件好事,而且这可能是一项艰巨的工作,但我也从一些专家那里学到了如何不制作东西大不了。知道东西很好,知道什么时候不去使用它们更好,这是大多数时候。【参考方案10】:看看下面的书。作者是ANTLR的创建者。
Language Implementation Patterns: Create Your Own Domain-Specific and General Programming Languages.
【讨论】:
【参考方案11】:John Levine 的《"Linkers and Loaders"》是一本尚未推荐但非常重要的书。如果您不使用外部汇编程序,则需要一种方法来输出可以链接到最终程序中的目标文件。即使您使用的是外部汇编器,您也可能需要了解重定位以及整个程序加载过程是如何工作的以制作一个工作工具。本书收集了大量关于这个过程的随机知识,适用于各种系统,包括 Win32 和 Linux。
【讨论】:
【参考方案12】:The Dragon Book 绝对是一本“构建编译器”的书,但如果您的语言不像当前一代语言那么复杂,您可能需要查看来自Design Patterns 的解释器模式。
书中的示例设计了一种类似正则表达式的语言,并且经过深思熟虑,但正如他们在书中所说,它有助于思考过程,但实际上只对小型语言有效。但是,使用这种模式为小型语言编写解释器要比学习所有不同类型的解析器、yacc 和 lex 等要快得多......
【讨论】:
【参考方案13】:如果您愿意使用 LLVM,请查看:http://llvm.org/docs/tutorial/。它教你如何使用 LLVM 的框架从头开始编写编译器,并且不假设你对该主题有任何了解。
本教程建议您编写自己的解析器和词法分析器等,但我建议您在了解后研究一下 bison 和 flex。它们让生活变得如此轻松。
【讨论】:
但是Visual Studio的设置文档写得不好,没有例子【参考方案14】:我发现 Dragon 的书太难读了,因为它过于关注在实践中编写编译器并不真正需要的语言理论。
我会添加 Oberon 这本书,其中包含一个非常快速和简单的 Oberon 编译器 Project Oberon 的完整源代码。
【讨论】:
【参考方案15】:Fraser 和 Hanson 的 LCC 编译器 (wikipedia) (project homepage) (github.com/drh/lcc) 在他们的《可重定位的 C 编译器:设计与实现》一书中进行了描述。它非常易读,并解释了整个编译器,直至代码生成。
【讨论】:
这似乎是一个非常好的资源谢谢。【参考方案16】:我正在研究相同的概念,并发现了 Joel Pobar 的这篇很有前途的文章,
Create a Language Compiler for the .NET Framework - not sure where this has gone
Create a Language Compiler for the .NET Framework - pdf copy of the original doc
他讨论了编译器的高级概念,并着手为 .Net 框架发明了自己的语言。虽然它是针对 .Net 框架的,但许多概念应该能够被复制。文章涵盖:
-
语言定义
扫描仪
解析器(我主要感兴趣的位)
以 .Net 框架为目标
代码生成器
还有其他主题,但你得到了公正。
它面向初学者,用 C#(不完全是 Java)编写
HTH
骨头
【讨论】:
“不太Java”是什么意思? 哈哈,对不起,我的意思是它是为 .Net 编写的,本质上类似于 java。两者都是 JIT 风格。 :)【参考方案17】:我记得大约七年前我刚接触编程时问过这个问题。
当我问起时我非常小心,但令人惊讶的是,我并没有像你来到这里那样受到批评。然而,他们确实为我指明了“Dragon Book”的方向,在我看来,这是一本非常棒的书,它解释了编写编译器所需的一切(你当然必须掌握一两种语言。你知道的语言越多越好。)。
是的,很多人说读那本书很疯狂,你不会从中学到任何东西,但我完全不同意。
许多人还说编写编译器既愚蠢又毫无意义。好吧,编译器开发有用的原因有很多:
因为它很有趣。 它具有教育意义,在学习如何编写编译器时,您将学到很多关于计算机科学和其他对编写其他应用程序有用的技术。 如果没有人编写编译器,现有的语言就不会变得更好。我没有立即编写自己的编译器,但询问后我知道从哪里开始。而现在,学习了很多不同的语言,读了龙书之后,写作已经不是什么大问题了。 (我也在学习计算机工程 atm,但我所知道的大部分编程知识都是自学的。)
总之,《龙书》是一本很棒的“教程”。但在尝试编写编译器之前,请花一些时间掌握一两种语言。不过不要指望在未来十年左右成为编译器大师。
如果你想学习如何编写解析器/解释器,这本书也很好。
【讨论】:
我们在大学里用 Dragon Book 学过编译器科目,我可以保证,这是我读过的最好的书之一【参考方案18】:"...让我们构建一个编译器..."
我将在 http://compilers.iecc.com/crenshaw/ 之后获得 @sasb。暂时别再买书了。
为什么?工具和语言。
所需的语言是 Pascal,如果我没记错的话是基于 Turbo-Pascal。如果你去http://www.freepascal.org/ 并下载 Pascal 编译器,所有的例子都可以直接从页面工作~http://www.freepascal.org/download.var Free Pascal 的美妙之处在于你可以使用它几乎任何你可以关心的处理器或操作系统。
一旦你掌握了课程,然后尝试更高级的“Dragon Book” ~ http://en.wikipedia.org/wiki/Dragon_book
【讨论】:
【参考方案19】:创建编译器的一种简单方法是使用 bison 和 flex(或类似),构建树 (AST) 并在 C 中生成代码。生成 C 代码是最重要的步骤。通过生成 C 代码,您的语言将自动在所有具有 C 编译器的平台上运行。
生成 C 代码与生成 html 一样简单(只需使用 print 或等效的),而这又比编写 C 解析器或 HTML 解析器容易得多。
【讨论】:
【参考方案20】:来自comp.compilers FAQ:
Per Brinch Hansen 的“个人计算机编程” Prentice-Hall 1982 ISBN 0-13-730283-5
这本不幸的书名 解释单用户编程环境的设计和创建 对于 micros,使用一种名为 Edison 的类似 Pascal 的语言。作者提出 一步一步实现的所有源代码和解释 Edison编译器和简单的配套操作系统,全部写在 爱迪生本身(除了一个用符号写成的小支持内核 PDP 11/23 的汇编器;也可以为 IBM 订购完整的源代码 个人电脑)。
这本书最有趣的地方是:1)它能够 演示如何创建一个完整的、自包含的、自维护的、 有用的编译器和操作系统,以及 2) 有趣的讨论 第 2 章中的语言设计和规范问题以及权衡。
Per Brinch Hansen 的“Pascal 编译器上的Brinch Hansen” Prentice-Hall 1985 ISBN 0-13-083098-4
另一种理论 重语用这里是如何编写代码的书。作者提出了 编译器和 p 代码的设计、实现和完整源代码 Pascal- (Pascal "minus") 的解释器,一个 Pascal 子集,带有布尔值和 整数类型(但没有字符、实数、子范围或枚举类型), 常量和变量定义以及数组和记录类型(但没有打包, 变体、集合、指针、无名、重命名或文件类型)、表达式、 赋值语句、带有值和变量的嵌套过程定义 参数、if 语句、while 语句和 begin-end 块(但没有 函数定义、过程参数、goto 语句和标签, case 语句、repeat 语句、for 语句和 with 语句)。
编译器和解释器是用 Pascal* (Pascal "star") 编写的, Pascal 子集扩展了一些 Edison 风格的功能,用于创建 软件开发系统。 IBM PC 的 Pascal* 编译器由 作者,但很容易将本书的 Pascal 编译器移植到任何 方便的 Pascal 平台。
这本书使编译器的设计和实现看起来很容易。一世 特别喜欢作者关注质量的方式, 可靠性和测试。编译器和解释器可以很容易地使用 作为更复杂的语言或编译器项目的基础,尤其是 如果您迫于压力要快速启动并运行某些东西。
【讨论】:
【参考方案21】:您应该查看 Darius Bacon 的“ichbins”,它是针对 C 的小型 Lisp 方言的编译器,代码仅超过 6 页。与大多数玩具编译器相比,它的优势在于该语言足够完整,编译器是用它编写的。 (tarball 还包括一个解释器来引导事物。)
在我的Ur-Scheme 网页上,我发现了更多关于学习编写编译器有用的内容。
【讨论】:
【参考方案22】:Python 捆绑了一个用 Python 编写的 Python 编译器。您可以看到源代码,它包括所有阶段,从解析、抽象语法树、发出代码等。 破解它。
【讨论】:
【参考方案23】:抱歉,它是西班牙语的,但这是阿根廷一门名为“Compiladores e Intérpretes”(编译器和口译员)课程的参考书目。
课程是从形式语言理论到编译器构建,这些是你需要构建的主题,至少,一个简单的编译器:
C. 中的编译器设计 Allen I. Holub 普伦蒂斯霍尔。 1990.
编译器。 Teoría y Consrucción。 桑奇斯 Llorca, F.J., Galán Pascual, C. 编辑 Paraninfo。 1988 年。
编译器构造。 尼克劳斯·沃斯 艾迪生-韦斯利。 1996 年。
Lenguajes、Gramáticas y Autómatas。 Un enfoque practico。 佩德罗 伊萨西·维努埃拉,帕洛玛·马丁内斯 费尔南德斯,丹尼尔·博拉霍·米兰。 Addison-Wesley 伊比利亚美洲 (西班牙)。 1997 年。
编译器设计的艺术。理论与实践。 托马斯 皮特曼,詹姆斯·彼得斯。 普伦蒂斯霍尔。 1992 年。
面向对象的编译器构造。 吉姆·福尔摩斯。 Prentice Hall, 恩格尔伍德 新泽西州克里夫斯市,1995 年
编译器。概念基础。 B. Teufel, S. 施密特,T. Teufel。 艾迪生-韦斯利伊比利亚美洲。 1995 年。
自动机理论、语言和计算简介。 约翰·E·霍普克罗夫特。 Jeffref D. Ullman。 艾迪生-韦斯利。 1979 年。
正式语言简介。 György E. Révész。 麦格劳希尔。 1983 年。
解析技术。实用指南。 Dick Grune, Ceriel 雅各布斯。 印象派 los 自动售货机。 1995http://www.cs.vu.nl/~dick/PTAPG.html
Yacc:又一个编译器-编译器。 斯蒂芬 C. Johnson 计算科学 1975 年第 32 号技术报告。贝尔 实验室。新默里山 泽西岛。
Lex:词法分析器生成器。 M. E. Lesk,E. 施密特。计算科学技术 1975 年第 39 号报告。贝尔实验室。 新泽西州默里山。
lex 和 yacc。 约翰·R·莱文、托尼·梅森、道格·布朗。 O'Reilly & Associates。 1995 年。
计算理论的要素。 哈里·R·刘易斯, Christos H. Papadimitriou。 西贡达埃迪西翁。普伦蒂斯霍尔。 1998 年。
Un Algoritmo Eficiente para la Construcción del Grafo de Dependencia de Control. 萨尔瓦多诉卡瓦迪尼。 Trabajo Final de Grado para obtener el Título de Ingeniero en Computación. Facultad de Matemática Aplicada。 U.C.S.E. 2001.
【讨论】:
【参考方案24】:-
这是一个庞大的主题。不要小看这一点。并且不要低估我的观点,不要低估它。
我听说Dragon Book 是一个(?)开始的地方,以及搜索。 :) 更好地搜索,最终它将成为你的生活。
构建自己的编程语言绝对是一个很好的练习!但要知道,它最终永远不会用于任何实际目的。例外情况很少,而且非常相差甚远。
【讨论】:
如果你还没有读过龙之书。请不要推荐它。事实上,你有没有实现过编译器? 是的,顾名思义,龙之书就是一个怪物。非常深入,但仍然是一个非常好的资源。不过,我不会向初学者推荐它... @Neil:你没用谷歌搜索过我吧?哈哈。 blog.280z28.org 但不,我没看过那本书。 我目前正在阅读它(龙书),同时也在阅读 Lex/Yacc,我觉得这本书相当不错。个人。 公平地说,我以“我听到...”开头。 :) #1 和 #3 是我觉得非常重要的一点,但很少被提及。【参考方案25】:如果您想了解有关编译器(和元编译器)的更多信息,这不是一本书,而是一本技术论文和一次非常有趣的学习体验……本网站将引导您构建一个完全独立的编译器系统,该系统可以自行编译和其他语言:
Tutorial: Metacompilers Part 1
这一切都基于一篇令人惊叹的 10 页小技术论文:
Val Schorre META II:面向语法的编译器编写语言
从 1964 年的诚实到上帝。早在 1970 年,我就学会了如何构建编译器。当您终于了解编译器如何重新生成自身时,这是一个令人兴奋的时刻......
我在大学时代就认识网站作者,但我与网站无关。
【讨论】:
正如其他人所说,这是一个很大的论点,我认为寿司任务是学士的最后工作,它需要了解很多数学、计算机科学等概念。 如果您不了解这些主题,那么您不应该真正尝试构建一个严肃的编译器。但是,如果您有 2-3 年的本科计算机科学教育(编程、数据结构、汇编语言),那么 MetaII 论文将适合您。【参考方案26】:这里有很多很好的答案,所以我想我应该在列表中再添加一个:
十多年前,我有一本名为 Project Oberon 的书,其中有一些关于编译器的非常好的文字。这本书真的很突出,因为来源和解释非常实用和可读。全文(2005 年版)已以 pdf 格式提供,因此您可以立即下载。编译器将在第 12 章讨论:
http://www.ethoberon.ethz.ch/WirthPubl/ProjectOberon.pdf
尼克劳斯·沃斯,于尔格·古特克内希特
(处理没有他关于编译器的书那么广泛)
我看了几本编译器方面的书,可以秒龙书,花在这本书上的时间很值得。
【讨论】:
【参考方案27】:我也喜欢Crenshaw tutorial,因为它非常清楚地表明编译器只是另一个读取一些输入并写入一些输出的程序。
阅读。
如果您愿意,可以使用它,然后查看另一个参考资料,了解如何真正编写更大、更完整的编译器。
阅读On Trusting Trust,了解在这个领域可以做的不明显的事情。
【讨论】:
【参考方案28】:如果您有兴趣为功能语言(而不是过程语言)编写编译器,Simon Peyton-Jones 和 David Lester 的“Implementing functional languages: a tutorial”是一个很好的指南。
函数式求值工作原理的概念基础以简单但强大的函数式语言“Core”的示例为指导。此外,核心语言编译器的每个部分都用 Miranda(一种与 Haskell 非常相似的纯函数式语言)中的代码示例进行了解释。
描述了几种不同类型的编译器,但即使您只遵循所谓的 Core 模板编译器,您也会非常了解是什么使函数式编程成为现实。
【讨论】:
【参考方案29】:您可以使用 Apache 软件基金会的 BCEL。使用此工具,您可以生成类似汇编程序的代码,但它是带有 BCEL API 的 Java。您可以了解如何生成中间语言代码(在本例中为字节代码)。
简单示例
用这个函数创建一个Java类:
public String maxAsString(int a, int b)
if (a > b)
return Integer.valueOf(a).toString();
else if (a < b)
return Integer.valueOf(b).toString();
else
return "equals";
现在用这个类运行 BCELifier
BCELifier bcelifier = new BCELifier("MyClass", System.out);
bcelifier.start();
您可以在控制台上看到整个类的结果(如何构建字节码 MyClass.java)。该函数的代码是这样的:
private void createMethod_1()
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_PUBLIC, Type.STRING, new Type[] Type.INT, Type.INT , new String[] "arg0", "arg1" , "maxAsString", "MyClass", il, _cp);
il.append(InstructionFactory.createLoad(Type.INT, 1)); // Load first parameter to address 1
il.append(InstructionFactory.createLoad(Type.INT, 2)); // Load second parameter to adress 2
BranchInstruction if_icmple_2 = InstructionFactory.createBranchInstruction(Constants.IF_ICMPLE, null); // Do if condition (compare a > b)
il.append(if_icmple_2);
il.append(InstructionFactory.createLoad(Type.INT, 1)); // Load value from address 1 into the stack
il.append(_factory.createInvoke("java.lang.Integer", "valueOf", new ObjectType("java.lang.Integer"), new Type[] Type.INT , Constants.INVOKESTATIC));
il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
il.append(InstructionFactory.createReturn(Type.OBJECT));
InstructionHandle ih_13 = il.append(InstructionFactory.createLoad(Type.INT, 1));
il.append(InstructionFactory.createLoad(Type.INT, 2));
BranchInstruction if_icmpge_15 = InstructionFactory.createBranchInstruction(Constants.IF_ICMPGE, null); // Do if condition (compare a < b)
il.append(if_icmpge_15);
il.append(InstructionFactory.createLoad(Type.INT, 2));
il.append(_factory.createInvoke("java.lang.Integer", "valueOf", new ObjectType("java.lang.Integer"), new Type[] Type.INT , Constants.INVOKESTATIC));
il.append(_factory.createInvoke("java.lang.Integer", "toString", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
il.append(InstructionFactory.createReturn(Type.OBJECT));
InstructionHandle ih_26 = il.append(new PUSH(_cp, "equals")); // Return "equals" string
il.append(InstructionFactory.createReturn(Type.OBJECT));
if_icmple_2.setTarget(ih_13);
if_icmpge_15.setTarget(ih_26);
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
【讨论】:
【参考方案30】:作为一个起点,最好创建一个递归下降解析器 (RDP)(假设您想创建自己的 BASIC 风格并构建一个 BASIC 解释器)以了解如何编写编译器。 我在 Herbert Schild 的 C Power Users 第 7 章中找到了最好的信息。这一章参考了 H. Schildt 的另一本书“C The complete Reference”,他解释了如何创建计算器(一个简单的表达式解析器)。我在 eBay 上发现这两本书都很便宜。 如果您访问 www.osborne.com 或签入www.HerbSchildt.com,您可以查看该书的代码 我在他的最新书中找到了相同的代码,但用于 C#
【讨论】:
以上是关于学习编写编译器[关闭]的主要内容,如果未能解决你的问题,请参考以下文章