-
1.
Building DSLs with
Eclipse
Peter Friese, itemis
@peterfriese
@xtext
(c) 2009 Peter Friese. Distributed under the EDL V1.0 - http://www.eclipse.org/org/documents/edl-v10.php
More info: http://www.peterfriese.de / http://www.itemis.com
-
2.
What is a DSL?
-
3.
Domain
-
4.
Language
-
5.
Suppose...
-
6.
You’d want to core an apple...
-
7.
... for your kids.
-
8.
?
Right tool for the job?
-
9.
Your trusty swiss army knife!
-
10.
Because you can use it for other stuff, too.
E.g., opening a bottle of wine.
-
11.
Suppose...
-
12.
You’d want to core a few more apples...
-
13.
... for an apple cake.
-
14.
Still the best tool for the job?
-
15.
Better use this one.
-
16.
and this one:
-
17.
BUT
avoid the unitasker!
-
18.
BUT
avoid the unitasker!
-
19.
... a DSL is ...
-
20.
A specific tool
for a specific job
-
21.
A specific tool
for a specific job
-
22.
Samples for DSLs
-
23.
SQL
-
24.
select name, salary
from employees
where salary > 2000
order by salary
-
25.
ANT
-
26.
<project name="MyProject" default="dist" basedir=".">
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<target name="init">
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile">
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/MyProject.jar"
basedir="${build}"/>
</target>
<target name="clean">
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>
-
27.
<project name="MyProject" default="dist" basedir=".">
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<target name="init">
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile">
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/MyProject.jar"
basedir="${build}"/>
</target>
<target name="clean">
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>
-
28.
External
or
Internal
-
29.
Internal DSLs
-
30.
Mailer.mail()
.to(“you@gmail.com”)
.from(“me@gmail.com”)
.subject(“Writing DSLs in Java”)
.body(“...”)
.send();
-
31.
Simple
-
32.
Limited
-
33.
External DSLs
-
34.
1)Create ANTLR grammar
2)Generate lexer / parser
3)Parser will create parse tree
4)Transform parse tree to semantic model
5)Iterate model
6)Pass model element(s) to template
-
35.
Flexible
-
36.
Adaptable
-
37.
Complicated
-
38.
Why not use a DSL...
... for building DSLs?
-
39.
Demo 1
-
40.
@SuppressWarnings("serial")
@Entity
@Table(name = "CUSTOMER_INFO")
public class CustomerInfo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idSeq")
@SequenceGenerator(name = "idSeq", sequenceName = "CUST_SEQ", allocationSize = 1)
@Column(name = "CUST_ID", nullable = false)
private String customerId;
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getCustomerId() {
return customerId;
}
@Column(name = "EMAIL", nullable = false, length = 128)
private String emailAddress;
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
String oldValue = emailAddress;
this.emailAddress = emailAddress;
firePropertyChangedEvent("emailAddress", oldValue, this.emailAddress);
}
-
41.
@SuppressWarnings("serial")
@Entity
@Table(name = "CUSTOMER_INFO")
public class CustomerInfo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idSeq")
@SequenceGenerator(name = "idSeq", sequenceName = "CUST_SEQ", allocationSize = 1)
@Column(name = "CUST_ID", nullable = false)
private String customerId;
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getCustomerId() {
return customerId;
}
@Column(name = "EMAIL", nullable = false, length = 128)
private String emailAddress;
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
String oldValue = emailAddress;
this.emailAddress = emailAddress;
firePropertyChangedEvent("emailAddress", oldValue, this.emailAddress);
}
-
42.
entity CustomerInfo
(id=CUST_ID, sequenceName=CUST_SEQ)
{
String emailAddress (notNull, length = 128)
}
-
43.
entity CustomerInfo
(id=CUST_ID, sequenceName=CUST_SEQ)
{
String emailAddress (notNull, length = 128)
}
Bean
DAO
(POJO)
-
44.
Underlying Technology
-
45.
Model
G
ra
m
m
ar
-
46.
ar
Model
m
m
ra
G
Generator
-
47.
ar
Model
m
m
ra
G
Generator
Runtime
Superclass
Subclass Class
LL(*) Parser ECore meta model Editor
-
48.
ar
Model
m
m
ra
G
Generator
Runtime
Superclass
Subclass Class
LL(*) Parser ECore meta model Editor
-
49.
Grammar (similar to EBNF)
grammar org.xtext.example.Entity with org.eclipse.xtext.common.Terminals
generate entity "http://www.xtext.org/example/Entity"
Model:
(types+=Type)*;
Type:
TypeDef | Entity;
TypeDef:
"typedef" name=ID ("mapsto" mappedType=JAVAID)?;
JAVAID:
name=ID("." ID)*;
Entity:
"entity" name=ID ("extends" superEntity=[Entity])?
"{"
(attributes+=Attribute)*
"}";
Attribute:
type=[Type] (many?="*")? name=ID;
-
50.
grammar org.xtext.example.Entity
with org.eclipse.xtext.common.Terminals Meta model inference
generate entity
"http://www.xtext.org/example/Entity"
entity
Model:
(types+=Type)*;
Model
Type:
TypeDef | Entity;
types
TypeDef: *
Type
"typedef" name=ID
name: EString
("mapsto" mappedType=JAVAID)?;
superEntity
JAVAID:
name=ID("." ID)*; TypeDef Entity
Entity: mappedType attributes
"entity" name=ID
Attribute
("extends" superEntity=[Entity])? JAVAID
name: EString
"{" name: EString
many: EBoolean
(attributes+=Attribute)*
"}"; type
Attribute:
type=[Type] (many?="*")? name=ID;
-
51.
grammar org.xtext.example.Entity
with org.eclipse.xtext.common.Terminals Meta model inference
generate entity
"http://www.xtext.org/example/Entity"
entity Rules -> Classes
Model:
(types+=Type)*;
Model
Type:
TypeDef | Entity;
types
TypeDef: *
Type
"typedef" name=ID
name: EString
("mapsto" mappedType=JAVAID)?;
superEntity
JAVAID:
name=ID("." ID)*; TypeDef Entity
Entity: mappedType attributes
"entity" name=ID
Attribute
("extends" superEntity=[Entity])? JAVAID
name: EString
"{" name: EString
many: EBoolean
(attributes+=Attribute)*
"}"; type
Attribute:
type=[Type] (many?="*")? name=ID;
-
52.
grammar org.xtext.example.Entity
with org.eclipse.xtext.common.Terminals Meta model inference
generate entity
"http://www.xtext.org/example/Entity"
entity
Model:
(types+=Type)*;
Model
Type:
TypeDef | Entity;
types
TypeDef: *
Type
"typedef" name=ID
name: EString
("mapsto" mappedType=JAVAID)?;
superEntity
JAVAID:
name=ID("." ID)*; TypeDef Entity
Entity: mappedType attributes
"entity" name=ID
Attribute
("extends" superEntity=[Entity])? JAVAID
name: EString
"{" name: EString
many: EBoolean
(attributes+=Attribute)*
"}"; type
Attribute:
type=[Type] (many?="*")? name=ID;
-
53.
grammar org.xtext.example.Entity
with org.eclipse.xtext.common.Terminals Meta model inference
generate entity
"http://www.xtext.org/example/Entity"
entity Alternatives -> Hierarchy
Model:
(types+=Type)*;
Model
Type:
TypeDef | Entity;
types
TypeDef: *
Type
"typedef" name=ID
name: EString
("mapsto" mappedType=JAVAID)?;
superEntity
JAVAID:
name=ID("." ID)*; TypeDef Entity
Entity: mappedType attributes
"entity" name=ID
Attribute
("extends" superEntity=[Entity])? JAVAID
name: EString
"{" name: EString
many: EBoolean
(attributes+=Attribute)*
"}"; type
Attribute:
type=[Type] (many?="*")? name=ID;
-
54.
grammar org.xtext.example.Entity
with org.eclipse.xtext.common.Terminals Meta model inference
generate entity
"http://www.xtext.org/example/Entity"
entity
Model:
(types+=Type)*;
Model
Type:
TypeDef | Entity;
types
TypeDef: *
Type
"typedef" name=ID
name: EString
("mapsto" mappedType=JAVAID)?;
superEntity
JAVAID:
name=ID("." ID)*; TypeDef Entity
Entity: mappedType attributes
"entity" name=ID
Attribute
("extends" superEntity=[Entity])? JAVAID
name: EString
"{" name: EString
many: EBoolean
(attributes+=Attribute)*
"}"; type
Attribute:
type=[Type] (many?="*")? name=ID;
-
55.
grammar org.xtext.example.Entity
with org.eclipse.xtext.common.Terminals Meta model inference
generate entity
"http://www.xtext.org/example/Entity"
entity Assignment -> Feature
Model:
(types+=Type)*;
Model
Type:
TypeDef | Entity;
types
TypeDef: *
Type
"typedef" name=ID
name: EString
("mapsto" mappedType=JAVAID)?;
superEntity
JAVAID:
name=ID("." ID)*; TypeDef Entity
Entity: mappedType attributes
"entity" name=ID
Attribute
("extends" superEntity=[Entity])? JAVAID
name: EString
"{" name: EString
many: EBoolean
(attributes+=Attribute)*
"}"; type
Attribute:
type=[Type] (many?="*")? name=ID;
-
56.
grammar org.xtext.example.Entity
with org.eclipse.xtext.common.Terminals Meta model inference
generate entity
"http://www.xtext.org/example/Entity"
entity
Model:
(types+=Type)*;
Model
Type:
TypeDef | Entity;
types
TypeDef: *
Type
"typedef" name=ID
name: EString
("mapsto" mappedType=JAVAID)?;
superEntity
JAVAID:
name=ID("." ID)*; TypeDef Entity
Entity: mappedType attributes
"entity" name=ID
Attribute
("extends" superEntity=[Entity])? JAVAID
name: EString
"{" name: EString
many: EBoolean
(attributes+=Attribute)*
"}"; type
Attribute:
type=[Type] (many?="*")? name=ID;
-
57.
Demo 2
-
58.
Poll "Simple poll"
question "What's your name?" name
question "How do you feel today?" howareyou
() "Fine" fine
() "Great" great
() "Bad" bad
() "Not too bad" not2bad
question "What's your favourite food?" food
[] "Pizza" pizza
[] "Pasta" pasta
[] "Sushi" sushi
[] "Mexican" mexican
-
59.
Pimp My Write
-
60.
Tooltips
Scoping
Outline
Label Provider
Validation Hyperlinking / Navigation
AST
Code Formatting
Content Assist
Folding
Quick Fix
Datatype Converter
Parser
Syntax Highlighting
-
61.
Tooltips
Scoping
Outline
Hyperlinking / Navigation
AST
Code Formatting
Content Assist
Folding
Quick Fix
Datatype Converter
Parser
Syntax Highlighting
-
62.
Tooltips
Scoping
Outline
Label Provider
Validation Hyperlinking / Navigation
AST
Code Formatting
Content Assist
Folding
Quick Fix
Datatype Converter
Parser
Syntax Highlighting
-
63.
Conclusion
-
64.
Abstraction
-
65.
Use a DSL to develop your tools
-
66.
Support
Newsgroup
Community Forum
Professional Support
-
67.
Heiko Sven Moritz Peter Dennis Jan Patrick Sebastian Michael Knut
Behrens Efftinge Eysholdt Friese Hübner Köhnlein Schönbach Zarnekow Clay Wannheden
Individual
-
68.
Twitter: @xtext
http://www.xtext.org
itemis = IT + Themis
Themis, goddess of
justice
order
knows the future
connect people
share contact details
your resume on the web (endorsements, who you know, what you&#x2019;ve done)
connect people / friends
&#x201C;friend&#x201D; someone / &#x201C;write on their wall&#x201D;
share photos
fun-oriented
connect people
everybody can have their say
Java = GPL
You can do everything with Java
But is it a good idea to do everything with Java?
concise
precise
wouldn&#x2019;t change anything
ANT, built on a single transatlantic flight
using XML to avoid writing own parser
leverage XML parser
today, we&#x2019;d do it differently
ANT, built on a single transatlantic flight
using XML to avoid writing own parser
leverage XML parser
today, we&#x2019;d do it differently
It&#x2019;s relatively easy to write an internal DSL
Syntax of host language is the limiting factor for implementing internal DSLs
External DSLs are very flexible - you can exactly adjust them to your needs
You can choose the syntax of your DSL to your liking
However, building external DSLs is complicated
Java = GPL
You can do everything with Java
But is it a good idea to do everything with Java?
Newsgroup
Foren
Prof. Support