我遇到了交叉引用终端的问题,这些终端只是本地唯一的(在它们的块/范围内),但不是全局的。我发现tutorials描述了我如何使用完全限定名称或包声明,但我的情况在语法上与示例略有不同,我无法更改DSL以支持显式完全限定名称或包声明之类的内容
在我的DSL中,我有两种类型的结构化JSON资源:
我可以轻松地解析这两个,并使用以下Java代码段获取EMF模型:
new MyDSLStandaloneSetup().createInjectorAndDoEMFRegistration();
ResourceSet rs = new ResourceSetImpl();
rs.getResource(URI.createPlatformResourceURI("/Foo/meta.json", true), true);
Resource instanceResource= rs.getResource(URI.createPlatformResourceURI("/Bar/instance.json", true), true);
EObject eobject = instanceResource.getContents().get(0);
简单的例子:
meta.json
{
"toplevel_1": {
"sublevels": {
"sublevel_1": {
"type": "int"
},
"sublevel_2": {
"type": "long"
}
}
},
"toplevel_2": {
"sublevels": {
"sublevel_1": {
"type": "float"
},
"sublevel_2": {
"type": "double"
}
}
}
}
instance.json
{
"toplevel_1": {
"sublevel_1": "1",
"sublevel_2": "2"
},
"toplevel_2": {
"sublevel_1": "3",
"sublevel_2": "4"
}
}
由此我想推断:
我能够交叉引用独特的toplevel-elements并迭代所有的子级别,直到我找到了我正在寻找的那些,但是对于我的用例来说效率非常低且复杂。另外,我没有让生成的编辑器以这种方式在子级别之间建立链接。
我玩链接和范围,但我不确定我真正需要什么,如果我必须扩展providers-classes AbstractDeclarativeScopeProvider和/或DefaultDeclarativeQualifiedNameProvider。
最好的方法是什么?
另见:
答案 0 :(得分:2)
经过一些试验和错误后,我用ScopeProvider解决了我的问题。 主要问题是我并不真正理解Xtext术语中的作用域是什么,以及我必须提供什么。
查看documentation的签名:
IScope scope_<RefDeclaringEClass>_<Reference>(<ContextType> ctx, EReference ref)
在我的示例语言中:
使用ctx的eContainer,我可以从instance.json获取Toplevel。 这个Toplevel已经有一个来自meta.json的匹配Toplevel的交叉引用,我可以用它来从meta.json获取Sublevels。这个Sublevels集合基本上是当前Sublevel应该是唯一的范围。
为了获得IScope,我使用了Scopes#scopeFor(Iterable)。
我没有在这里发布任何代码,因为实际的语法更大/不同,因此并没有真正帮助解释。