编译器编程:最基本的成分是什么?

我有兴趣编写一个非常简约的编译器。

我想写一小段软件(用C / C ++),它符合以下标准:

  • ELF格式的输出(* nix)
  • input是单个文本文件
  • 类C语法和语法
  • 没有链接器
  • 没有预处理器
  • 非常小(最大1-2 KLOC)

语言特色:

  • 本机数据类型:char,int和float
  • 数组(适用于所有本机数据类型)
  • 变量
  • 控制结构(if-else)
  • function
  • 循环(会很好)
  • 简单代数(div,add,sub,mul,布尔表达式,位移等)
  • 内联asm(用于系统调用)

谁能告诉我怎么开始? 我不知道编译器包含哪些部分(至少在某种意义上我不能直接启动)以及如何对它们进行编程。 谢谢你的想法。

首先,您需要决定是要创建编译器还是解释器。 编译器将您的代码转换为可以直接在硬件上,在解释器中运行,或者编译成另一种语言然后以某种方式解释的代码。 这两种语言都是完整的,因此它们具有相同的表达能力。 我建议您创建一个编译器,将您的代码编译成.net或Java字节码,因为它为您提供了一个非常优化的解释器以及许多标准库。

做出决定后,需要遵循一些常见步骤

  1. 语言定义首先,您必须定义语言在语法上的外观。

  2. Lexer第二步是创建代码的关键字,称为标记。 在这里,我们讨论的是非常基本的元素,如数字,加号和字符串。

  3. 解析下一步是创建一个与您的令牌列表匹配的语法。 您可以使用例如无上下文语法来定义语法。 可以使用这些语法之一来提供许多工具,并为您创建解析器。 通常,解析的标记被组织成一个解析树。 解析树是您的语法表示为可以移动的数据结构。

  4. 编译或解释最后一步是在解析树上运行一些逻辑。 创建自己的解释器的一种简单方法是创建与树中每个节点类型相关联的逻辑,并从下到上或从上到下遍历树。 如果要编译为另一种语言,可以插入如何在节点中转换代码的逻辑。

维基百科非常适合学习更多,您可能想从这里开始。

关于现实世界的阅读材料,我建议由David A Watt和Deryck F Brown编写“JAVA编程语言处理器”。 我在编译器课程中使用了那本书,通过实例学习在这个领域很棒。

有了您希望完成的所有目标,最具挑战性的要求可能是“非常小(最大1-2 KLOC)”。 我认为你的第一个要求(生成ELF输出)本身可能需要超过一千行代码。

简化问题的一种方法,至少在开始时,是用汇编语言文本生成代码,然后将其提供给现有的汇编程序( nasm将是一个不错的选择)。 汇编程序将负责生成实际的机器代码,以及构建实际可运行的可执行文件所需的所有ELF特定代码。 然后,您的工作将简化为语言分析和汇编代码生成。 当您的项目成熟到想要删除对汇编程序的依赖关系时,您可以自己重写此部分并随时将其插入。

如果我是你,我可以从一个汇编程序开始,然后在它上面构建一些部分。 最简单的“编译器”可能只使用一些非常简单的语句来使用语言:

print "hello" a = 5 print a 

并将其转换为汇编语言。 一旦你开始工作,你就可以构建一个词法分析器和解析器以及抽象语法树和代码生成器,它们是现代块结构化语言所需的大部分部分。

祝好运!

这些是绝对必要的部分:

  • 扫描仪:这会将输入文件分解为令牌
  • 解析器:这从扫描器识别的标记构造抽象语法树(AST)。
  • 代码生成:这会产生AST的输出。

你可能也想要:

  • error handling:这告诉解析器遇到意外令牌时该怎么做
  • 优化:这将使编译器能够生成更高效的机器代码

编辑:你已经设计了语言吗? 如果没有,你也会想要研究语言设计。

我不知道你希望从中得到什么,但如果它正在学习,并且看着现有的代码适合你,那么总有tcc 。

最重要的是关于编译器编写的书。 很多人会告诉你读Aho等人的“龙书”,但我读过的关于编译器的最好的书是“关于Pascal编译器的Brinch Hansen”。 我怀疑它已经绝版(亚马逊是你的朋友),但它会引导你完成使用递归下降设计和编写编译器的所有步骤,这是编译器新手理解的最简单方法。

虽然本书使用Pascal作为实现和目标语言,但所提供的课程和技术同样适用于所有其他语言。

这些示例都在Perl中,但Perl中的探索编程语言架构是一本好书(并且是免费的)。

一套非常好的免费参考资料,恕我直言,是:

整体编译器教程:让我们用Jack Crenshaw编写一个编译器( http://compilers.iecc.com/crenshaw/ )它很罗嗦,但我喜欢它。

汇编程序:NASM( nasm.us )适用于Linux和Windows / DOS,最重要的是很多doco和示例/教程。 ( FASM也不错,但文档/教程较少)

其他来源PCassembly书( http://www.drpaulcarter.com/pcasm/index.php

我正在尝试写一个LISP,所以我使用的是Lisp 1.5手册 。 您可能希望获得您正在编写的任何语言的语言规范。

至于1-2KLOC,假设您使用高级语言(如Py或Rb),如果您不是太野心勃勃,那么您应该接近。

作为初学者,我总是建议使用flex和bison作为这种工作。 您可以随时了解编写自己的扫描仪和解析器的细节,尽管它们可能会增加代码大小,至少它们将通过工具为您生成。 🙂