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

我知道有一些语言工作台正在开发中,并且我听说过诸如 .NET 的“Irony”之类的东西。当然,还有 ANTLR、Lex/Yaac 等,但我担心这些对于我想做的事情来说太复杂了。

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

有帮助吗?

解决方案

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

我的意见是这样的:如果您的目标语言足够简单,可以由愚蠢的视觉设计人员处理,那么使用解析器生成器为其编写语法应该非常容易。

如果你的目标 DSL 足够复杂,以至于你需要费尽心思编写语法,那么愚蠢的可视化工具无论如何都无法满足你的要求,你最终还是不得不学习编写语法。

不过,从长远来看,我同意内部 DSL 与外部 DSL 的观点。我在 Boo 中编写了一个内部 DSL,并且必须修改我的 DSL 语法才能使其工作,而且总感觉像是一个 hack。使用 Irony.NET 或 ANTLR 的相同语法同样可以轻松完成,并且更加灵活。

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

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

其他提示

如果您正在考虑编写独立的 DSL,那么您正在考虑构建编译器——没有其他办法。编译器构建 基本的编程知识,而且它实际上并不像人们想象的那么困难。史蒂夫·叶格的 合适的程序员食物 总结了了解如何很好地构建编译器的价值。

有很多方法可以开始。我建议查看文章中提到的两篇论文: 想写一个编译器吗?只需阅读这两篇论文. 。第一个, 让我们构建一个编译器, ,非常方便。它使用Turbo Pascal作为实现语言,但你可以轻松地用任何其他语言实现它——源代码非常清晰。Pascal 是一种简单的语言。

一旦您对事物的工作原理和所涉及的术语有了很好的了解,我建议您深入研究类似的内容 ANTLR. 。ANTLR 有一个不错的 IDE, ANTLRWorks, ,它带有一个解释器和一个调试器。它还可以实时生成非常好的语法可视化效果。我发现它对学习非常有价值。

ANTLR 有几个很好的教程,尽管一开始可能会有点让人不知所措。 这个 很好,虽然它是针对 ANTLR 2.0 的,所以你可能会遇到与更新版本的不兼容问题(目前最新的是 3.1)。

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

如果您确实采用这种方法,那么您需要使用可嵌入的 Lisp。在Java下,你有 克洛尤尔, ,一种与 JVM 及其库完美互操作的 Lisp 方言。我个人没用过,但看起来不错。对于Scheme,有GNU 诡计, ,即 根据 LGPL 获得许可. 。对于 Common Lisp 来说,有 电化学发光, ,也在 LGPL 下。两者都使用 C 接口来实现互操作性,因此您几乎可以将它们嵌入到任何其他语言中。ECL 在 Lisp 中是独一无二的,因为每个 Lisp 函数都是作为 C 函数实现的,因此如果您愿意,您可以用 C 编写 Lisp 代码(例如,在您自己的扩展方法中 - 您可以创建对 Lisp 对象进行操作的 C 函数,然后从 Lisp 中调用它们)。我在我的业余项目中使用 ECL 一段时间了,我喜欢它。维护者非常活跃并且反应灵敏。

你真的应该检查一下 拉格尔. 。它是一个将状态机嵌入到常规源代码中的框架。Ragel 支持 C、C++、Objective-C、D、Java 和 Ruby。

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

使用 Ragel 的几个著名项目是: 杂种, ,一个很棒的 ruby​​ Web 服务器。和 赫普里科特, ,一个基于 ruby​​ 的 html 解析器,有点受 jQuery 的启发。

Ragel 的另一个重要功能是它如何生成 图形可视化基于图表,可视化您的状态机。下面是一个例子,取自 泽德·肖的 关于拉格尔州图表的文章.

ragel state chart

文本 是为此而建造的。

来自网站:

XTEXT是开发编程语言和域特定语言的框架。

它涵盖了一个完整的语言基础架构的各个方面,从解析器,链接器,编译器或解释器到完全吹出的顶级日食IDE集成。它在所有这些方面都有良好的默认设置,同时每个方面都可以根据您的需求量身定制。

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

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

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

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

希望能帮助到你!

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top