构建有效的外部DSL

时间:2008-09-19 13:43:11

标签: compiler-construction dsl

我有什么工具可以构建一个真正的,诚实的,善良的外部DSL。不,我不是在讨论滥用Ruby,Boo,XML或其他现有语言或语法,我的意思是一个真正的外部DSL - 我自己的语言。

我知道有一些语言工作台正在开发中,我听说过像“Irony”这样的.NET。当然,还有ANTLR,Lex / Yaac等等,但我担心这些事情太复杂了。

请谈谈您可能已经使用或听过的DSL构建工具,以及您对它的帮助及其缺点的印象。

7 个答案:

答案 0 :(得分:9)

我在Boo,Irony.NET和一个名为Grammatica的工具包中编写了DSL。你说解析器生成器过于复杂,但你的判断可能过于仓促,事实上,一旦你克服了一个小的学习曲线,它们就很容易使用,并开辟了一个可以轻易覆盖的广阔世界。努力。我发现学习为大多数解析器生成器编写语法所需的符号有点类似于学习正则表达式 - 你必须稍微弯曲一下才能让它们进入,但是奖励很重要。

我的观点是:如果你的目标语言足够简单,可以由一个愚蠢的视觉设计师处理,那么使用解析器生成器为它编写语法应该很容易。

如果你的目标DSL足够复杂,你需要打破写一个语法的汗水,那么这个愚蠢的视觉工具无论如何都不会削减芥末,你最终还是要学会写一个语法

但是,从长远来看,我同意内部与外部DSL的关系。我在Boo中编写了一个内部DSL,并且必须修改我的DSL语法以使其工作,并且它总是感觉像是一个黑客。使用Irony.NET或ANTLR的相同语法同样易于实现,具有更大的灵活性。

我有blog post讨论一些选项。这篇文章的主要内容是编写用于运行时表达式评估的DSL,但这些工具都是相同的。

我对Irony.NET的体验非常积极,并且使用它实现了一些参考语言,这是一个很好的起点。如果您的语言很简单,启动和运行绝对不复杂。 CodeProject上还有一个名为TinyParser的库 - 这个非常有趣,因为它将解析器生成为纯源代码,这意味着您的最终产品完全没有任何第三方引用。不过,我自己没有用过它。

答案 1 :(得分:8)

如果您正在考虑编写独立的DSL,那么您正在研究构建编译器 - 没有办法解决它。编译器构造必不可少的编程知识,它实际上并不像通常认为的那么困难。 Steve Yegge的Righ Programmer Food总结了知道如何很好地构建编译器的价值。

有很多方法可以开始使用。我建议查看文章中提到的2篇论文:Want to write a compiler? Just read these Two papers。第一个Let's build a compiler非常易于访问。它使用Turbo Pascal作为实现语言,但您可以使用任何其他语言轻松实现它 - 源代码非常清晰。 Pascal是一种简单的语言。

一旦你对事情的运作方式和所涉及的术语有了良好的认识,我建议钻研ANTLR之类的东西。 ANTLR有一个很好的IDE,ANTLRWorks,它带有一个解释器和一个调试器。它还可以即时生成非常好的语法可视化。我发现它在学习上非常宝贵。

ANTLR有几个很好的教程,虽然起初它们可能有点压倒性。 This one很好,虽然这是针对ANTLR 2.0的,所以你可能会遇到与更新版本不兼容的问题(目前最新的版本是3.1)。

最后,还有另一种DSL方法:Lisp方法。鉴于Lisp的无语法特性(你的代码基本上是抽象语法树),你可以用它来塑造无穷无尽的语言,只要你习惯了括号:)。

如果你采用这种方法,你想使用嵌入式Lisp。在Java下,您有Clojure,一种Lisp方言,可以与JVM及其库完美地互操作。我没有亲自使用它,但它看起来不错。对于Scheme,有GNU Guile,即licensed under LGPL。对于Common Lisp,还有ECL,也在LGPL下。两者都使用C接口实现互操作性,因此您几乎可以将它们嵌入到任何其他语言中。 ECL在Lisp中是独一无二的,因为每个Lisp函数都是作为C函数实现的,所以你可以在C语言中编写Lisp代码(比如说,在你自己的扩展方法中 - 你可以创建在Lisp对象上运行的C函数,然后从Lisp中调用它们。我一直在使用ECL作为我的一个侧面项目,我喜欢它。维护者非常积极和敏感。

答案 2 :(得分:4)

你应该看看Ragel。它是一个在常规源代码中嵌入状态机的框架。 Ragel支持C,C ++,Objective-C,D,Java和Ruby。

Ragel非常适合编写文件和协议解析器以及单步执行外部DSL。主要是因为它允许您在状态转换等上执行任何类型的代码。

使用Ragel的几个着名项目是Mongrel,一个很棒的ruby Web服务器。还有Hpricot,一个基于ruby的html解析器,有点受jQuery启发。

Ragel的另一个重要特性是如何生成基于graphviz的图表,可视化您的状态机。以下是取自Zed Shaw's article on ragel state charts的示例。

ragel state chart

答案 3 :(得分:2)

Xtext就是为此而建的。

来自网站:

  

Xtext是一个用于编程语言和开发的框架   领域特定语言。

     

它涵盖了完整语言基础架构的所有方面   解析器,链接器,编译器或解释器,以完全成为一流的   Eclipse IDE集成。它具有所有这些的良好默认值   方面,同时每个方面都可以定制   你的需求。

答案 4 :(得分:1)

我一直在使用Irony取得好成绩。关于讽刺的一个重要部分是,您可以轻松地将它包含在您将使用DSL的任何运行时中。我正在创建一个外部DSL,我将其填充到用C#编写的语义模型中,因此具有讽刺意味。然后我使用语义模型使用StringTemplate生成代码。

答案 5 :(得分:1)

如果您计划实施外部DSL,Spoofax(http://strategoxt.org/Spoofax)是一个很好的语言工作台来完成这项工作。它是一个基于解析器的文本Langauge Workbench,它利用了SDF,Stratego等多种先进技术。除了DSL实现之外,您还可以获得非常丰富的编辑器服务,例如代码完成,大纲视图,智能感知等。它已被用于构建多种语言,例如http://mobl-lang.org/。检查一下,了解所提供的支持。

Spoofax项目附带了一个开箱即用的漂亮示例DSL实现和一个java代码生成器。它可以作为开始使用这些工具的起点。

关于本langauge工作台的使用的教程详细信息:http://strategoxt.org/Spoofax/Tour

希望它有所帮助!

答案 6 :(得分:0)

对于严重的外部DSL,你无法避免解析问题; ANTLR是您所需要的最少的。您要检查的是程序转换系统,它可用于将任意DSL语法映射到Java等目标语言。

请参阅http://en.wikipedia.org/wiki/Program_transformation