Search code examples
xtextscoping

Scoping in Xtext


I have troubles with understanding how i can influence the scoping. assume i have simple grammar:

Model:
    def = DefVarList
    (use = UseList)?
;

DefVarList:
    name = 'def' '{' (list += DefVar)* '}'
;

DefVar:
    name = ID ';'
;

UseList:
    name = 'use' '{'
        (list += UseVar)* 
    '}'
;

UseVar:
    name = [DefVar] ';'
;

of course, writing something like

def {   qwerty;  }
use {   qwerty;  }

results error, because one couldn't resolve a reference. So i went to ScopeProvider class and rewrite it:

public class TestgrammarScopeProvider extends AbstractTestgrammarScopeProvider{
    public IScope scope_UseVar_name(UseVar v, EReference ref) {
        Model m = (Model)v.eContainer().eContainer();
        return Scopes.scopeFor(m.getDef().getList());
    }
}

This doesn't working. It doesn't even call this function. What am i doing wrong?

P.S. i know about inserting fragment line in my mwe2 file, but i wonder why this program doesnt call this function.


Solution

  • You are using a cross reference as an identifier in UseVar. I changed that to

    UseVar: ref=[DefVar] ';'
    

    Then this xtend snippets works for your DSL.

    override IScope getScope(EObject context, EReference ref){
        if(context instanceof UseVar && ref == USE_VAR__REF){
            val model = context.getContainerOfType(Model)
    
            val defVarList = model.def.list         
            return Scopes::scopeFor(defVarList)
        }
        return IScope::NULLSCOPE
    }
    

    Am also assuming this is just a starting demo to get your project going but you might consider removing some of the syntactic noise such using this for a list instead

     List items+=rule (',' items+=rule)*;
    

    or perhaps removing the curly braces too (but you may want nested blocks later in which case you may need them). Only you can tell but its worth considering.