2

I am having trouble with this concept in building a dsl. I am not sure if it is a simple thing I am missing or something that is not an intended feature of xtext. Hopefully someone can explain it to me in the context of this example.

Given the following minimal grammar:

Model:
    'ns' name=QualifiedName
    classes+=Class*
    instances+=Instance*
    uses+=Use*
;

Class:
    'class' name=ID '{'
        variables+=Variable*
    '}'
;

Variable:
    'var' variable=PrimaryVariable
;

Instance:
    variable=PrimaryVariable '=' 'new' type=[Class]
;

Use:
    reference=[PrimaryVariable|QualifiedName]
;

PrimaryVariable:
    name=ID
;

QualifiedName:
    ID ('.' ID)*
;

I would like to be able to write the following code, which of course is not valid:

ns com.mine
class Class1 {
    var var1
}
instance1 = new Class1
instance1.var1 // <- error here, can't resolve reference

With this grammar and default scoping, only this would work:

ns com.mine
class Class1 {
    var var1
}
instance1 = new Class1
Class1.var1

So my question is: how would I go about implementing the concept of referencing variables by qualified name through an instance variable?

I don't think I could manage qualifiedNameProvider to achieve this because the PrimaryVariable does not have knowledge of what instance it is being used in.

I could of course create a rule which uses two reference (and is what I am currently doing), one to the instance variable and then traverse the instance variable's type to get variables in scope for the variable reference, but this seems like a hack to the way it should be and not as scalable in the case of nested objects.

This is a slightly broad question, I am hoping that I can get informed before I go off doing something completely counter productive.

Joel
  • 1,564
  • 7
  • 12
  • 20
Zannith
  • 429
  • 4
  • 21

1 Answers1

2

Here is a sample for the scope provider

import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EReference
import org.eclipse.xtext.EcoreUtil2
import org.eclipse.xtext.naming.QualifiedName
import org.eclipse.xtext.resource.EObjectDescription
import org.eclipse.xtext.scoping.IScope
import org.eclipse.xtext.scoping.impl.SimpleScope
import org.xtext.example.mydsl6.myDsl.Model
import org.xtext.example.mydsl6.myDsl.MyDslPackage

class MyDslScopeProvider extends AbstractMyDslScopeProvider {

   override getScope(EObject context, EReference reference) {
      if (reference === MyDslPackage.Literals.USE__REFERENCE) {
         val model = EcoreUtil2.getContainerOfType(context, Model)
         if (model !== null) {
            val result = newArrayList
            for (i : model.instances) {
               result.add( EObjectDescription.create(
                  QualifiedName.create( i.variable.name ), i.variable ))
               for (v : i.type.variables) {
                  result.add( EObjectDescription.create(
                     QualifiedName.create( i.variable.name, v.variable.name ),
                     v.variable ))
               }
            }
            println(result)
            return new SimpleScope(IScope.NULLSCOPE, result)
         }
      }
      super.getScope(context, reference)
   }
}
Aubin
  • 14,617
  • 9
  • 61
  • 84
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32
  • Wow, okay it may seem obvious to most, but I had not thought to create my own eObjectDescriptions in scoping. I have just always been providing a list of candidates. – Zannith Nov 06 '18 at 13:20