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

建立有效的外部DSL

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

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

    我知道有一些语言工作台正在开发中,我听说过类似.NET的“讽刺”之类的事情。当然,还有Antlr,Lex/Yaac等等,但恐怕这些对我来说太复杂了。

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

    7 回复  |  直到 5 年前
        1
  •  9
  •   Nathan    16 年前

    我已经在boo、rainty.net和一个名为Grammatica的工具包中编写了DSL。你说解析器生成器太复杂了,但是你的判断可能太仓促了,事实上,一旦你通过一个小的学习曲线,它们就很容易被使用,并且打开了一个巨大的可能性世界,很容易覆盖你的工作。我发现学习为大多数解析器生成器编写语法所需的符号有点类似于学习正则表达式——您必须稍微弯曲一下头脑,让它们进入,但是回报是显著的。

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

    如果你的目标DSL足够复杂,以至于你需要在写语法的时候大汗淋漓,那么这个愚蠢的视觉工具无论如何也不会减少芥末,你最终还是要学会写语法。

    不过,从长远来看,我同意内部和外部DSL。我在boo中编写了一个内部DSL,必须修改我的DSL语法以使其正常工作,这总是让人觉得像是一次黑客攻击。使用Irony.net或Antlr的相同语法同样容易实现,而且灵活性更高。

    我有一个 blog post 讨论一些选择。本文的中心是编写用于运行时表达式评估的DSL,但是工具都是相同的。

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

        2
  •  8
  •   Muhammad Haggag    16 年前

    如果您打算编写独立的DSL,那么您就需要构建编译器——不能绕过它。编译器构造 基本的编程知识,实际上并不像一般人想象的那样困难。Steve Yegge Righ Programmer Food 总结了了解如何非常好地构建编译器的价值。

    有很多方法可以开始。我建议查看文章中提到的两篇论文: Want to write a compiler? Just read these Two papers . 第一个, Let's build a compiler ,非常容易接近。它使用turbo pascal作为实现语言,但是您可以很容易地用任何其他语言实现它——源代码非常清楚。帕斯卡是一种简单的语言。

    一旦你对事物的工作方式和所涉及的术语有了良好的了解,我建议你深入研究 ANTLR . 安特尔有一个漂亮的侧面, ANTLRWorks ,它附带了一个解释器和一个调试器。它还可以在运行中产生非常好的语法可视化效果。我发现它在学习上非常有价值。

    Antlr有几个很好的教程,尽管一开始它们可能有点压倒性。 This one 很好,尽管它是针对Antlr2.0的,所以您可能会遇到与较新版本(当前最新版本是3.1)不兼容的问题。

    最后,还有另一种DSL方法:Lisp方法。考虑到Lisp的无语法特性(代码基本上是抽象语法树),只要习惯了括号,就可以从中塑造出无限的语言。

    如果您确实使用这种方法,那么您需要使用可嵌入的Lisp。在Java下,你有 Clojure 是一种与JVM及其库完美互操作的Lisp方言。我没亲自用过,但看起来不错。对于方案,有GNU Guile ,这就是 licensed under LGPL . 对于普通的口齿不清, ECL 也在LGPL下。两者都使用C接口实现互操作性,因此您几乎可以将它们嵌入到任何其他语言中。ECL在Lisp中是唯一的,因为每个Lisp函数都是作为C函数实现的,所以如果您想用C编写Lisp代码(例如,在您自己的扩展方法中,您可以创建对Lisp对象进行操作的C函数,然后从Lisp调用它们)。我用ECL做我的一个小项目已经有一段时间了,我喜欢它。维修人员非常活跃,反应迅速。

        3
  •  4
  •   Glorfindel Randy Levy    5 年前

    你真的应该去看看 Ragel . 它是一个将状态机嵌入常规源代码的框架。Ragel支持C、C++、Objul-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    10 年前

    Xtext 是为这个而建造的。

    从网站:

    Xtext是开发编程语言和 特定于域的语言。

    它涵盖了完整语言基础结构的各个方面,从 解析器、超链接器、编译器或解释器到完全成熟的顶级 Eclipse IDE集成。所有这些都有很好的默认值 同时,每个方面都可以根据 你的需要。

        5
  •  1
  •   jhaukur    15 年前

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

        6
  •  1
  •   Adil Akhter    13 年前

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

    Suffax项目带有一个很好的示例DSL实现和一个Java代码生成器。它可以作为开始使用工具的起点。

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

    希望它有帮助!

        7
  •  0
  •   Ira Baxter    10 年前

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

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