这是我的意见(和猜测),如果不了解本科(高等教育)计算机科学课程中通常涵盖的数据结构,编写编译器将会很困难。这并不意味着你不能编写,但你需要了解基本的数据结构,如链表和树。
与其编写一个完整或符合标准的C语言编译器(至少在一开始),我建议您将自己限制在语言的基本子集上,例如常见运算符、仅支持整数以及基本函数和指针。其中一个经典的例子是Ron Cain的
Small-C,它因在我认为的1980年代写在
Dr. Dobbs Journal上的一系列文章而广受欢迎。他们发布了一个
CD,其中包括James Hendrix的绝版书籍
A Small-C Compiler。
我建议您遵循Crenshaw的教程,但将其编写为类似C的语言编译器,并选择任何CPU目标(Crenshaw的目标是Motorola 68000 CPU)。为了做到这一点,您将需要了解您想要运行已编译程序的目标的基本汇编语言。这可能包括模拟器,例如用于68000或MIPS的模拟器,它们的汇编指令集比Intel x86(16/32位)的古老CISC指令集更好。
有许多潜在的书籍可用作学习编译器/翻译器理论(和实践)的起点。阅读
comp.compilers FAQ以及各种在线书店的评论。大多数入门书籍都是为大二到大四的本科计算机科学课程编写的教科书,所以如果没有计算机科学背景,阅读起来可能会比较困难。一本比
“The Dragon Book”更入门,但阅读起来更容易的旧书是Thomas Parsons的
Introduction to Compiler Construction。它比较老,因此您应该能够以合理的价格从您选择的在线书店中找到二手副本。
所以我建议,尝试从Jack Crenshaw的Let's Build a Compiler教程开始,按照他的示例编写自己的编译器,并构建一个简单的编译器的基础知识。一旦你做到了这一点,你就可以更好地决定从那个点开始往哪里走。
添加:
关于引导过程。由于现有的C编译器是免费提供的,您不需要担心引导问题。使用独立的现有工具(GCC、Visual C++ Express、Mingw / djgpp、tcc)编写编译器,您可以在后期担心自我编译项目。我对这个问题的一部分感到惊讶,直到我意识到你是通过阅读Ken Thomas的ACM Turing奖演讲
Reflections on Trusting Trust而被带到编写自己的编译器的想法中,其中涉及了编译器引导过程。这是一个高级话题,并且也非常麻烦。即使在旧的Unix系统(64位Alpha上的Digital OSF/1)下引导GCC C编译器,其中包括C编译器,也是一个缓慢而耗时,容易出错的过程。
另一个问题是像Yacc这样的编译器工具实际上是做什么的。Yacc(或GNU的Bison)是一种旨在使编写编译器(或翻译器)解析器更容易的工具。基于您输入到yacc的目标语言的正式语法,它会生成一个解析器,这是编译器整体设计的一部分。接下来是Lex(或GNU的flex),用于生成词法分析器或扫描器,通常与由yacc生成的解析器结合使用,形成编译器前端的框架。这些工具使得编写前端比自己编写词法分析器和解析器要容易得多。Crenshaw的教程没有使用这些工具,您也不需要使用它们,许多编译器编写者并不总是使用它们。当然,Crenshaw承认教程的解析器非常基础。
Crenshaw的教程还跳过了生成AST(抽象语法树),这简化了但也限制了教程编译器。它缺乏大部分甚至所有的优化,并且与特定的编程语言和编译器“后端”发出的特定汇编语言非常相关。通常,AST是中间件,其中可以执行一些优化,并且在设计上有助于解耦编译器前端和后端。对于没有计算机科学背景的初学者,我建议您不要担心第一个编译器(或至少其第一个版本)没有AST。我认为保持它小而简单将有助于您完成编写编译器的第一个版本,然后您可以从那里决定如何继续。