Search code examples
eclipseenumsxtextcross-reference

Xtext cross-reference to constants of Enum


I try to write new grammar and I wrote something like Enum in Java, that enables for Var (a type in my grammar) to be a set of predefined constants.

I want it to recognize the constants that include to this Var, but I didn't find a way how to do it (although I try to read the book "Implementing Domain-Specific Languages with Xtext and Xtend", and searched a lot on the internet)

So I made a little example on the Domainmodel grammar:

Domainmodel:
    (elements+=AbstractElement)*;

PackageDeclaration:
    'package' name=QualifiedName '{'
    (elements+=AbstractElement)*
    '}';

AbstractElement:
    PackageDeclaration | Type | Import;

QualifiedName:
    ID ('.' ID)*;

Import:
    'import' importedNamespace=QualifiedNameWithWildcard;

QualifiedNameWithWildcard:
    QualifiedName '.*'?;

Type:
    DataType | Entity | Var;

DataType:
    'datatype' name=ID;

Entity:
    'entity' name=ID ('extends' superType=[Entity|QualifiedName])? '{'
    (features+=Feature)*
    '}';

Feature:
    (many?='many')? name=ID ':' type=[VarDecl |QualifiedName];

Var:
    kind='Var' var=VarDecl;

VarDecl:
    type=VarType name=SimpleVarID;

SimpleVarID:
    ID ('[' INT ']')*;

VarType:
    name='boolean'
    | '{' const+=TypeConstant (',' const+=TypeConstant)* '}';

TypeConstant:
    ID | INT | 'FALSE' | 'TRUE';

So, the example is:

Var  {LEFT,RIGHT} move

entity C {
    content: move
    side: LEFT //ERROR: couldn't resolve reference to VarDecl 'LEFT'
}

I know that LEFT isn't VarDecl, it's ID, but I don't know how to do it different. What I need to do so that LEFT would be recognize like something that include to move?
comment: in my real grammar I actually try to do move==LEFT (boolean operator) and it's not recognize LEFT as constant of move (the same error appears) .

Thanks!


Solution

  • i am not sure if i get you but here are some hints

    first you can only reference the things you allow in the grammar

    QualifiedName:
        TypeConstantLiteral ('.' TypeConstantLiteral)*;
    
    VarType:
        name='boolean'
        | '{' const+=TypeConstant (',' const+=TypeConstant)* '}';
    
    Feature:
        (many?='many')? name=ID ':' type=[Referrable | QualifiedName];    
    
    Referrable:
        VarDecl | TypeConstant
    ;
    
    TypeConstant:
        name=TypeConstantLiteral;
    
    TypeConstantLiteral:ID | INT | 'FALSE' | 'TRUE';    
    

    then you have to care about naming

    class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {
    
        override bindIQualifiedNameProvider() {
            SimpleNameProvider
        }
    
    }
    

    (depending in your usecase you may use your own subclass of DefaultDeclarativeNameProvider instead

    please note: this does not cover typesystem / scoping / validation yet