如何启动一个简单的(也许是最简单的)C编译器?

41
我看到了这篇文章:使用 Turbo Pascal 编写编译器
我很好奇是否有任何教程或参考资料可以解释如何创建一个简单的 C 编译器。如果能让它理解算术运算,就足够了。在阅读 Ken Thompson 的一篇文章后,我变得非常好奇。编写能够理解自己的东西似乎很令人兴奋。
为什么我要提出这个问题而不是问 Google?我试过 Google,但 Turbo Pascal 那个链接是第一个显示的。其他的链接似乎与此无关,再加上我不是计算机科学专业的学生(所以我还需要学习像 yacc 这样的工具都是做什么用的),我希望通过实践来学习,并希望有更多经验的人比 Google 更擅长这些事情。我想阅读一些像我上面列出的那篇文章一样的文章,至少强调构建简单的 C 编译器的引导阶段。
此外,我不知道最好的学习方式。我应该用 C 或其他语言开始构建 C 编译器?我应该编写 C 编译器还是其他语言的编译器?我觉得这样的问题最好在我有了一些探索方向后再回答。有什么建议吗?
任何建议?

尝试使用初学者标志创建C(甚至是子集)编译器有点令人惊讶。您应该先尝试一些更简单的东西。 - Phong
3
编写自己的编译器可以非常有趣。但最好先考虑获得计算机科学学位,这样才有足够的武器来战胜困难。 - Hans Passant
经典编译器参考问题在https://dev59.com/x3VD5IYBdhLWcg3wXaed。顺便说一句 - 作为第一个入门的引子,我是Crenshaw编译器的忠实粉丝。将Pascal翻译成C并不困难,所以请放心操作。不过,如果您想坚持编译器,很快就需要更完整的参考资料了。 - dmckee --- ex-moderator kitten
另外请参见我的SmallerC,它与Small C不同,但精神上类似。 - Alexey Frunze
@Legend 这是Imagist答案的一部分。解析器和编译器是两个不同的问题。例如,我可能会用C语言编写一个编译器,但我永远不会用C语言编写一个解析器(我会使用解析器生成器)。对于非常简单的解析器,速度不是很重要的情况下,我可能会在Perl或Python中手动编写解析器,因为它们具有良好的文本处理功能。 - user3095977
显示剩余4条评论
12个回答

3
如果您想获得一次令人惊叹的体验,学习如何编写自己的编译器,那么您需要阅读这篇来自1964年的论文。由Val Schorre撰写的META II a syntax-oriented compiler writing language
在10页纸中,它告诉您如何编写编译器,如何编写元编译器,提供了一个虚拟元编译器指令集以及一个使用元编译器构建的示例编译器。
我在60年代后期就是通过这篇论文学会了如何编写编译器,并使用这些想法为几台小型计算机和微处理器构建了类似于C语言的语言。
如果这篇论文本身太难(其实不是!),那么在线教程将引导您完成整个过程。
如果因为您不是ACM会员而从原始链接获取论文感到困难,那么您会发现该教程包含所有细节。(依我之见,对于这个价格,这篇论文本身就非常值得一读。) 只有10页纸!

原始文章(Schorre)不是在ACM的付费墙后面吗?如果是,请注意。我碰巧是ACM会员,但并非所有人都是。 - mctylr
我不确定我是否可以在这里发布链接,但我相信通过Google学术可以找到替代版本...非常感谢Ira Baxter。 - Legend
一个指向(公开的)ACM Queue文章的链接,该文章介绍了如何使用Python遵循META II论文。META II: 数字写字室中的数字羊皮纸,作者是Dave Long(2015年1月,第13卷,第1期)。 - mctylr
@mctylr:他关于MetaII的文章比MetaII论文本身还长 :-} - Ira Baxter

2
我不建议用C语言来实现编译器,也不建议使用任何编译器生成器或解析器生成器。C是一门非常棘手的语言,最好自己创造一种语言。它可以有点像C(例如,如果要表示函数体,请使用花括号,使用相同的类型名称,这样您就不必记住您称呼的每个东西)。
制作编译器和解析器的工具非常好,但存在一个问题,那就是它们真正只是简写符号。如果您不知道如何长手编写编译器,则简写将会看起来晦涩难懂,限制性等等。因此,首先编写自己的简单编译器,然后再从那里继续。我还建议您不要开始生成实际的机器代码,除非您吃喝睡汇编语言。使用VM创建自己的字节码解释器。
至于您应该使用哪种语言来创建第一个编译器:实际上并不重要,只要语言相对完整即可。您将从输入文本中读取数据,构建数据结构并写出二进制数据。因此,如果某种语言在任何方面都使这些事情变得更容易,那么这是它的优点。选择您熟悉的语言,这样您就可以专注于创建编译器,而不是学习语言。我通常使用面向对象的语言,这使得语法树更容易编写,如果您熟悉函数式语言,则可能也适用。
我已经在博客中写了很多关于编程语言的内容,因此您可能会在这里找到一些有用的帖子:http://orangejuiceliberationfront.com/category/language-design/ 特别是,http://orangejuiceliberationfront.com/how-to-write-a-compiler/ 是关于解析常见构造并从中生成有用内容的入门指南,以及 http://orangejuiceliberationfront.com/generating-machine-code-at-runtime/,它讲述了实际吐出执行操作的Intel指令。
关于编译器的引导:您可能无法从一开始就完成这项工作。创建编译器需要相当多的工作。因此,编写引导编译器不仅涉及编写编译器(在其他语言中),还需要使用自身编写编译器的第二个版本。这是两倍的工作量,加上需要对现有编译器和引导新编译器进行调试,直到一切正常。也许不是两倍的工作量,但是仍然需要更多的工作。我会先尝试轻松的成功,然后再从那里继续。
无论如何,祝您玩得开心!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接