Saturday, November 9, 2013

Default enum literals for Xtext generated EMF models

Xtext allows to easily build fully-fledged editors for domain specific languages (DSL) which are based on the Eclipse Modeling Framework (EMF). While existing Ecore models may be used, Xtext is also able to infer an Ecore model from the Xtext grammar. For complex Ecore models, it should certainly be considered to manage them independently, e.g. with Xcore. However, a few simple tweaks of grammar rules can influence the automatically generated Ecore model quite remarkably (e.g. the inheritance hierarchy) and may delay the point in time where it may be better to manage them independently. This example shows how to influence the generation of enumerators (enums) and default literals with grammar rules.

The code example below assumes that there's a model element with an optional "visibility" attribute of type enum and that the DSL must be able to capture the case where no visibility enum at all was given.

As the default literal of a generated enum is the first literal, an enum rule is added to the grammar which uses, say, "unspecified" for that. However, the user of the DSL editor should simply be able to enter nothing at all instead of "unspecified" which would look odd in the editor. This can be achieved by adding a second rule which returns the aforementioned enum, but only contains the literals allowed for the user. Please note that the order of the enum rules is important for generated models.

MyModelElement:
 // ...
 // user may specify enum or nothing at all
 visibility=Visibility? 
 // ...
;

// rule for the generated Ecore model
enum VisibilityEnum:
 unspecified | // first literal is the default
 public |
 private
;

// rule for the DSL editor
enum Visibility returns VisibilityEnum:
 public | 
 private
;

11 comments:

  1. Hi Dietmar,

    I tried your technique to define the visibility of elements in my DSL. Sadly, the default visibility of MyModelElement is the first literal of the Visibility rule, not the first one of VisibilityEnum. Do you have an idea on how to proceed to get the unspecified visibility when the user hasn't specified a visibility in its source code ?

    Thanks in advance,
    Florence

    ReplyDelete
  2. Hi Florence,

    thanks for the feedback. Please send me your grammar/example to my e-mail under "Contact" so I could have a look at it.

    Cheers
    --Dietmar

    ReplyDelete
    Replies
    1. Hi Dietmar,

      Thanks a lot for your quick answer.

      While building the minimal example to reproduce my problem, I found the important difference between your example and my grammar: the definition order of VisibilityEnum and Visibility. I had defined Visibility first and VisibilityEnum second. If, like you, I define VisibilityEnum first, I obtain the wanted behavior. Do you know why this definition order has an impact ?

      Still, I have a workaround for my problem, thank you for your help !

      Florence

      Delete
    2. Hi Florence,

      great to hear that you solved it! In case of generated models (like here), the generator has to make a decision which enum should be the default, so it just takes the first one encountered in the grammar.

      Dietmar

      Delete
  3. Good blog post. Helped me to introduce a Enum in our DSL

    ReplyDelete
  4. Hi Dietmar,

    I get model files from some environment which uses existing enum say Visibility, used your example and tried to load model files, it fails with error - "The value 'unspecified' is invalid for enum VisibilityEnum". This occurs when the attribute "visibility" is not available in the model file. Do you have any idea on how to ignore grammer check when the attribute is missing or any other alternative to avoid this error ? Thanks in advance.

    Ramapriya

    ReplyDelete
    Replies
    1. Hi Ramapriya,

      If you have an existing model, the easiest way is to change the default enum in the model file or add a default enum. If you have an existing Ecore model, you also don't need the "rule for the generated Ecore model". I hope that helps.

      Cheers
      --Dietmar

      Delete
    2. Hi Dietmar,

      Thanks for your response.
      Yes, I could have used your solution, but the model here is from different application and somehow need to handle extra value "unspecified" in the enum.

      Thanks,
      Ramapriya

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Could you please model this in Enterprise Arcitect for better understanding?

    ReplyDelete
  7. Thanks for the post, very nice way to avoid the default of first literal.

    ReplyDelete