Xtext как ссылаться на переменные по определенному имени через экземпляр? - PullRequest
0 голосов
/ 06 ноября 2018

У меня возникли проблемы с этой концепцией при создании DSL. Я не уверен, упускаю ли я простую вещь или что-то, что не предназначено для xtext. Надеюсь, кто-то может объяснить это мне в контексте этого примера.

Учитывая следующую минимальную грамматику:

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)*
;

Я бы хотел написать следующий код, который, конечно, недействителен:

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

С этой грамматикой и областью видимости по умолчанию будет работать только это:

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

Итак, мой вопрос: как бы я реализовал концепцию обращения к переменным по квалифицированному имени через переменную экземпляра?

Не думаю, что мне удалось бы qualifiedNameProvider добиться этого, потому что PrimaryVariable не знает, в каком экземпляре он используется.

Конечно, я мог бы создать правило, которое использует две ссылки (и это то, что я сейчас делаю), одну на переменную экземпляра, а затем перебираю тип переменной экземпляра, чтобы получить переменные в области видимости для ссылки на переменную, но это похоже на хак к тому, как это должно быть и не так масштабируемо для вложенных объектов.

Это немного широкий вопрос, я надеюсь, что смогу получить информацию, прежде чем приступить к выполнению чего-то совершенно непродуктивного.

1 Ответ

0 голосов
/ 06 ноября 2018

вот пример для провайдера области действия

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

/**
 * This class contains custom scoping description.
 * 
 * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#scoping
 * on how and when to use it.
 */
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)
    }

}
...