在C#中实现编译器的最有趣和最有前途的方法是什么?

时间:2011-11-09 22:47:36

标签: .net reflection.emit codedom mono.cecil roslyn

我刚刚完成毕业项目,应该持续6个月。 该项目的目标是为一种脚本语言实现.Net编译器。我将编译器构造作为课程的主题,并且知道如何实现编译器的基本步骤,但我们使用Bison和简单的编译器和GCC作为后端,因此我对实现编译器知之甚少在.Net平台上。

在对这个主题进行了一些研究后,我发现了以下代码生成的替代解决方案(我不是在谈论编译器的其他重要部分,比如解析器 - 它超出了范围):

  1. 使用Reflection.Emit直接生成代码。
  2. 对Reflection.Emit使用Common Compiler Interface抽象来实现某些代码生成的自动化。
  3. 在运行时使用CodeDOM进行C#和VB编译。
  4. 有一种新兴的C#“编译器即服务”称为Roslyn,现在可作为CTP使用。
  5. DLR提供对动态代码生成的支持,并具有一些通过表达式树等生成运行时代码的接口。
  6. Mono附带Mono.Cecil库,似乎也有一些代码生成功能。
  7. 我的项目的主要目标是深入研究.Net的内容,学习编译器构建并为我的工作取得好成绩。第二个目标是提出一个编译器实现,以后可以在许可的开源许可下向社区开放。

    那么,这里最有趣,最具教育性,最有趣和最有希望的方法是什么呢?如果我有更多的时间,我肯定会尝试所有这些,但我需要在6个月内提交我的工作以获得积极的成绩......

    提前谢谢你, 亚历山大。

3 个答案:

答案 0 :(得分:5)

如果您想要更简单的方法并且您的语言可以合理地翻译成C#,我建议您生成C#代码(或类似代码)并进行编译。罗斯林可能是最好的。显然,CCI也可以使用CCI Code来做到这一点,但我从未使用过它。我不推荐CodeDOM,因为it doesn't support features like static classes or extension methods

如果您想要更多控制,或者想要进入低级别,可以使用Reflection.Emit直接生成CIL。但它会(更多)更多的工作,特别是如果你不熟悉CIL。我认为Cecil可以以相同的方式使用,但它的目的是用于其他东西,我认为它没有提供任何优于Reflection.Emit的优势。

DLR的全称是动态语言。它使用的Expression可用于代码生成,但我认为它们最适合在运行时生成相对简单的方法。当然,如果您的语言是动态的,DLR本身就非常有用。

答案 1 :(得分:2)

Boo是一种针对CLI的语言/编译器。它似乎是开源的,所以你可以研究它们是如何实现它的。

答案 2 :(得分:2)

当我编写编译器时,我会写汇编语言(即汇编语言源代码),然后我通过系统的汇编程序运行。这样我就可以很容易地看到我正在产生什么。阅读mov ax, bx(x86汇编)比解码HEX操作码更容易。

如果我不允许在最终产品中使用汇编程序,我使用汇编输出开发了编译器,然后一旦我完成所有工作,我就制作了二进制输出路径。美丽是,我必须改变的是实际的字节输出(操作码和二进制值而不是文本)。

我建议为你的项目做类似的事情。最初开发它以输出可以用ILASM组装的MSIL。这样,您可以通过读取生成的代码轻松验证代码生成器的输出。一旦您确信代码生成器正在运行,请添加将使用Reflection.Emit或Common Compiler Infrastructure的输出选项。