Xtext @ Profict Summer Camp

Post on 06-May-2015

1.113 views 1 download

Tags:

Transcript of Xtext @ Profict Summer Camp

Domain-Specific Languages with

Sven Efftinge

copyright 2008 by itemis AG

Kiel, Germany

Peter

Dennis

Jan

“... won’t talk about

model-driven stuff”

You’re lucky!

No UML!

No MDA!

No meta meta meta meta ...

taken from Martin Fowler’s upcoming Book on DSLs

Hands-on a

concrete example

You’re working for a company specialized on systems for

secret compartments

Your customer:

Mrs. H she likes secrets

To open the secret compartment, she has to

To open the secret compartment, she has to

close the door,

To open the secret compartment, she has to

close the door,

open the second draw in her chest,

turn her bedside light on.

To open the secret compartment, she has to

close the door,

open the second draw in her chest,

events doorClosed drawOpened lightOn doorOpened panelClosedend

resetEvents doorOpenedend

commands unlockPanel lockPanel lockDoor unlockDoor end

state idle actions {unlockDoor lockPanel} doorClosed => activeend

state active drawOpened => waitingForLight lightOn => waitingForDrawend

state waitingForLight lightOn => unlockedPanelend

state waitingForDraw drawOpened => unlockedPanelend

state unlockedPanel actions {unlockPanel lockDoor} panelClosed => idleend

events doorClosed drawOpened lightOn doorOpened panelClosedend

resetEvents doorOpenedend

commands unlockPanel lockPanel lockDoor unlockDoor end

state idle actions {unlockDoor lockPanel} doorClosed => activeend

state active drawOpened => waitingForLight lightOn => waitingForDrawend

state waitingForLight lightOn => unlockedPanelend

state waitingForDraw drawOpened => unlockedPanelend

state unlockedPanel actions {unlockPanel lockDoor} panelClosed => idleend

event :doorClosedevent :drawOpenedevent :lightOnevent :doorOpenedevent :panelClosed

command :unlockPanelcommand :lockPanelcommand :lockDoorcommand :unlockDoor

resetEvents :doorOpened

state :idle do actions :unlockDoor, :lockPanel transitions :doorClosed => :activeend

state :active do transitions :drawOpened => :waitingForLight, :lightOn => :waitingForDrawend

state :waitingForLight do transitions :lightOn => :unlockedPanelend

state :waitingForDraw do transitions :drawOpened => :unlockedPanelend

state :unlockedPanel do actions :unlockPanel, :lockDoor transitions :panelClosed => :idleend

External DSL Internal DSL

events doorClosed drawOpened lightOn doorOpened panelClosedend

resetEvents doorOpenedend

commands unlockPanel lockPanel lockDoor unlockDoor end

state idle actions {unlockDoor lockPanel} doorClosed => activeend

state active drawOpened => waitingForLight lightOn => waitingForDrawend

state waitingForLight lightOn => unlockedPanelend

state waitingForDraw drawOpened => unlockedPanelend

state unlockedPanel actions {unlockPanel lockDoor} panelClosed => idleend

event :doorClosedevent :drawOpenedevent :lightOnevent :doorOpenedevent :panelClosed

command :unlockPanelcommand :lockPanelcommand :lockDoorcommand :unlockDoor

resetEvents :doorOpened

state :idle do actions :unlockDoor, :lockPanel transitions :doorClosed => :activeend

state :active do transitions :drawOpened => :waitingForLight, :lightOn => :waitingForDrawend

state :waitingForLight do transitions :lightOn => :unlockedPanelend

state :waitingForDraw do transitions :drawOpened => :unlockedPanelend

state :unlockedPanel do actions :unlockPanel, :lockDoor transitions :panelClosed => :idleend

External DSL Internal DSL

On top of external DSLs

no compromises

On top of external DSLs

domain-specific static analysis

no compromises

On top of external DSLs

domain-specific static analysisgraphical views

no compromises

On top of external DSLs

domain-specific static analysisgraphical views

no compromises

closed scope

Implementing anexternal DSLis complicated

