【发布时间】:2017-01-01 05:11:23
【问题描述】:
我已经为一种语言实现了一种语法,这种语言最好被描述为 C++ 的脚本版本,而无需预处理器。我正在尝试使范围界定工作。 (语法大约有 500 行,所以这可能让您了解包含了多少 C++ 语法以及遗漏了多少。它包括枚举、类、全局和类成员函数,以及一些时髦的东西在这里并不重要。)
我觉得问这么宽泛的问题可能有一个简单的答案有点愚蠢,但我觉得在这一点上我已经花了足够的时间在 XText 文档、书籍、网络搜索、相关博客和看看XText的代码最好问问。
我正在尝试确定范围。我已经在工作的一些关键部分:
- 它提供了适当的限定名称,因此类 C 的对象成员变量 x 是 C.x。理论上,一旦我有一个类型系统(如 XText 书中的那个)工作,这应该可以让我确定一个对象的类型,然后使用它来导入该类的范围。
- 在语法中词法分析器规则可能具有多个相应数据类型的地方,我已经弄清楚了如何使用 ref=[ecore::EObject|GenericDataTypeRule],其中我有 GenericDataTypeRule: name=ID;
所以问题如下:
我如何(有效地!)让我的 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) } - 本示例中不包含类继承,但我已经设法按照书中的示例并自定义多重继承来使其工作,尽管它并没有真正执行正确的 DFS 或 BFS,它更像是“愚蠢但终止搜索”:在每一步中,查看每个顶点的边,并在步骤结束时查看顶点数是否等于您开始的顶点数;所以也许我应该使用非愚蠢的图形搜索来加快速度。
- 我确实尝试过使用 context.resourceSet 并迭代所有资源并过滤所有类,但我的代码库大约 300 个文件中有大约 300k 行,这太慢了。
- 我尝试编写一个实现 IScope 的自定义类。 Scopes.ScopeFor 将 EObject 的列表转换为 EObjectDescription 的列表,但是如果我有两个 EObjectDescription 列表(例如,我可以从两个不同的实现 IScope 的类中得到它)想要组合呢?当然,必须有一种简单的方法来合并两个范围,而我只是脑死亡,找不到它。
- 我已经开始考虑编写自己的对象缓存,这将使我转向一个完全 100% 自定义的类,从头开始实现 IScope,但显然 XText 有相当多的类继承自 AbstractScopeProvider,我只需要找出我需要使用哪一个。
谢谢!我很乐意写更多细节,但我想这很简单。
【问题讨论】:
-
你能提示一下你真正想要的范围吗?
-
对于你也不需要任何范围界定的课程。方法调用需要它
-
和 ref=[ecore::EObject|GenericDataTypeRule] 的东西没有意义。请解释
标签: xtext