导入包定义'。'定义xtext语法时的InterfaceDefinition

时间:2014-07-07 12:46:26

标签: java antlr grammar xtext

我正在尝试使用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();
}

你有什么想法吗?

3 个答案:

答案 0 :(得分:0)

当我读到语法时:

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 ('.*')? ';';

它不允许静态导入,必须采取措施来跟踪。*如果发生。

答案 1 :(得分:0)

您可以绑定自定义QualifiedNameProvider以覆盖接口导出的名称。 这样的东西应该导入引用ok :( 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查看导出对象的名称。

答案 2 :(得分:0)

实际上@laune是对的。 Xtext支持开箱即用。只要模型中引用的类型具有名为“name”的功能,该类型的完全限定名称就是开箱即用的。我注意到我的Xtext语法定义错误的是Package应该包含Interface,这样当形成一个完全限定的名称时,xtext通过将Interface的'name'与包的'name'相结合来构建它(或者它的父母)。 @Fabien如果xtext语法规则不包含'name'功能,你的答案是正确的。这是一种构建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
;