Dart是否支持编写嵌入式DSL?

时间:2013-12-18 14:15:27

标签: dart dsl

我想知道Dart是否能够在运行时使用Groovy能够提供的代理支持来执行闭包?请参阅此示例以便更好地理解:A Groovy DSL from scratch in 2 hours

我有一个用Groovy编写的DSL,可以轻松定义MARC库记录。我希望能够通过将定义调用绑定到程序中的委托类来本机处理类似的Dart脚本。

record {
   leader "00000nam a2200000 u 4500"
   controlfield "001", "LIB001"
   controlfield "005", "20120311123453.0"
   datafield("100") {
     subfield "a", "Author of record"
   }
   datafield("245", "0") {
     subfield "a", "Title of record"
   }
}

你可能想知道:为什么这不能用JSON表达?有了这样的DSL,我可以做的不仅仅是表达数据。因为它是嵌入式的,你可以在DSL中做任何有效的东西语言(这种情况下是Groovy)。如果你必须使用不同的值多次定义相同的东西,你可以做一个for循环,你可以使用GString表达式,调用数据库,访问文件等。通过定义DSLD,IDE就像知道你的概念一样它始终是语言的一部分,它可以为您提供辅助工具。它具有高度的表现力和直观性。

Dart的类似之处就是我正在寻找的东西。

2 个答案:

答案 0 :(得分:4)

Dart没有任何内置的DSL支持。但是,在某些情况下,您可以使用method cascadesoperator overloading来实现基本的DSL。

对于您的示例,只需要方法级联。您可以在parsers libraryFuzzy Logic library中看到一些运算符重载的好例子。

以下是代码级联版本的方法:

new Record()
  ..leader = '00000nam a2200000 u 4500'
  ..controlfield('001', 'LIB001')
  ..controlfield('005', '20120311123453.0')
  ..datafield('100', '',
      new Subfield('a', 'Author of record'))
  ..datafield('245', '0',
      new Subfield('a', 'Title of record'));

无法在此范围内添加循环,但您可以定义接受数据的方法和基于该数据创建字段的函数:

List data = [
               ['a', 'Title of record'],
               ['a', 'Something of record']
              ];
// Same record code from above with the addition of this line:
  ..datafields('245', '', data, (e) => new Subfield(e[0], e[1]));

示例使用以下支持类:

class Record {
  String leader;
  List<ControlField> controlFields = [];
  List<DataField> datafieldList = [];

  void controlfield(String a, String b) {
    controlFields.add(new ControlField(a, b));
  }

  void datafield(String a, String b, Subfield subfield) {
    datafieldList.add(new DataField(a, b, subfield));
  }

  void datafields(String a, String b, Iterable data, Subfield f(E e)) {
    data.forEach( (e) {
      datafieldList.add(new DataField(a, b, f(e)));
    });
  }

}

class ControlField {

  String a;
  String b;

  ControlField(this.a, this.b);
}

class DataField {

  String a;
  String b;
  Subfield subfield;

  DataField(this.a, this.b, this.subfield);
}

class Subfield {

  String a;
  String b;

  Subfield(this.a, this.b);
}

由于我不熟悉MARC记录,我已经在所有字段中使用了相当无用的字段名称a和b,随意将它们更改为适当的字段。我也相信我基于你的代码片段对结构做出的一些假设是错误的,但它们应该很容易改变。

答案 1 :(得分:0)

您应该查看sweet.js,它为JavaScript提供了卫生宏。您可以编写宏来接受所需的DSL。编译时,您将获得必须包含的JavaScript文件。然后,您可以直接从JavaScript或Dart使用DSL。