Wednesday, June 12, 2013

Using Xcore in Xtext

With Xtext you can easily create your own textual language. The structure of the language is defined in an Ecore model. This model can be automatically derived from the grammar, which allows quick turnarounds in the beginning. But in the long run, this model becomes an increasingly important API to the language. You want to fix it and make it a first class artifact: You are switching from an inferred Ecore model to an imported one in the grammar.

Traditionally, you use EMF's tree editors to edit Ecore models. That can be cumbersome as the tooling is not the nicest to use. Furthermore, the Ecore model only describes the declarative part. Behavior, such as the body of EOperations or the code for derived EStructuralFeatures has to be woven in either from additional models or directly in the generated code. These and more issues are addressed by Xcore. Xcore allows to specify Ecore models textually, including the behavioral parts and the code generation parameters. Having a single source of information facilitates the maintanance of such a model drastically. Xcore is shipped with EMF.

In the upcoming Eclipse release 4.3 (Kepler) Xcore and Xtext can be used together. Here is a step-by-step example how to do this with Xtext's "Greetings" language:
  1. Create an Xtext project File > New > Project > Xtext Project. The defaults are fine. This will create the usual four projects for your Xtext language in your workspace.
  2. By default, Xcore generates its code to the folder src-gen. The same folder is used by Xtext and will be wiped each time you regenerate the language from the grammar. To avoid loosing data, choose a separate output folder for Xcore: Eclipse/Window > Preferences > Xcore > Compiler > Output Folder > Directory > ./emf-gen

  3. Create a new folder model in the root of org.xtext.example.mydsl and file Greetings.xcore inside that folder. Our Ecore model consists of an EPackage org.xtext.example.mydsl, two EClasses Model and Greetings, a containment EReference greetings and an EAttribute name. In Xcore, this looks like
:

  4. Open the grammar MyDsl.xtext. By default, the Ecore model myDsl is generated from the grammar rules. We want to replace this with the Ecore model specified in the Xcore file:

  5. We have to load the Xcore model in the workflow GenerateMyDsl.mwe2 of the language generator. Add an appropriate loadedResource entry to the language section:

    module org.xtext.example.mydsl.GenerateMyDsl
    ...
    Workflow {
      ...
      component = Generator {
        ...
        language = auto-inject {
          loadedResource =
    "platform:/resource/${projectName}/model/Greetings.xcore"
          uri = ...
    
  6. You have to add a dependency to org.eclipse.emf.xcore in the MANIFEST.MF of the project.
  7. Now generate the language infrastructure Run As > MWE2 Workflow. There should not be any error.
  8. Make sure that all folders will be correctly deployed. Your build.properties file should look like this
:
  9. Launch a new Eclipse workbench Run > Run Configurations > Eclipse Application > Launch Runtime Eclipse and enjoy your language in action.
For the geeky fun of it: As Xcore is itself implemented in Xtext with an imported Ecore model, this lays the foundation to replace Xcore.ecore with Xcore.xcore and thereby bootstraping it.
Sorry, I couldn't resist ;-)