3

我对仅在本地唯一(在其块/范围内)而不是全局唯一的交叉引用终端有疑问。我找到了描述如何使用完全限定名称或包声明的教程,但我的案例在语法上与示例有点不同,我无法更改 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);

简单的例子:

元.json

{
    "toplevel_1": {
        "sublevels": {
            "sublevel_1": {
                "type": "int"
            },
            "sublevel_2": {
                "type": "long"
            }
        }
    },
    "toplevel_2": {
        "sublevels": {
            "sublevel_1": {
                "type": "float"
            },
            "sublevel_2": {
                "type": "double"
            }
        }
    }
}

实例.json

{
    "toplevel_1": {
        "sublevel_1": "1",
        "sublevel_2": "2"
    },
    "toplevel_2": {
        "sublevel_1": "3",
        "sublevel_2": "4"
    }
}

由此我想推断:

  • toplevel_1:sublevel_1 的类型为 int,值为 1
  • toplevel_1:sublevel_2 的类型为 long 且值为 2
  • toplevel_2:sublevel_1 的类型为 float 且值为 3
  • toplevel_2:sublevel_2 的类型为 double 且值为 4

我能够交叉引用独特的顶级元素并遍历所有子级别,直到找到我正在寻找的那些,但对于我的用例来说,这是非常低效和复杂的。此外,我没有让生成的编辑器以这种方式链接子级别。

我玩弄了链接和范围,但我不确定我真正需要什么,以及是否必须扩展提供程序类 AbstractDeclarativeScopeProvider 和/或 DefaultDeclarativeQualifiedNameProvider。

最好的方法是什么?

也可以看看:

4

1 回答 1

2

经过反复试验,我用 ScopeProvider 解决了我的问题。主要问题是我并没有真正理解 Xtext 术语中的范围是什么,以及我必须提供什么。

查看文档中的签名:

IScope scope_<RefDeclaringEClass>_<Reference>(<ContextType> ctx, EReference ref)

在我的示例语言中:

  • RefDeclaringEClass将引用来自 instance.json 的子级别,
  • 从 meta.json引用对 Sublevel 的交叉引用,以及
  • ContextType将匹配RefDeclaringEClass

使用 ctx 的 eContainer 我可以从 instance.json 中获取 Toplevel。这个 Toplevel 已经有对来自 meta.json 的匹配 Toplevel 的交叉引用,我可以使用它来从 meta.json 获取 Sublevels。这个子级别的集合基本上是当前子级别应该是唯一的范围。

为了获得 IScope,我使用了 Scopes#scopeFor(Iterable)。

我没有在这里发布任何代码,因为实际的语法更大/不同,因此并没有真正帮助解释。

于 2013-07-15T21:36:15.533 回答