viliam ganz - domain specific languages
TRANSCRIPT
ahead of one’s time
Domain Specific Languages
Groovy, Antlr
“Computer programming language of limited expressivenes focused on a particular domain”
Specialized to solve problems within that domain
Easy to understand
Executable by computer
Not necessarily a completely new language(Internal/External)
HTML, CSS, RegEx, XSLT, Spring xml configs, SQL...
What is Domain specific language?
DSL goals
To be more expressive in its domain – more powerful
Include domain experts in application development
Extraction of bussines logic – separate lifecycle
Easier work in its domain
Let's think about Turtle● It can move in 2 dimensional space● It can draw paths● We can turn it, move and reset it
DSL Example – problem
Requirements & Goals
We want to move the turtle by DSL
We want to execute the DSL actions one by one
Comparison between Groovy and Antlr
DSL Example
● 4 actions
– Parametrized
● excluding reset
– changing state of the turtle
– changing state of the world
● Sequential evaluation
turn leftmove 5turn rightmove 30pen downturn rightmove 5turn rightmove 3pen upreset
DSL Example – Semantic model
Representation of the same subject DSL describes
DSL populates the semantic model
Covers semantic aspects of the problem
Not depending on the DSL
In this case quite simple:
Action Turtle World
Execution class model
<<interface>>
Executor
GroovyExecutor AntlrExecutor
<<interface>>
Action
TurnLeftAction
ResetAction
PenUpAction
PenDownAction
MoveAction
TurnRightAction
DSL in Groovy
GroovyShell shell = new GroovyShell();
Script script = shell.parse(config);
script.run();
…..aand we are done, right?
DSL in Groovy
...not yet
Let's see how its evaluated
turn left
move 5
pen down
turn right
reset
●
●
●
turn(left) // left is a var
move(5) // 5 is number
pen(down) // down is var
turn(right) // right is var
reset // reset is var
DSL in Groovy – Binding methods
●
● Binding binding = new Binding()
● binding.setVariable("move", new Closure<Object>(null) {
– @Override
– public Object call(Object... args) {
● turtleActions.add(new MoveAction((Integer) args[0]));
● return null;
– }
● });
DSL in Groovy – Binding variables
binding.setVariable("left", TurnDirection.LEFT);
binding.setVariable("right", TurnDirection.RIGHT);
binding.setVariable("down", PenState.DOWN);
binding.setVariable("up", PenState.UP);
DSL in Groovy – Binding reset
●
● Binding binding = new Binding() {
@Override
– public Object getVariable(String name) {
● if ("reset".equals(name)) {
– turtleActions.add(new ResetAction());– return null;
● }● return super.getVariable(name);
– }
● };
DSL in Groovy – Security, restrictions & tweaks
Compilation customization
● Import customization
– Regular, static, star
● AST transformation customization
– Rewriting methods...
● SecureASTCustomizer
– Allow/disallow – closures, imports, method definitions, tokens, constant types...
Security manager
● Restricting permissions
Antlr
●
● ANTLR (ANother Tool for Language Recognition)
● Powerful parser generator for reading, processing, executing, or translating structured text or binary files.
● From a grammar, ANTLR generates a parser that can build and walk parse trees.
Antlr – Principles
DSL in Antlr – Grammar - Base
●
● grammar Turtle;●
● execution● : action+● ;
● action● : turnAction● | moveAction● | penAction● | resetAction● ;
DSL in Antlr – Grammar - Actions
–
– turnAction
● : TURN direction;
– direction
● : LEFT● | RIGHT● ;
– moveAction
● : MOVE NUMBER● ;
–
–
–
– penAction
● : PEN penState;
penState
● : UP● | DOWN● ;
– resetAction
– : RESET
– ;
DSL in Antlr – Grammar - Tokens
●
● TURN : 'turn';● MOVE : 'move';● RESET : 'reset';● LEFT : 'left';● RIGHT : 'right';● PEN : 'pen';● UP : 'up';● DOWN : 'down';● NUMBER : [1-9][0-9]*;● WS● : ( ' ' | '\t' | '\r' | '\n' )+ -> skip● ;
DSL in Antlr – Grammar – Parse tree
DSL in Antlr
Antlr generates:
● Token list
● TurtleLexer
● TurtleParser
● TurtleListener – SAX approach
● TurtleBaseListener
● TurtleVisitor – DOM approach
● TurtleBaseVistor
DSL in Antlr – Visitor
TurtleActionBuildingVisitor extends
TurtleBaseVisitor<List<TurtleAction>> {
@Override
public List<TurtleAction> visitResetAction(
@NotNull ResetActionContext ctx) {
return toList(new ResetAction());
}
...
}
DSL in Antlr – Visitor
– public List<TurtleAction> visitPenAction(
– @NotNull PenActionContext ctx) {● PenStateContext penStateContext = ctx.penState();
● If (penStateContext.UP() != null) {
– return toList(new PenUpAction());● }
● if (penStateContext.DOWN() != null) {
– return toList(new PenDownAction());● }
● throw new IllegalStateException("Unknown pen state:" + penStateContext.getText());
– }
DSL in Antlr – Executor
●
● ANTLRInputStream input = new ANTLRInputStream(dsl);
●
● TurtleLexer turtleLexer = new TurtleLexer(input);
●
● CommonTokenStream tokenStream = new
– CommonTokenStream(turtleLexer);
●
● TurtleParser turtleParser = new TurtleParser(tokenStream);
●
DSL in Antlr – Executor
●
● ExecutionContext executionContext =
– turtleParser.execution();
●
● TurtleActionBuildingVisitor turtleActionBuildingVisitor =
– new TurtleActionBuildingVisitor();
●
● List<TurtleAction> actionList =
● turtleActionBuildingVisitor.visit(executionContext);
DSL in action
Which tool is better?
Pros & Cons
Groovy
✔ Lot of goodness out of the box
✔ Expressions evaluation
✔ GPL fallback
✔ Interoperability with Java
✔ Built-in intepretation
✗ Security & restricting
✗ Hidden complexity
✗ Syntax restrictions
Antrl
✔ Encourages separation
✔ Syntax validation
✔ Tooling
✔ Left Recursion support
✔ No Syntax restrictions
✗ Grammar complexity
✗ Visitor restrictions
✗ Custom interpretation
Useful references
http://www.slideshare.net/predo/embedding-groovy-in-a-java-application
http://www.slideshare.net/glaforge/going-to-mars-with-groovy-domainspecific-languages
http://www.antlr.org/
Fowler, M. 2010. Domain-Specific Languages
ahead of one’s time
Thank you for your attention
For more information, please contact me [email protected]