2009-10-04 79 views
5

我想知道部署必须至少以两种语言(Java,C#)运行并且可能更多(Python,可能还有Javascript)的领域特定语言的好策略。编写便携式域特定语言

一些背景。我们已经开发并部署了一个当前用C#编写的领域特定语言。它通过一系列方法调用进行部署,其参数是公共语言基元(字符串,double等),集合(IEnumerable,HashSet,...)或特定于领域的库(CMLMolecule,Point3,RealSquareMatrix)中的对象。这个库已经过很好的测试,对象必须遵守一个稳定的部署XML模式,所以变化将会演化和管理(至少这是希望)。

我们希望这个语言能够被广泛和部分计算机使用的社区使用,用于在没有中央控制的情况下攻击他们自己的解决方案。理想情况下,DSL将创建一定程度的封装并产生他们所需的基本功能。图书馆将管理多种多样而详细的算法。 DSL的要求在Domain-specific languages vs. library of functions中有很多共同之处。

我很欣赏最好的体系结构(很明显,一旦部署,我们不能轻易回溯)。选项至少包括:

  • 创建IDL(例如通过CORBA)。 W3C为XML DOM做了这样的工作 - 我讨厌它 - 并且它似乎是过度杀伤
  • 手动为每个平台创建类似的签名并尽力保持它们的同步。
  • 创建可解析语言(例如CSS)。
  • XML声明式编程(c.f. XSLT)。这是我的首选解决方案,因为它可以被搜索,操纵等。

性能并不重要。明确的目的是。

编辑有关应用程序调用是否构成DSL的讨论。我发现了Martin Fowler对DSL的介绍(http://martinfowler.com/dslwip/Intro.html),他认为简单的方法调用(或者链接调用)可以称为DSL。等等一系列这样的:

point0 = line0.intersectWith(plane); 
point1 = line1.intersectWith(plane); 
midpoint = point0.midpoint(point1); 

可以被认为是DSL

+1

了很大的负面在XML表达的任何语言。你打算让开发人员直接使用XML或者是存储/运行时格式?发明ANT的人说XML是错误的选择,如果他能改变事情,他会选择不同的方式。 – SteveD 2009-10-08 14:10:55

+0

@stevendick。谢谢,我听到你说的话。我个人是一个XML上瘾者,但我尽量保持开放的态度。 – 2009-10-08 20:25:48

+0

看看ANT的原作者有什么话:http://web.archive.org/web/20040602210721/x180.net/Articles/Java/AntAndXML.html 不要盲目地遵循XML-金锤范例。如果您打算创建一个由实际人员阅读和写入的DSL,请考虑使用许多优秀的词法分析器/分析器工具中的一种,而不是XML。这些日子里有很多很好的工具(比如ANTLR)使得这个工具很实用。现在写lexers/parser并不像现在lex/yacc是最先进的那样痛苦。 – 2009-10-15 01:50:00

回答

6

语言和图书馆之间的问题似乎有些不明确之处。术语“内部DSL”和“外部DSL”是有用的,我认为是由于Martin Fowler

“外部”DSL可能是一个独立的命令行工具。它传递了一串资源,它以某种方式解析它,然后用它做一些事情。对语法和语义如何工作没有真正的限制。它也可以作为一个库,主要由类似eval的方法提供;一个常见的例子是将SQL查询作为字符串构建并在RDBMS库中调用execute方法;不是一个非常愉快或方便的使用模式,而且如果大规模地散布在一个程序中,那就太糟糕了。

“内部”DSL是一种库,其编写方式是利用主机(通用)语言的怪癖来创建新语言可嵌入现有语言的印象。在语法丰富的语言(C++,C#)中,这意味着使用操作符重载的方式严重拉伸(或忽略)操作符的通常意义。 C++中有很多例子。在C#中也有一些 - Irony parser toolkit以相当有限的方式模拟BNF,效果很好。

最后,还有一个普通的旧图书馆:类,方法,属性,以及精心挑选的名字。

外部DSL将允许您完全忽略跨语言集成问题,因为唯一类似库的部分将是eval方法。但是发明自己的工具链并不重要。人们总是忘记调试,智能感知,语法突出等重要性。

如果您想在C#和Java上做好,内部DSL可能是毫无意义的努力。问题是,如果你利用一种宿主语言的怪癖,你不一定能够重复另一种语言的技巧。例如Java没有运算符重载。

这留下一个普通的旧图书馆。如果你想跨越C#和Java(至少),那么你在选择实现语言方面存在一些困难。你真的想两次写图书馆吗?一种可能性是使用Java编写库,然后使用IKVM将其交叉编译为.NET程序集。这将保证你在这两个平台上都有相同的界面。

不利的一面是,API将用最小公因分位特征来表示 - 也就是说,Java特性:)。没有属性,只需getX/setX方法。避开泛型,因为这两个系统在这方面有很大不同。即使这两种命名方法的标准方式也不同(camelCasePascalCase),所以一组用户会闻到一只老鼠。

+0

@Earwicker +1非常有用的概述。 Java和C#的参与是一个给定的(不幸的)。我一定会尝试IKVM。我不介意丢失属性,泛型很简单。命名约定可以是自动的,我希望。 我知道发明我自己的工具链的问题,这是一个有用的总结。 – 2009-10-04 10:15:06

+0

是的,毫无疑问,你可以编写一个修复命名约定的工具。你甚至可以为属性做类似的事情 - 寻找getX/setX方法对(虽然也许一个属性标记是必须的,因为并非所有的getX方法都适用于属性语法,例如有时它们具有可见的副作用)。 – 2009-10-04 10:26:09

+1

@Earwicker。这是我目前的想法。减少对尽可能多的语言的通用子集的调用(例如,不要使用属性,当然不是运算符重载)。 – 2009-10-04 10:32:16

1

能够逃脱在你需要做的事情,只是不被你的DSL支持,或性能方面的原因的情况下实现语言(尽管我意识到这不是优先事项)。

我正在研究在C#中的规则引擎中实现规则的DSL,其中一些规则非常复杂,并且可能在未来发生重大变化,因此能够转义出C#是非常有用的。当然,这会打破跨平台兼容性,但它实际上只是一种绕过边缘案例而不必更改DSL的方式。

+1

@戴尔。是!会出现边缘案例,没有理由不以这种方式加以处理,然后可能会被抽象化和泛化。我希望主要的图书馆功能无论如何都会被公开,所以我们不会有一个单一的网关。 – 2009-10-04 08:56:33

0

你最好关闭写在C库(或类似rpython将生成C代码的一些语言),然后使用痛饮或类似的生成C#语言的特定绑定的Java的Python等

请注意,如果您在浏览器中使用Javascript,此方法将无济于事 - 您必须单独编写JavaScript库。如果您通过Rhino使用JavaScript,那么您将只能使用Java绑定。

0

可以直接使用脚本引擎从Java程序内部解释JavaScript,显然也可以从C#解释。 Python可以在JVM和.NET引擎上运行。

我建议您调查这些选项,然后将您的库写入可用于您选择的语言的执行路径的通用子集中。我不会考虑用需要翻译和转换的语言编写它,因为您引入了一个步骤,在发生问题时可能非常非常难以调试。

2

虽然我不想过多宣传我自己的项目,但我想提一下PIL, a Platform Independent Language,这是一种我一直致力于支持多种软件平台(如Java,Python等)的中间语言。 ,专门用于外部DSL。总的想法是,您可以在PIL(Java的一个子集)中生成代码,然后PIL编译器可以转换为其他语言之一,目前只是Java或Python,但将来会增加更多。

大约两天前,我在软件和语言工程会议上介绍了关于此问题的一篇论文,如果您有兴趣,可以找到PIL网站(pil-lang.org)的出版物链接。

+0

几年前我尝试过这样的事情,看到人们做得更好很有用。 – 2009-10-08 20:27:35

3

如果您愿意使用ANTLR重新描述您的语言,则可以使用多种语言生成您的DSL解释器,而无需手动维护它们,包括所提及的所有语言以及更多。

的Antlr是一个语法/词法分析器生成器和有大量目标语言。这允许您一次描述您的语言,而无需保留多个副本。

见目标语言here的整个列表。

+0

我个人喜欢这个想法。当然,这是一个巨大的飞跃,难以从 – 2009-10-08 20:26:22

+0

撤退。确实,有一个Antlr和StringTemplate的学习曲线。但是,我个人喜欢它。我发现越来越多的问题可以用简单描述的语法来解决。最终,当你在转换过程中松动的时候,你将不仅能够弥补节省的维护费用。 – 2009-10-09 18:32:32

0

我想展开Darien的答案。我认为ANTLR带来了一些其他词法分析器工具提供的东西(至少据我所知)。如果你想创建一个最终生成Java和C#代码的DSL,ANTLR真的很闪耀。

ANTLR提供了四个基本要素:

  • 词法语法(分解输入流为标记)
  • 分析器语法(组织标记成抽象语法树)
  • 树语法(走抽象语法树并将元数据导入模板引擎)
  • StringTemplate(基于函数式编程原则的模板引擎)

您的词法分析器,分析器和树语法可以保持独立于最终生成的语言。实际上,StringTemplate引擎支持模板定义的逻辑组。它甚至提供了模板组的接口继承。这意味着,当您最初提供的所有内容都是java和C#输出时,您可以让第三方使用您的ANTLR解析器创建说python,assembly,c或ruby。随着时间需求的变化,DSL的输出语言可以很容易地扩展。

要充分利用ANTLR的你将要阅读以下内容:

The Definitive ANTLR Reference: Building Domain-Specific Languages

Language Implementation Patterns: Create Your Own Domain-Specific and General Programming Languages