xtext

Extracting parts of a rule for reusability


I'm working on a grammar that is translated to an EMF model. The actual model consists of types with many attributes which make the grammar hard to read. Also some rules contain identical parts which I would like to extract for reusability. I'm looking for a solution that doesn't require changes in the EMF model though.

Consider this very simplified example:

Function1 returns Function:
    'function' name=ID 
    '{' (statements=Statement)* '}';

Function2 returns Function:
    'function2' name=ID 
    '{' (statements=Statement)* '}';

I would like to extract the repeating part and move it to its own rule like this:

Function1 returns Function:
    'function' name=ID;
    Body;

Function2 returns Function:
    'function2' name=ID;
    Body;

Body returns Function:
   '{' (statements=Statement)* '}';

The idea here is, that Function1 and Body are merged into a single instance. Unfortunately that doesn't work though, because only a single unassigned rule is allowed.

I know I could move the body to it's own rule and use assignments, e.g.

Function1:
    'function' name=ID;
    body=Body;

But as far as I understand that would require me to change the EMF model an add a "Body" type and a "body" feature to the function. Is there any other way which avoids changing the model?


Solution

  • If you declare Body as a parser rule fragment, you'll get exactly your desired behavior.

    fragment Body returns Function: ...;
    

    It's still an undocumented feature, but available since 2015 and it is stable.