... to develop DSLs?

Why not using a DSL ...

Statemachine : 'events' (events+=Event)+ 'end' 'resetEvents' (resetEvents+=[Event])+ 'end' 'commands' (commands+=Command)+ 'end' (states+=State)+;Event : name=ID;Command : name=ID;State : 'state' name=ID ('actions' '{' (actions+=[Command])+ '}')? (transitions+=Transition)* 'end';Transition : event=[Event] '=>' state=[State];

Statemachine : 'events' (events+=Event)+ 'end' 'resetEvents' (resetEvents+=[Event])+ 'end' 'commands' (commands+=Command)+ 'end' (states+=State)+;Event : name=ID;Command : name=ID;State : 'state' name=ID ('actions' '{' (actions+=[Command])+ '}')? (transitions+=Transition)* 'end';Transition : event=[Event] '=>' state=[State];

starts with keyword ‘events’

Statemachine : 'events' (events+=Event)+ 'end' 'resetEvents' (resetEvents+=[Event])+ 'end' 'commands' (commands+=Command)+ 'end' (states+=State)+;Event : name=ID;Command : name=ID;State : 'state' name=ID ('actions' '{' (actions+=[Command])+ '}')? (transitions+=Transition)* 'end';Transition : event=[Event] '=>' state=[State];

followed by at least one definition of Event

which is defined here and consists of just one

identifier (ID)

Statemachine : 'events' (events+=Event)+ 'end' 'resetEvents' (resetEvents+=[Event])+ 'end' 'commands' (commands+=Command)+ 'end' (states+=State)+;Event : name=ID;Command : name=ID;State : 'state' name=ID ('actions' '{' (actions+=[Command])+ '}')? (transitions+=Transition)* 'end';Transition : event=[Event] '=>' state=[State];

this is a cross reference, referencing Events

declared in the previous section.

Statemachine : 'events' (events+=Event)+ 'end' 'resetEvents' (resetEvents+=[Event])+ 'end' 'commands' (commands+=Command)+ 'end' (states+=State)+;Event : name=ID;Command : name=ID;State : 'state' name=ID ('actions' '{' (actions+=[Command])+ '}')? (transitions+=Transition)* 'end';Transition : event=[Event] '=>' state=[State];

commands are very similar to events

Statemachine : 'events' (events+=Event)+ 'end' 'resetEvents' (resetEvents+=[Event])+ 'end' 'commands' (commands+=Command)+ 'end' (states+=State)+;Event : name=ID;Command : name=ID;State : 'state' name=ID ('actions' '{' (actions+=[Command])+ '}')? (transitions+=Transition)* 'end';Transition : event=[Event] '=>' state=[State];

States have a name (ID)

Statemachine : 'events' (events+=Event)+ 'end' 'resetEvents' (resetEvents+=[Event])+ 'end' 'commands' (commands+=Command)+ 'end' (states+=State)+;Event : name=ID;Command : name=ID;State : 'state' name=ID ('actions' '{' (actions+=[Command])+ '}')? (transitions+=Transition)* 'end';Transition : event=[Event] '=>' state=[State];

States have a name (ID)

optional action block

Statemachine : 'events' (events+=Event)+ 'end' 'resetEvents' (resetEvents+=[Event])+ 'end' 'commands' (commands+=Command)+ 'end' (states+=State)+;Event : name=ID;Command : name=ID;State : 'state' name=ID ('actions' '{' (actions+=[Command])+ '}')? (transitions+=Transition)* 'end';Transition : event=[Event] '=>' state=[State];

States have a name (ID)

optional action block

any number of Transitions

This was the example DSL implemented in

So what do we get from such a description?

Antlr based Parser

Eclipse based Editor

Antlr based Parser

Statemachine

name:StringCommand

name:StringState

name:StringEvent

Transition

** *

*

*

stateseventscommands

actions

stateevent

resetStates

EMF based Semantic Model

Eclipse based Editor

Antlr based Parser

Demo

oaw.itemis.comThank you very much!

the eclipse distro can be downloaded from

http://oaw.itemis.com