The Grammar Language

The grammar language is the corner stone of Xtext and is defined in itself. Actually it is a DSL to create DSLs, so what would be more helpful than developing the Xtext language with Xtext?

The grammar language is a domain-specific language, carefully designed for the description of textual languages based on LL(*)-Parsing that is like ANTLR3's parsing strategy. The main idea is to describe the concrete syntax and how an EMF-based in-memory model is created during parsing.

A first example

To get an idea of how it works we’ll start by implementing a simple example introduced by Martin Fowler. It’s mainly about describing state machines used as the (un)lock mechanism of secret compartments. People who have secret compartments control their access in a very old-school way, e.g. by opening the door first and turning on the light afterwards. Then the secret compartment, for instance a panel, opens up. One of those state machines could look like this:

events
  doorClosed  D1CL
  drawOpened  D2OP
  lightOn     L1ON
  doorOpened  D1OP
  panelClosed PNCL
end
 
resetEvents
  doorOpened
end
 
commands
  unlockPanel PNUL
  lockPanel   PNLK
  lockDoor    D1LK
  unlockDoor  D1UL
end
 
state idle
  actions {unlockDoor lockPanel}
  doorClosed => active
end
 
state active
  drawOpened => waitingForLight
  lightOn    => waitingForDraw
end
 
state waitingForLight
  lightOn => unlockedPanel
end
 
state waitingForDraw
  drawOpened => unlockedPanel
end
 
state unlockedPanel
  actions {unlockPanel lockDoor}
  panelClosed => idle
end

So, we have a bunch of declared events, commands and states. Within states there are references to declared actions, which should be executed when entering such a state. Also there are transitions consisting of a reference to an event and a state. Please read Martin's description if it is not clear enough.

In order to get a complete IDE for this little language from Xtext, you need to write the following grammar:

grammar my.pack.SecretCompartments 
   with org.eclipse.xtext.common.Terminals

generate secretcompartment "http://www.eclipse.org/secretcompartment"
 
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];