Showing posts with label DSLs. Show all posts
Showing posts with label DSLs. Show all posts

Friday, June 03, 2011

5 simple steps to Fowler's DSL with Xtext 2.0

You might have read (about) the book Domain-Specific Languages written by Martin Fowler. As the name suggests it is about these little useful programming languages you can built very easily with Xtext. Unfortunately Martin decided to use more low level technology in order to explain how to implement such a language. So if you don't want to spend hours of hours dealing with complex low level technology just to end up with a parser but nothing else, here are the five steps needed to get a fully working implementation for the DSL he uses throughout the book (Mrs Grant's Controller). It doesn't get simpler.

Below you can find a detailed description. For those of you who prefer to just sit and watch, here are three screencasts I've recorded around this example.



Creating the project and defining the language



Defining the code generator and see its integration



Features, Features, Features



1) Download Eclipse and Install Xtext

For many people this is the hardest part. But believe me things have improved and it is now quite easy to get a working Eclipse distribution including the latest milestone of Xtext 2.0. :-)

Download an Eclipse Classic distribution for your platform from here :  
    http://www.eclipse.org/downloads/index-developer.php

Unzip and start Eclipse, choose Help -> Install New Software... and use the update site
    http://download.itemis.com/updates/milestones
in order to install the Xtext SDK feature

2) Use the Xtext project wizard

Select New -> Project..., and within the dialog choose Xtext Project. You can stick with the defaults on the next page, but make sure you choose the Experimental Features configuration in order to get the latest and greatest features, such as rename refactoring.

You should use the experimental features

3) Define the grammar

The Xtext grammar file is automatically opened. Just copy and paste the following grammar definition for Martin's statemachine DSL in.


grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate statemachine "http://www.xtext.org/example/secretcompartments/Statemachine"

Statemachine :
     {Statemachine}
     ('events' 
          events+=Event+ 
     'end')?
     ('resetEvents' 
          resetEvents+=[Event]+ 
     'end')?
     ('commands' 
          commands+=Command+ 
     'end')?
     states+=State*
;

Event:
     name=ID code=ID
;

Command:
     name=ID code=ID
;

State:
     'state' name=ID
          ('actions' '{' actions+=[Command]+ '}')?
          transitions+=Transition*
     'end'
;

Transition:
     event=[Event] '=>' state=[State]
;


4) Run the generator

Now you need to run the generator which creates the parser and a couple of other parts of the language infrastructure. To do so right click into the editor and choose 
   Run As -> Generate Xtext Artifacts

5) Define the code generator

A DSL isn't worth much if you are not able to execute it somehow. Xtext has already provided you with a stub for a code generator written in our cool new template language Xtend (Xtend as well as the grammar language are also implemented with Xtext of course). 
To get a working implementation which produces a Java implementation of a defined statemachine, just copy the following into the file MyDslGenerator.xtend

package org.xtext.example.mydsl.generator

import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.IGenerator
import org.eclipse.xtext.generator.IFileSystemAccess
import org.xtext.example.mydsl.statemachine.Statemachine
import org.xtext.example.mydsl.statemachine.Event
import org.xtext.example.mydsl.statemachine.Command
import org.xtext.example.mydsl.statemachine.State

class MyDslGenerator implements IGenerator {
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
fsa.generateFile(resource.className+".java", toJavaCode(resource.contents.head as Statemachine))
}
def className(Resource res) {
var name = res.URI.lastSegment
name.substring(0, name.indexOf('.'))
}
def toJavaCode(Statemachine sm) '''
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class «sm.eResource.className» {
public static void main(String[] args) {
new «sm.eResource.className»().run();
}
«FOR c : sm.commands»
«c.declareCommand»
«ENDFOR»
protected void run() {
boolean executeActions = true;
String currentState = "«sm.states.head.name»";
String lastEvent = null;
while (true) {
«FOR state : sm.states»
«state.generateCode»
«ENDFOR»
«FOR resetEvent : sm.resetEvents»
if ("«resetEvent.name»".equals(lastEvent)) {
System.out.println("Resetting state machine.");
currentState = "«sm.states.head.name»";
executeActions = true;
}
«ENDFOR»
}
}
private String receiveEvent() {
System.out.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
return br.readLine();
} catch (IOException ioe) {
System.out.println("Problem reading input");
return "";
}
}
}
'''
def declareCommand(Command command) '''
protected void do«command.name.toFirstUpper»() {
System.out.println("Executing command «command.name» («command.code»)");
}
'''
def generateCode(State state) '''
if (currentState.equals("«state.name»")) {
if (executeActions) {
«FOR c : state.actions»
do«c.name.toFirstUpper»();
«ENDFOR»
executeActions = false;
}
System.out.println("Your are now in state '«state.name»'. Possible events are [«
state.transitions.map(t | t.event.name).join(', '].");
lastEvent = receiveEvent();
«FOR t : state.transitions»
if ("«t.event.name»".equals(lastEvent)) {
currentState = "«t.state.name»";
executeActions = true;
}
«ENDFOR»
}
'''
}

Thursday, November 12, 2009

Xtext in the automotive industry

At this year's Eclipse Summit Europe there was a very nice Xtext-related talk given by Sebastian Benz who is working at BMW Car IT.
The talk was about how they used Xtext in order to develop a textual syntax and corresponding IDE for the AUTOSAR standard. The name of the project is ARText and it is freely available to all AUTOSAR members as part of the Artop project.

One of the biggest challenges when implementing the AUTOSAR standard is to create scalable solutions. AUTOSAR projects might become very, very big and in order to work with such huge projects the tools need to perform very well. In the modeling world people usually strife for repository-based (i.e. database-based) solutions as soon as projects get really big. However, the folks at BMW Car IT wanted to develop AUTOSAR projects in a traditional text-based manner and given all the good experiences with tools like JDT or IntelliJ, it's clear that text-based IDEs can scale very well.

In order to implement the language they first had tried the old Xtext version from oAW, which was way too slow. Then, later, when the new TMF Xtext came around they gave it another try and saw that the performance had been improved significantly. Sebastian showed the following slide in his talk:
After that he explained how they have solved a couple of other problems, such as supporting different releases of the standard or making the language extendable. All the solutions looked very nice, they must have some very skilled people at BMW Car IT.

He compared working with the state-of-the-art commercial graphical modeling tool (What's the name of it?) and the ARText IDE and found that the use of ARText reduces development time by about 40%.

In the end there was this nice summary slide I don't want to withhold:

It was a very nice talk and of course a pleasure to see that Xtext is used by such smart people in such an interesting environment. And even better it seems that they've had as much fun using Xtext as we had and still have when developing (and using) it. :-)

Btw.: If you have other interesting applications of Xtext or Eclipse Modeling in general, please contact me. (Even if you don't want me to blog about it ;-))

Edited: Sebastian has recently posted a screencast showing ARText in action:

Thursday, June 26, 2008