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.
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 none 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.