构建有效的外部 DSL
有什么工具可以帮助我构建一个真正的、诚实的外部 DSL。 不,我不是在谈论滥用 Ruby、Boo、XML 或其他现有语言或语法,我的意思是真正的外部 DSL——用于我自己目的的我自己的语言。
我知道有一些语言工作台正在开发中,并且我听说过诸如 .NET 的“Irony”之类的东西。 当然,还有 ANTLR、Lex/Yaac 等,但我担心这些对于我想做的事情来说太复杂了。
请谈谈您可能使用过或听说过的 DSL 构建器工具,以及您对它的帮助和缺点的印象。
What tools are there for me to build a real, honest to goodness external DSL. And no, I'm not talking about abusing Ruby, Boo, XML or another existing language or syntax, I mean a REAL external DSL -- my own language for my own purposes.
I know that there are a few language workbenches being developed and I've heard about things like "Irony" for .NET. And, of course, there's ANTLR, Lex/Yaac, etc but I'm afraid those are too complicated for what I'm trying to do.
Please talk about a DSL builder tool you may have used or heard about and your impressions on how it helps and what its downsides are.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我用 Boo、Irony.NET 和一个名为 Grammatica 的工具包编写了 DSL。 你说解析器生成器太复杂了,但你的判断可能太仓促了,事实上,一旦你克服了一个小的学习曲线,它们就很容易使用,并打开了一个广阔的可能性世界,很容易覆盖的努力。 我发现学习为大多数解析器生成器编写语法所需的符号有点类似于学习正则表达式 - 你必须稍微弯曲你的思想才能让它们进来,但回报是巨大的。
我的观点是:如果您的目标语言足够简单,可以由愚蠢的视觉设计人员处理,那么使用解析器生成器为其编写语法应该非常容易。
如果你的目标 DSL 足够复杂,以至于你需要费尽心思编写语法,那么愚蠢的可视化工具无论如何都无法满足你的要求,你最终还是不得不学习编写语法。
不过,从长远来看,我同意内部 DSL 与外部 DSL 的观点。 我在 Boo 中编写了一个内部 DSL,并且必须修改我的 DSL 语法才能使其工作,而且总感觉像是一个 hack。 使用 Irony.NET 或 ANTLR 的相同语法同样可以轻松完成,并且更加灵活。
我有一篇博客文章讨论一些选项。 这篇文章的重点是编写用于运行时表达式求值的 DSL,但工具都是相同的。
我对 Irony.NET 的体验是积极的,并且有几种使用它实现的参考语言,这是一个很好的起点。 如果您的语言很简单,那么安装和运行绝对不复杂。 CodeProject 上还有一个名为 TinyParser 的库 - 这个库非常有趣,因为它生成解析器作为纯源代码,这意味着您的最终产品完全不受任何第三方引用。 不过我自己没用过。
I've written DSLs in Boo, Irony.NET and a toolkit called Grammatica. You say that a parser-generator is too complicated, but you may be being too hasty in your judgment, in fact they are quite simple to use once you get over a small learning curve, and open up a vast world of possibility that easily overrides the effort. I found learning the notation required to write grammars for most parser generators somewhat similar to learning Regular Expressions - you have to bend your mind just slightly to let them in, but the rewards are significant.
My opinion is this: If your target language is simple enough that it could be handled by a dumbed down visual designer, then writing a grammar for it using a parser generator should be quite easy.
If your target DSL is complicated enough that you'll need to break a sweat writing a grammar, then the dumbed down visual tool won't cut the mustard anyway and you'll end up having to learn to write a grammar anyway.
I agree in the long term about internal vs external DSL's, though. I wrote an internal DSL in Boo and had to modify my DSL syntax to make it work, and it always felt like a hack. The same grammar using Irony.NET or ANTLR would have been just as easy to accomplish with more flexibility.
I have a blog post discussing some options. The post is centered around writing a DSL for runtime expression evaluation, but the tools are all the same.
My experience with Irony.NET has been all positive, and there are several reference language implemented using it, which is a good place to start. If your language is simple, it is absolutely not complicated to get up and running. There is also a library on CodeProject called TinyParser - this one is really interesting, because it generates the parser as pure source code, which means your final product is completely free of any third party reference. I haven't used it myself, though.
如果您正在考虑编写独立的 DSL,那么您正在考虑构建编译器——没有其他办法。 编译器构建是必不可少的编程知识,而且它实际上并不像人们想象的那么困难。 Steve Yegge 的正确的程序员食物总结了了解如何做的价值很好地构建编译器。
有很多方法可以开始。 我建议查看文章中提到的两篇论文:想要编写编译器吗? 只需阅读这两篇论文。 第一个让我们构建一个编译器非常容易访问。 它使用Turbo Pascal作为实现语言,但你可以轻松地用任何其他语言实现它——源代码非常清晰。 Pascal 是一种简单的语言。
一旦您对事物的工作原理和所涉及的术语有了很好的了解,我建议您深入研究 ANTLR 之类的内容。 ANTLR 有一个很好的 IDE,ANTLRWorks,它带有解释器和调试器。 它还可以实时生成非常好的语法可视化效果。 我发现它对学习非常有价值。
ANTLR 有几个很好的教程,尽管一开始可能会有点不知所措。 这个很好,尽管它是针对 ANTLR 2.0 的,所以您可能会遇到与更新版本的不兼容问题(目前最新的是3.1)。
最后,还有另一种 DSL 方法:Lisp 方法。 考虑到 Lisp 的无语法性质(你的代码基本上是抽象语法树),只要你习惯了括号,你就可以用它塑造无数的语言:)。
如果您确实采用这种方法,那么您需要使用可嵌入的 Lisp。 在 Java 下,您可以使用 Clojure,这是一种与 JVM 及其库完美互操作的 Lisp 方言。 我个人没用过,但看起来不错。 对于Scheme,有GNU Guile,即Guile。 gnu.org/software/guile/docs/docs-1.8/guile-ref/Guile-License.html" rel="noreferrer">根据 LGPL 许可。 对于 Common Lisp,有 ECL,也在 LGPL 下。 两者都使用 C 接口来实现互操作性,因此您几乎可以将它们嵌入到任何其他语言中。 ECL 在 Lisp 中是独一无二的,因为每个 Lisp 函数都是作为 C 函数实现的,因此如果您愿意,您可以用 C 编写 Lisp 代码(例如,在您自己的扩展方法中 - 您可以创建对 Lisp 对象进行操作的 C 函数,然后从 Lisp 中调用它们)。 我在我的业余项目中使用 ECL 一段时间了,我喜欢它。 维护者非常活跃并且反应敏捷。
If you're looking into writing stand-alone DSLs, then you're looking into building compilers--no way around it. Compiler construction is essential programming knowledge, and it's really not as difficult as commonly thought. Steve Yegge's Righ Programmer Food summarizes the value of knowing how to build compilers quite nicely.
There are plenty of ways to get started. I recommend checking out the 2 papers mentioned in the article: Want to write a compiler? Just read these Two papers. The first one, Let's build a compiler, is very accessible. It uses Turbo Pascal as an implementation language, but you can easily implement it in any other language--the source code is very clear. Pascal is a simple language.
Once you get a good feel for how things work and the terminology involved, I recommend delving into something like ANTLR. ANTLR has a nice IDE, ANTLRWorks, that comes with an interpreter and a debugger. It also produces really really good visualizations of your grammars on the fly. I found it invaluable in learning.
ANTLR has several good tutorials, although they might be a bit overwhelming at first. This one is nice, although it's against ANTLR 2.0, so you might run into incompatibilities with a more recent version (currently the latest is 3.1).
Finally, there's another approach to DSLs: The Lisp approach. Given Lisp's syntax-less nature (your code is basically abstract syntax trees), you can shape endless languages out of it, provided you get used to the parentheses :).
If you do go with that approach, you want to use an embeddable Lisp. Under Java, you have Clojure, a Lisp dialect that interoperates flawlessly with JVM and its libraries. I haven't used it personally, but it looks good. For Scheme, there's GNU Guile, which is licensed under LGPL. For Common Lisp, there's ECL, also under the LGPL. Both use a C interface for interoperability, so you can pretty much embed them into any other language. ECL is unique among Lisps in that each Lisp function is implemented as a C function, so you can write Lisp code in C if you want to (say, inside your own extensions methods--you can create C functions that operate on Lisp objects, and then call them from Lisp). I've been using ECL for a side-project of mine for a while, and I like it. The maintainer is quite active and responsive.
如果您计划实现外部 DSL,Spoofax (http://strategoxt.org/Spoofax) 是一个不错的选择语言工作台可以做到这一点。 它是一个基于解析器的文本语言工作台,利用了 SDF 、 Stratego 等多种最先进的技术。 除了 DSL 实现之外,您还可以获得非常丰富的编辑器服务,例如代码完成、大纲视图、智能感知等。它已被用于构建多种语言,例如 http://mobl-lang.org/。 查看此内容以了解所提供的支持。
Spoofax 项目附带了一个开箱即用的优秀 DSL 实现示例和一个 java 代码生成器。 它可以作为开始使用这些工具的起点。
以下教程详细介绍了此语言工作台的用法:http://strategoxt.org/Spoofax/Tour。
希望能帮助到你!
If you are planning to implement an external DSLs , Spoofax ( http://strategoxt.org/Spoofax )is a nice Language Workbench to do this. It is a parser-based textual Langauge Workbench that leverage several state-of-art technology such as SDF , Stratego. Besides the DSL implemenation , you could get a very rich editor services such as, code completion , outline view , intellisense etc. It has been used to build several languages e.g. http://mobl-lang.org/. Check this out to get the idea about the provided support.
Spoofax project comes with a out-of-the box nice sample DSL implementation and a java code generator. It may work as a starting point to get started with the tools.
Following tutorial details about the usage this langauge workbench : http://strategoxt.org/Spoofax/Tour.
Hope it helps!
Xtext 就是为此而构建的。
来自网站:
Xtext was built for this.
From the website:
我一直在使用 Irony 并取得了良好的效果。 讽刺的一个重要部分是,您可以轻松地将其包含在您将使用 DSL 的任何运行时中。 我正在创建一个外部 DSL,并将其填充到用 C# 编写的语义模型中,因此具有讽刺意义。 然后我使用语义模型通过 StringTemplate 生成代码。
I've been using Irony with good results. The great part about irony is that you can easily include it in whatever runtime you'll be using the DSL for. I'm creating an external DSL that I populate into a semantic model written in C# so irony is great. Then I use the semantic model to generate code with StringTemplate.
你真的应该看看 Ragel。 它是一个将状态机嵌入到常规源代码中的框架。 Ragel 支持 C、C++、Objective-C、D、Java 和 Ruby。
Ragel 非常适合编写文件和协议解析器以及单步执行外部 DSL 内容。 主要是因为它允许您在状态转换等上执行任何类型的代码。
使用 Ragel 的几个著名项目是 Mongrel,一个很棒的 ruby Web 服务器。 还有 Hpricot,一个基于 ruby 的 html 解析器,有点受 jQuery 的启发。
Ragel 的另一个强大功能是它如何生成基于 graphviz 的图表,以可视化状态机。 以下示例取自 Zed Shaw 关于 ragel 州图表的文章。
You should really check out Ragel. It's a framework to embed state machines in your regular source code. Ragel supports C, C++, Objective-C, D, Java and Ruby.
Ragel's great for writing file and protocol parsers as well as stepping through external DSL stuff. Chiefly because it allows you to execute any kind of code on state transitions and such.
A couple of notable projects that use Ragel are, Mongrel, a great ruby web server. And Hpricot, a ruby based html-parser, sort of inspired by jQuery.
Another great feature of Ragel is how it can generate graphviz-based charts that visualize your state machines. Below is an example taken from Zed Shaw's article on ragel state charts.
对于严重的外部DSL,你无法避免解析问题; ANTLR 是您最不需要的东西。 您想要检查的是程序转换系统,它可用于将任意 DSL 语法映射到 Java 等目标语言。
请参阅http://en.wikipedia.org/wiki/Program_transformation
For serious external DSLs, you can't avoid the parsing problem; ANTLR is the least of what you need. What you want to check is program transformation systems, which can be used to map arbitrary DSL syntax into target languages like Java.
See http://en.wikipedia.org/wiki/Program_transformation