首页 > 解决方案 > Xtext中“无法解析引用”的不同情况,特别解决了,但是属性引用呢?

问题描述

我有以下 Xtext 语法部分:

AssignmentStatement: (variable=[SymbolicVariable] | array=ArrayVariable) ':=' value=Expression;
ArrayVariable: varName=[SymbolicVariable] '[' index=Expression ']';
SymbolicVariable: name=ID;

以及 id1 和 id2 是 SymbolicVariable 的测试,此外 SymbolicVariable 可以是 Expression 的一部分:

id1 := 0 < id2 [ 0 ]

在测试中,之前没有定义 id1 和 id2 ,因为我通过语法生成输入作为测试并且不关心语义。我想为它们动态创建对象以摆脱:

错误:无法解析对 SymbolicVariable 'id1' 的引用。

错误:无法解析对 SymbolicVariable 'id2' 的引用。

同时验证。

遵循 post XText cross-reference to an non-DSL resource的想法,我能够创建 ScopeProvider impl 和 Scope impl:

class MyScope extends AbstractPoSTScopeProvider {
    
    override getScope(EObject context, EReference reference) {
        val res = context.eResource
        var uri = res.URI       
        val rs = res.resourceSet
        val scope = super.getScope(context, reference)
        if (context instanceof ArrayVariableImpl) new ScopeWrapper(scope, res) else scope
    }
}

class ScopeWrapper implements IScope {
    
    IScope scope;
    Resource resource;
    
    protected new(IScope w, Resource res) {
        scope = w
        resource = res
    }
    override getSingleElement(QualifiedName name) {
        println("[scope]getSingleElement " + name.toString())
        val r = scope.getSingleElement(name)
        if (r === null) {
            val fac = PoSTPackage.eINSTANCE.getPoSTFactory()
            var s = fac.createSymbolicVariable()
            s.name = name.toString()
            println("[!!!!! ] creation")
            Main.isChanged = true //to rerun in cause of modification 
            val ret = new MyDescr(s, name) //just a wrap
            resource.contents += s
            ret
        } else
        r
    }
    
}

注入后,出现了id2,我可以用它生成代码,但我仍然得到

错误:无法解析对 SymbolicVariable 'id1' 的引用。

而且在调试期间我在任何地方都看不到 id1 。

似乎,对于属性,我们需要一些其他的魔法。我应该遵循哪种模式?

标签: referencextext

解决方案


在测试中,之前没有定义 id1 和 id2 ,因为我通过语法生成输入作为测试并且不关心语义。

如果您正在生成文本模型id1 := 0 < id2 [ 0 ],我不确定您为什么无法生成它,因为id1; id2; id1 := 0 < id2 [ 0 ]这可能会解决。

如果您真的想“动态创建 id1 和 id2”,我认为您需要自定义您的IScopeProvider实现,以便在计算两个引用的范围时AssignmentStatement.variableArrayVariable.varName如果父实现返回一个空范围,那么您只需SymbolicVariable在内存中创建一个并提供它在返回的范围内。


推荐阅读