The Grammar Language

The grammar language is the corner stone of Xtext. It is a domain-specific language, carefully designed for the description of textual languages. The main idea is to describe the concrete syntax and how it is mapped to an in-memory model 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 you want to read the whole story.

In order to implment this little language with 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];
  

Martin uses this example throughout his book “Domain-Specific Languages” to implement external and internal DSLs using different technologies. Note, that non of his implmentations is nearly as readable and concise as the description in Xtext’s grammar language above. That is of course because the grammar language is designed to do just that, i.e. it is specific to the domain of language descriptions.