1

我有一个非常简单的 DSL,它由一个包含比较器列表的验证器元素组成:

Validator:
  'validator' name = ID '{'
    comparisons+=Comparison*
  '}'
;

Comparison:
  LessThan | GreaterThan | EqualTo
;

LessThan:
  'lt' value = INT
;

有了这个,我正在尝试生成 C 代码。在我遍历每个验证器的地方,创建一个 C 文件(基于验证器的名称)并将比较器放入三元条件语句中。当我遍历每个比较器时,它会调用Comparison输出if语句的类的定义。一个缩减示例(输出类似于 CPPUNIT 的内容):

int
main(int argc, char **argv)
{
  // parse argv[1] if it exists -> place into i
  printf("%c", i < (comparator_value_1) ? '.' : 'F');
  printf("%c", i > (comparator_value_2) ? '.' : 'F');
  printf("\n");
  return 0;
}

我可以很好地完成所有这些工作;但是我遇到的问题是我似乎必须在我的Comparison生成器中选择条件。我似乎无法通过为 LessThan 添加处理程序来覆盖生成器。

def compile(Comparison c) '''
  printf("%c",
    i «IF c.eClass.name.equals("LessThan")»...«ENDIF» «c.value»
      ? '.' : 'F');
'''

当我试图重载它时:

def compile(LessThan lt) '''
  printf("%c", i < «c.value» ? '.' : 'F');
  ...
'''

重载的例程不会被调用,这充其量是不幸的。

如果这有什么不同,它会被调用:

«FOR c:v.comparisons»
  «c.compile»
«ENDFOR»

其中“v”是验证器。

Xtext有这个能力吗?

4

1 回答 1

1

Xtext 可以使用多态调度(@SpaceTrucker 提供),其中:

可以根据多个参数的运行时(动态)类型动态调度函数或方法。

为了使用这个功能,我不得不添加一个词dispatch

def dispatch expandComparator(GreaterThan gt) '''
    printf("%c", i < «gt.value» ? '.' : 'F');
'''

def dispatch expandComparator(EqualTo eq) '''
    printf("%c", i == «eq.value» ? '.' : 'F');
'''

def dispatch expandComparator(LessThan lt) '''
    printf("%c", i < «lt.value» ? '.' : 'F');
'''

并使用以下内容生成它:

«FOR c:v.comparisons»
    «c.expandComparator»
«ENDFOR»

compile函数的名称必须像单个调度函数一样更改。

以下链接包含有关此解决方案的更多详细信息。 http://dslmeinte.wordpress.com/2012/08/03/polymorphic-dispatch-in-xtend/

于 2012-10-05T19:36:58.490 回答