【问题标题】:Import packageDefinition '.' InterfaceDefinition when defining xtext grammar导入 packageDefinition '.'定义xtext语法时的InterfaceDefinition
【发布时间】:2014-07-07 12:46:26
【问题描述】:

我正在尝试使用 xText 创建一个简单的语法。语法应该(仅)定义 Java 接口的语言,目前我正在努力处理导入声明。我希望能够从我使用它们的 FQN 定义的其他包中引用其他接口。这是我的语法的样子:

DomainModel:
    elements=AbstractElement;

AbstractElement:
    'package' packageDeclaration=PackageDeclaration 
    'import'? importDeclarations+=ImportDeclaration*
    typeDeclaration=TypeDeclaration;

PackageDeclaration:
    name=QualifiedName ';';

ImportDeclaration:
    importedNamespace=[ReferncedType|QualifiedName] ('.*')? ';';

ReferncedType:
    PackageDeclaration |InterfaceDeclaration; //need to combine both?? separated by '.'

TypeDeclaration:
    'interface' interfaceDeclaration=InterfaceDeclaration;

TypeList:
    Type ( ',' type+=Type)*;

Type:
    typeDefinition=[ReferncedType|ValidID];

InterfaceDeclaration:
    name=ValidID ('extends' superType=TypeList)? body=InterfaceBody;

InterfaceBody:
    '{' (declarations+=InterfaceBodyDeclaration)+ '}';

InterfaceBodyDeclaration:
    interfaceMemberDelcaration+=InterfaceMemberDeclaration ';';

InterfaceMemberDeclaration:
    InterfaceMethodDeclaration;
InterfaceMethodDeclaration:
    (Type | 'void') name+=ValidID '(' (formalParameters+=FormalParameters)* ')' ('throws'
    ....)?;

我已经定义了两个文件:

package org.first.sample;

interface Demo {
   void getA();
}

....

package org.second.sample;

import org.first.sample.Demo; // this line says that the reference to org.first.sample.Demo is invalid, but I am able to reference org.first.sample

interface AnotherDemo {
   Demo getDemo();
}

你有什么想法吗?

【问题讨论】:

  • 不行,Demo类编译好了。

标签: java antlr grammar xtext


【解决方案1】:

当我阅读语法时:

ImportDeclaration:
    importedNamespace=[ReferncedType|QualifiedName] ('.*')? ';';

ReferncedType:
    PackageDeclaration |InterfaceDeclaration; //need to combine both?? separated by '.'

PackageDeclaration:
    name=QualifiedName ';';

所以import 后面可以跟一个 (PackageDeclaration=QualifiedName 后面跟一个 ;,然后回到规则 ImportDeclaration,后面必须跟另一个 ;

另外,我不明白为什么ReferncedType也可以扩展成一个InterfaceDeclaration,这就是整个事情?

稍后

所以,也许“导入”应该定义为

AbstractElement:
    'package' packageDeclaration=PackageDeclaration 
    importDeclarations+=ImportDeclaration*
    ...

ImportDeclaration
   'import' importedNamespace=QualifiedName ('.*')? ';';

它不允许静态导入,并且必须做一些事情来跟踪 .* 如果它发生。

【讨论】:

  • 好吧,我不太确定 ReferencedType 规则应该包含什么。我只需要能够像在 Java 中一样导入类型(import com.somepackage.TypeName)或(com.sompackage.*)
  • 查看我的“稍后”添加。
  • 谢谢,但如果导入的包不是有效的,这不会引发编译错误。它将使用任何有效的限定名称进行编译。我只需要引用现有类型。
  • 应该像 Java 编译器那样以任何方式工作吗?如果是这样,则使用限定名称来访问类文件,或者,如果全部参与编译,则限定名称最终必须引用(在其他地方)声明的接口。但导入时界面不会出现字面完整。
【解决方案2】:

您可以绑定自定义 QualifiedNameProvider 以覆盖您的接口导出的名称。 像这样的东西应该使导入引用正常:(import org.first.sample.Demo;)

public class CustomQualifiedNameProvider extends DefaultDeclarativeQualifiedNameProvider {
    @Override
    public QualifiedName getFullyQualifiedName(EObject obj) {
        if (obj instanceof InterfaceDeclaration && obj.eContainer().eContainer() instanceof AbstractElement) {
            QualifiedName packageQualifiedName = getFullyQualifiedName(((AbstractElement)obj.eContainer().eContainer()).getPackageDeclaration());
            return packageQualifiedName.append(((InterfaceDeclaration) obj).getName());
        }
        return super.getFullyQualifiedName(obj);
    }
}

另外,您可以按 Ctrl + Shift + F3 来查看导出对象的名称。

【讨论】:

  • 谢谢!这很有帮助。
【解决方案3】:

其实@laune 是对的。 Xtext 开箱即用地支持这一点。只要模型中引用的类型具有称为“名称”的特征,该类型的完全限定名称就是开箱即用的。我注意到我的 Xtext 语法定义中的错误是包应该包含接口,因此当形成完全限定名称时,xtext 通过将接口的“名称”与包的“名称”组合来构造它(或其父)。 @Fabien 如果 xtext 语法规则不包含“名称”功能,您的答案是正确的。这是构建 fqns 的一种自定义方式,例如,如果我们使用这个:

Package:
 'package' name=ID ';' imports=Import ';' interface=Interface ';'
;

Interface:
 qualifier=Qualifier !id=ID (instead of name=ID)
;

然后我们应该显式地构造 fqn,因为内置支持仅查找“名称”功能。

所以在我的情况下,正确的使用方法是:

 Package:
 'package' name=ID; imports=Import typeDefinition=TypeDefinition;

Import:
 'import' importedNamespace=[TypeDefinition|QualifiedName] ';'
;

TypeDefinition:
  InterfaceDefinition | EnumDefinition ...
;

InterfaceDefinition:
 qualifier=Qualifier !name=ID
;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多