由于讨论了一个工作示例已创建并添加到https://github.com/Johanvdberg/mcrl2.xtext,请参阅test.multiname。*和test.reflang。* eclipse项目。
Multiname 由语法
定义grammar test.multiname.dsl.MultiNameDsl with org.eclipse.xtext.common.Terminals
generate multiNameDsl "http://www.multiname.test/dsl/MultiNameDsl"
Model:
modules+=Module+;
Module:
'begin module' name=ID
vars+=Vars*
funcs+=Funcs*
'end_module';
VarName:
name=ID;
FuncName:
name=ID;
Name:
VarName | FuncName;
Funcs:
'func' left=FuncName (bracket?='(' ')')? '=' right=[Name] ';';
Vars:
'var' VarName ';';
具有此语法的文件将类似于
begin module test1
var t1v1;
var t1v2;
end_module
或
begin module test2
var t2v1;
var t2v2;
end_module
将引用上述语言的语言语法 RefLang
语法test.reflang.dsl.RefDsl与org.eclipse.xtext.common.Terminals
generate refDsl "http://www.reflang.test/dsl/RefDsl"
import "http://www.multiname.test/dsl/MultiNameDsl" as multi
Model:
ref_from=Import
refs=DataRef;
Import:
'import' imports=[multi::Module];
DataRef:
'ref_vars' data+=[multi::VarName|FQN] (',' data+=[multi::VarName|FQN])*;
FQN:
ID ("." ID)*;
并且具有上述语法的文件如下所示:
import test2
ref_vars test2.t2v1, test1.t1v1
希望行为是ref_vars
只能来自import
指定的模块,上面的文件是test2
而var test1.t1v1
不正确。< / p>
RefLang 的范围提供者是:
override getScope(EObject context, EReference reference) {
if (context instanceof DataRef) {
if (reference == RefDslPackage.Literals.DATA_REF__DATA) {
val rootElement = EcoreUtil2.getRootContainer(context)
return super.getScope(context, reference);
}
}
return super.getScope(context, reference);
}
但我无法使用rootElement访问 multiname 语言中定义的模型元素test2
以及 RefLang 中的引用。所有属性rootElement.ref_from.imports.{vars, funcs}
均为null
。
注意问题有所改变,而且工作正常,这些更改是基于对旧问题的评论而做出的。
旧问题
我有两个语法A
和B
,其中语法B
引用语法A
中的元素:
Model:
import_model=Import
flows=FlowData;
Import :
'import' importURI=STRING ';';
FlowData:
'flows' data+=[A::Flow|FQN] (',' data+=[A::Flow|FQN])* ';';
FQN: ID ("." ID)*;
importURI
定义使用语法A
的文件,并包含Flow
开头引用的定义。
使用https://christiandietrich.wordpress.com/2011/10/15/xtext-calling-the-generator-from-a-context-menu/中的上下文菜单可以访问语法模型B
。如何在同一个处理程序中访问importURI
指定的文件模型?
更新1
添加与导入相关的MWE2文件:
fragment = scoping.ImportNamespacesScopingFragment2 auto-inject {}
referencedResource="platform:/resource/.../A.genmodel"
在语法文件中
import "http://www..../A" as A
添加语法B的dsl项目plugin.xml与语法A
的dsl项目的依赖关系。还分别增加了ide和ui项目对ide和ui的依赖性。
需要访问完整的语法模型A
。语法A
定义一个系统和语法B
定义数据在系统中的位置,并且需要转换两个模型的并集。
每种语法模型A
可能存在多个配置(模型)。
答案 0 :(得分:1)
你似乎是一个真正讨厌语法作业的人
Funcs:
'func' left=FuncName (bracket?='(' ')')? '=' right=[Name] ';';
Vars:
'var' varName=VarName ';';
这里是适用于我的scopeprovider
class MyDslScopeProvider extends AbstractMyDslScopeProvider {
override getScope(EObject context, EReference reference) {
if (context instanceof DataRef) {
if (reference == MyDslPackage.Literals.DATA_REF__DATA) {
val rootElement = EcoreUtil2.getContainerOfType(context, Model)
val names = <Name>newArrayList
val importedModule = rootElement?.ref_from?.imports
if (importedModule !== null) {
for (v : importedModule.vars.map[varName]) {
names += v
}
for (f : importedModule.funcs.map[left]) {
names += f
}
}
// this is the unqualified variant
// return Scopes.scopeFor(names)
// this is the unqualified variant
return Scopes.scopeFor(names, [QualifiedName.create(importedModule.name, it.name)], IScope.NULLSCOPE)
}
}
return super.getScope(context, reference);
}
}
此外,关键字中空格的使用是代码气味,可能会导致意外行为
你应该只考虑引用的简单相同
(在范围界定 - 请参阅我的评论 - 以及语法ref=[XXX|ID]