代码之家  ›  专栏  ›  技术社区  ›  chadmyers

构建有效的外部DSL

  •  11
  • chadmyers  · 技术社区  · 17 年前

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

    我知道有一些语言工作台正在开发中,我听说过像“讽刺”这样的东西。网。当然,还有ANTLR、Lex/Yaac等,但恐怕这些对我来说太复杂了。

    请谈谈你可能使用过或听说过的DSL构建器工具,以及你对它的帮助和缺点的印象。

    7 回复  |  直到 14 年前
        1
  •  9
  •   Nathan    17 年前

    我用Boo,Irony写过DSL。NET和一个名为Grammatica的工具包。你说解析器生成器太复杂了,但你的判断可能太草率了,事实上,一旦你克服了一个小的学习曲线,它们就很容易使用,并开辟了一个广阔的可能性世界,很容易克服这些努力。我发现学习为大多数解析器生成器编写语法所需的符号有点类似于学习正则表达式——你必须稍微弯曲一下头脑才能让它们进入,但回报是巨大的。

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

    如果你的目标DSL足够复杂,以至于你需要费力地写语法,那么这个简单的视觉工具无论如何都不会奏效,你最终还是必须学会写语法。

    不过,从长远来看,我同意内部DSL与外部DSL的观点。我在Boo中编写了一个内部DSL,必须修改我的DSL语法才能使其工作,这总是感觉像一次黑客攻击。使用反语的语法相同。NET或ANTLR同样容易实现,具有更大的灵活性。

    我有一个 blog post 讨论一些选择。这篇文章的重点是编写一个用于运行时表达式求值的DSL,但工具都是一样的。

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

        2
  •  8
  •   Muhammad Haggag    17 年前

    如果你正在考虑编写独立的DSL,那么你正在考虑构建编译器——这是不可避免的。编译器构造 基本的编程知识,其实并不像通常认为的那么难。Steve Yegge的 Righ Programmer Food 总结了了解如何很好地构建编译器的价值。

    有很多方法可以开始。我建议查看文章中提到的两篇论文: 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 ,一种与JVM及其库完美互操作的Lisp方言。我没有亲自使用过,但它看起来不错。对于Scheme,有GNU Guile ,即 licensed under LGPL 对于Common Lisp,有 ECL 同样在LGPL之下。两者都使用C接口实现互操作性,因此您几乎可以将它们嵌入到任何其他语言中。ECL在Lisp中是独一无二的,因为每个Lisp函数都是作为C函数实现的,所以如果你想的话,你可以用C编写Lisp代码(比如,在你自己的扩展方法中——你可以创建对Lisp对象进行操作的C函数,然后从Lisp调用它们)。我已经在我的一个副项目中使用ECL有一段时间了,我很喜欢它。维护人员非常积极,反应迅速。

        3
  •  4
  •   Glorfindel Doug L.    7 年前

    你真的应该去看看 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

        4
  •  2
  •   Sven Efftinge    11 年前

    Xtext 是为此而建的。

    来自网站:

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

    它涵盖了完整语言基础设施的各个方面,从 解析器、超链接器、编译器或解释器,完全达到一流水平 Eclipse IDE集成。所有这些都有很好的默认值 同时,每个方面都可以定制 您的需求。

        5
  •  1
  •   jhaukur    17 年前

    我一直在使用Irony,效果很好。具有讽刺意味的是,你可以很容易地将它包含在你将使用DSL的任何运行时中。我正在创建一个外部DSL,并将其填充到用C#编写的语义模型中,所以具有讽刺意味。然后,我使用语义模型使用StringTemplate生成代码。

        6
  •  1
  •   Adil Akhter    15 年前

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

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

    以下教程详细介绍了此langauge工作台的使用方法: http://strategoxt.org/Spoofax/Tour .

    希望它能有所帮助!

        7
  •  0
  •   Ira Baxter    11 年前

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

    看见 http://en.wikipedia.org/wiki/Program_transformation