我已经为一种语言实现了一种语法,这种语言最好被描述为C ++的脚本化版本,没有预处理器。我正在尝试确定范围。 (语法大约是500行,所以这可能会让你了解C ++语法包含了多少以及遗漏了多少。它包括枚举,类,全局和类成员函数,以及一些时髦的东西。这里并不重要。)
我觉得有点愚蠢提出这么广泛的问题可能有一个简单的答案,但我觉得在这一点上我已经烧掉了足够的时间在XText文档,书籍,网络搜索,相关博客和查看最好问的XText代码。
我正在试图找出范围。我已经完成的一些关键部分:
所以问题如下:
我如何(有效!)获取MyCppLikeDSLScopeProvider以允许以下类型的引用:
class MyClass {
void memberFunction();
Integer j;
...
}
Integer MyClass::memberFunction() {
return j;
}
我尝试过的一些事情:
我尝试过使用Scopes.scopeFor(context.getAllContentsOfType(ClassDecl),如果在同一个文件中定义了类,那可以正常工作,但不知何故我无法弄清楚如何让它工作如果该类位于另一个资源中,则可伸缩。例如,如果所有内容都在同一个文件中,并且我正在寻找可以是类,变量,函数或枚举的东西,我可以这样做:
def scope_SymbolicValue_ref(EObject context, EReference eRef) {
var Iterable<EObject> crossRefClassDeclTargets = context.getAllContentsOfType(ClassDecl).map[it as EObject]
var Iterable<EObject> crossRefDataDefTargets = context.getAllContentsOfType(DataDef).map[it as EObject]
var Iterable<EObject> crossRefFxnTargets = context.getAllContentsOfType(FunctionSpec).map[it as EObject]
var Iterable<EObject> crossRefEnumTargets = context.getAllContentsOfType(SimpleEnum).map[it as EObject]
var List<EObject> allCrossRefTargets = new ArrayList()
allCrossRefTargets.addAll(crossRefClassDeclTargets)
allCrossRefTargets.addAll(crossRefDataDefTargets)
allCrossRefTargets.addAll(crossRefEnumTargets)
allCrossRefTargets.addAll(crossRefFxnTargets)
return Scopes.scopeFor(allCrossRefTargets)
}
谢谢!我很乐意写更多详细信息,但我认为这是微不足道的。
答案 0 :(得分:0)
如果您需要能够引用任何全局可见的类/方法/等。从当前或其他模型,这是由访问Xtext索引的全局范围提供程序完成的。
在这种情况下,您需要一个像
这样的规则MethodImpl:
containingClass=[ClassDeclaration] '::' method=[Method] ;
在范围提供程序中,您必须为&#34;方法&#34;定义范围方法。为containingClass
的所有方法创建范围的属性,例如:
def scope_MethodImpl_method(MethodImpl methodImpl, EReference ref) {
Scopes::scopeFor(methodImpl.containingClass.members.filter(Method))
}
更棘手的部分是containingClass
的范围:
C ++没有像导入机制那样的东西。您只能为之前在同一文件中或直接或间接#include
d头文件中定义的类提供方法实现。
因此,如果您的C ++子集允许#include
,您必须以某种方式模拟此行为(这可能涉及创建自定义IDefaultResourceDescriptionStrategy
或类似的东西,但这不是问题的一部分。)
在任何情况下,使用缓存都是最有意义的,正如您所写,您应该使用IResourceScopeCache
来缓存直接或间接包含的文件中的所有类。
忽略循环包含,它可能看起来像这样:
@Inject
IResourceScopeCache cache
def Set<ClassDeclaration> getImportedClasses(Module module) {
cache.get("INCLUDED_CLASSES", module.eResource) [
(module.classDeclarations + module.includes.map[module.importedClasses].flatten).toSet
]
}