2

During writing validation rules a came across the problem that I need some content from a rule in my grammar which is hierarchically higher than the one I pass to my validationMethod.
I know that I can refer to a "higher" rule with .eContainer but then I don't have a clue how to access the values I want to.

For example I have the following grammar snippet:

rule1:
  name=ID content=rule2
;

rule2:
  <<whatever content>>
;

If I have a normal validationMethod with the argument rule1 then I can access the name via .name but when I give rule2 as an argument and then referring to rule via .eConatiner the .name method does not exist.

Greetings Krzmbrzl

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
Raven
  • 2,951
  • 2
  • 26
  • 42

2 Answers2

2

EObject is the root class of all AST node classes. It comes from the EMF Ecore framework which is used by Xtext to generate the AST implementation. Therefore, the EObject class contains a lot of the tree structure features, e.g., iterating through a tree. The EObject.eContainer() method returns an element of type EObject which actually is the super type of the type of the actual returned object. To get access to methods of the next higher element, you have to cast the eContainers methods result like this:

@Check
public void check(rule2 r2) {
    EObject o = r2.eContainer();
    rule1 r1 = (rule1) o;
    String r1Name = r1.getName();
}

If the type of the parent object is ambigous, you should test whether the actual type is the expected with an instanceof expression:

@Check
public void check(rule2 r2) {
    EObject o = r2.eContainer();
    if (o instanceof rule1) {
        rule1 r1 = (rule1) o;
        String r1Name = r1.getName();
    }
}
Joko
  • 600
  • 3
  • 15
  • Alternatively you can use EcoreUtil2.getContainerOfType(ctx, TypeOfAncestor) – Christian Dietrich May 23 '15 at 21:18
  • First of all a big thank you for your answer and especially for the explanation! But it appears that you do type casting not with the brackets as you did but with using the "as" operator. So the correct cast would look like this: rule1 r1 = (o as rule1). – Raven May 24 '15 at 08:47
  • Yes, you're right, iff you use Xtend as programming language. The language I used in the examples was Java, so the syntax was correct ;). But if you're using Xtend it's o as rule1. – Joko May 24 '15 at 09:06
  • Do you know how to check the type of the object in Xtend? I couldn't find something like instanceof – Raven May 24 '15 at 15:03
1

Xtend provide the same instanceof-expression like Java. But if the object to be checked definetly can have more then a few types, you can use Xtends really powerful switch expression. It supports so called type guards. You can switch over any object and instead of case value: guards simply write the a concrete type:

switch (anyAbstractTypeObject) {
    ConcreteSubtypeA: {...}
    ConcreteSubtypeB: {...}
}

This is an elegant shorthand if-instanceof-eleseif-... in Xtend.

Joko
  • 600
  • 3
  • 15