22
Prof. Dr. H. Drachenfels Version 11.0 Hochschule Konstanz 13.2.2019 Grundlagen der modellgetriebenen Softwareentwicklung Teil 3: Domänenspezifische Sprachen Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-1 Hochschule Konstanz Domänen Domäne Arbeits-, Wissensgebiet, auf dem jemand besonders gut Bescheid weiß, auf dem er sich speziell und besonders intensiv betätigt ... (Duden Fremdwörterbuch, 1982) Jede Software wird für eine bestimmte Domäne entwickelt, z.B.: Übersetzung von Programmiersprachen Kommunikation in verteilten System Grafische Benutzeroberflächen Web-Shop Buchhaltung Waschmaschinensteuerung ...

Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Embed Size (px)

Citation preview

Page 1: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Version 11.0 Hochschule Konstanz 13.2.2019

Grundlagen der modellgetriebenen Softwareentwicklung

Teil 3: Domänenspezifische Sprachen

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-1

Hochschule Konstanz

Domänen

Domäne Arbeits-, Wissensgebiet, auf dem jemand besonders gut Bescheid weiß, auf dem er sich speziell und besonders intensiv betätigt ... (Duden Fremdwörterbuch, 1982) Jede Software wird für eine bestimmte Domäne entwickelt, z.B.:

• Übersetzung von Programmiersprachen

• Kommunikation in verteilten System

• Grafische Benutzeroberflächen

• Web-Shop

• Buchhaltung

• Waschmaschinensteuerung

• ...

Page 2: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2

Hochschule Konstanz

Domänenspezifische Bibliotheken

Traditionell wird Domänenwissen in Bibliotheken (und Frameworks) erfasst, die ihrerseits in einer universellen Programmiersprache implementiert sind.

Die Aufteilung Sprachen universell und Bibliotheken domänenspezifisch ist im Prinzip ein Erfolgsmodell, hat aber trotzdem auch Nachteile:

• Das Domänenwissen muss mit Hilfe der Konzepte der Programmiersprache ausgedrückt werden (z.B. mit Funktionen oder Objekten).

Die dadurch bedingte semantische Lücke ist eine Fehlerquelle und führt zu Redundanz in Form von sich wiederholendem Standardcode (Boilerplate). Beispiele: GUI-Programmierung mit Java Swing, Datenverwaltung mit Java Collections

• Bibliotheksimplementierungen binden Domänenwissen an bestimmte Plattformen und an bestimmtes Laufzeitverhalten.

macht die Integration mehrerer Bibliotheken für unterschiedliche Domänen in einer Anwendung mitunter schwierig

erfordert gegebenenfalls viele aufwendig zu pflegende Varianten einer Bibliothek

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-3

Hochschule Konstanz

Domänenspezifische Sprachen

DSL (Domain Specific Language, auch: Fachsprache)

Eine formale Sprache, die speziell für ein bestimmtes Problemfeld (die Domäne) entworfen und implementiert wird.

Potenzielle Vorteile einer DSL:

• die relevanten Aspekte einer Domäne (und möglichst nichts darüber hinaus) lassen sich kompakt und korrekt beschreiben und können auf unterschiedliche Implementierungen abgebildet werden

wenige spezialisierte Konzepte mit möglichst wenig syntaktischem Ballast

• Domänenexperten können damit umgehen, d.h. sie können zumindest mit der DSL verfasste Beschreibungen verstehen

Anlehnung an die in der Domäne üblichen Notationen

Entwurfsschritte für eine DSL:

• Domänenanalyse zum Bestimmen der relevanten Aspekte

• Sprachklasse, Syntax und Semantik festlegen

Page 3: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-4

Hochschule Konstanz

Formale Sprachen

Formale Sprache

Menge von Symbolen mit Regeln für zulässige Kombinationen der Symbole

z.B. Programmiersprachen

Metasprache

formale Sprache zum Beschreiben formaler Sprachen (d.h. zum Definieren der Symbole und Regeln)

eine unendliche Meta-Rekursion ist durch selbstbeschreibende Metasprachen vermeidbar

z.B. erweiterte Backus-Naur-Form (EBNF)

Sprache Metasprache

«beschreibt» «beschreibt»

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-5

Hochschule Konstanz

DSL: Domänenanalyse

Möglichkeiten zum Erfassen der relevanten Konzepte einer Domäne:

• Glossar

Liste von Begriffen mit Erklärungen

• Taxonomie

hierarchischer Einordnung von Begriffen in Kategorien

• Thesaurus

Taxonomie mit zusätzlichen Synonym-/Verwandtschafts-Beziehungen

• Ontologie (Begriffsnetz, semantisches Netz)

Begriffe mit Eigenschaften, beliebigen Relationen und Axiomen

Axiome sind Aussagen, die in der Domäne immer wahr sind

Taxonomien und Thesauren sind im Prinzip Spezialfälle von Ontologien mit fest vorgegebenen Relationstypen und ohne Axiome

Page 4: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-6

Hochschule Konstanz

DSL: Sprachklassen

Klassifizierung nach Notation:

• rein textuell

• grafisch mit textuellen Beschriftungen

Klassifizierung nach Implementierung:

• Spezialisierung einer Universalsprache

z.B. UML-Profile, XML-Dialekte

• Black-Box-Einbettung in eine Wirtssprache

Kapselung in Strings oder Kommentaren der Wirtssprache z.B. reguläre Ausdrücke, printf-Formatstrings, Dokumentationskommentare in Java

• White-Box-Einbettung in eine Wirtssprache (interne DSL) Realisierung als Ausdrücke in der Wirtssprache z.B. EasyMock mit Wirtssprache Java

• eigenständige Sprache (externe DSL) z.B. HTML, Unix shell script, Makefile

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-7

Hochschule Konstanz

DSL: Syntax

• die konkrete Syntax einer DSL legt fest, wie etwas formuliert werden kann:

spezifiziert im Detail die Notation der Sprache (Schlüsselwörter, Symbole, ...), z.B. bei textuellen DSLs mit Hilfe von regulären Ausdrücken und/oder EBNF

die konkrete Syntax ist die Benutzerschnittstelle der DSL und ist entscheidend für die Lesbarkeit der DSL durch den Menschen

• die abstrakte Syntax einer DSL legt fest, was formuliert werden kann:

spezifiziert die Struktur der Sprache (Konzepte und deren Beziehungen ...), z.B. mittels eines Metamodells, das als abstrakter Syntaxgraph (ASG) bzw. abstrakter Syntaxbaum (AST) instanziert wird

zu ein und derselben abstrakten Syntax kann es mehrere konkrete Syntaxformen geben z.B. eine textuelle und eine grafische Notation

die abstrakte Syntax ist entscheidend für die automatisierte Verarbeitung dessen, was der Benutzer mit der DSL formuliert

Page 5: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-8

Hochschule Konstanz

DSL: Semantik

• die statische Semantik regelt die Wohlgeformtheit von Formulierungen:

explizit in Form von Konsistenzregeln für abstrakte Syntaxgraphen

z.B. eindeutige Namen für Entitäten verlangen

z.B. bei Programmiersprachen: Variablen müssen vor ihrer Verwendung definiert werden

• die dynamische Semantik regelt die Bedeutung von Formulierungen:

implizit in Form von Transformatoren für abstrakte Syntaxgraphen

Transformatoren erzeugen aus jedem Sprachkonzept etwas Bestimmtes

z.B. erzeugt der Compiler einer Programmiersprache aus einer Variablendefinition eine Speicherreservierung

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-9

Hochschule Konstanz

DSL: Werkzeug-Unterstützung

Werkzeuge machen eine DSL erst praktisch einsetzbar:

• Parser

wandelt konkrete Syntax in abstrakte Syntax

muss nur bei externen DSLs jeweils neu implementiert werden

• Serialisierer

wandelt abstrakte Syntax in konkrete Syntax

ist nicht immer erforderlich

• Editor

ermöglicht das interaktive Bearbeiten von konkreter und/oder abstrakter Syntax

je nach Sprachklasse und gewünschtem Komfort entweder Wiederverwendung oder spezielle Implementierung

• Interpreter / Transformatoren / Generatoren

verarbeiten die in abstrakter Syntax vorliegende Information

legen die dynamische Semantik der DSL fest

die Implementierung der Werkzeuge kann zu großen Teilen automatisiert werden.

Page 6: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-10

Hochschule Konstanz

UML-Spezialisierung: Profile

UML kann mittels Profil zu einer DSL spezialisiert werden.

Ein UML-Profil besteht aus

• Stereotypen Spezialisierungen von Modellelementen

• Tagged Values Attribute der Stereotypen

• Constraints Konsistenzregeln für mit den Stereotypen markierte Modellelemente

Ein UML-Profil modifiziert

• die abstrakte Syntax von UML mittels Stereotypen und Tagged Values

als Metasprache wird im Prinzip das UML-Klassendiagramm verwendet, siehe dazu auch den MOF-Standard (Meta Object Facility)

• die statische Semantik von UML mittels Constraints

als Metasprache wird die Object Constraint Language (OCL) verwendet

• die konkrete Syntax von UML mittels graphischer Symbole

einem Stereotyp kann ein graphisches Symbol zugeordnet werden

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-11

Hochschule Konstanz

UML-Spezialisierung: OCL (1)

Constraints werden mit OCL (Object Constraint Language) formal spezifiziert. Sie machen Aussagen über die Gültigkeit von Modellen (statische Semantik).

Arten von Constraints:

• Invarianten sind Bedingungen, die bei jedem Objekt einer bestimmten Klasse zu jedem Zeitpunkt erfüllt (true) sein müssen

• Vorbedingungen (Preconditions) und Nachbedingungen (Postconditions) sind Bedingungen, die vor bzw. nach Aufruf einer bestimmten Operation erfüllt (true) sein müssen

• Anfangswerte, die bei bestimmten Attributen einzuhalten sind

• Ergebniswerte, die bestimmte Abfrageoperationen zu liefern haben

Page 7: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-12

Hochschule Konstanz

UML-Spezialisierung: OCL (2)

Syntax von Constraints:

• Invarianten

context Klasse inv: Bedingung

• Vor- und Nachbedingungen:

context Operation pre: Bedingung post: Bedingung

• Anfangswerte:

context Attribut init: Ausdruck

• Ergebniswerte:

context Operation body: Ausdruck

Wertebereich von Attributen beschränken Beziehungen zwischen Klassen / Objekten beschränken

Anwendbarkeit einer Operation beschränken Auswirkung einer Operation spezifizieren

Implementierung von Abfrageoperationen spezifizieren

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-13

Hochschule Konstanz

Beispiel UML-Spezialisierung (1)

UML-Profile sind z.B. gut auf UML-Klassendiagramme anwendbar:

• auf der Metaebene Definition eines Profils Joi (Java Objects by Interface) mit Stereotyp Component, Tagged Value singleton und Constraint,

anwendbar auf Klassen

• konforme Verwendung des obigen Profils:

<<metaclass>>

UML::Class

<<stereotype>>

Joi::Component

singleton: boolean

{ eine Joi-Komponente darf weder Ober- noch Unterklasse haben und muss mindestens ein Interface implementieren }

<<Joi::Component>>

{ singleton = false }

EinModell::EineKlasse

<<interface>>

EinModell::EinInterface

Page 8: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-14

Hochschule Konstanz

Beispiel UML-Spezialisierung (2)

• die Constraints für mit Stereotyp Joi::Component markierte Klassen können mit OCL wie folgt formalisiert werden:

context Component

inv: self.base_Class.superClass->isEmpty()

inv: Generalization.allInstances().general ->excludes(self.base_Class)

inv: self.base_Class.clientDependency ->select(oclIsKindOf(InterfaceRealization)) ->notEmpty()

(getestet mit Papyrus UML 1.0.2 in Eclipse Luna 4.4.2)

keine Oberklasse

Navigation im UML-Metamodell

keine Unterklasse

mindestens ein Interface

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-15

Hochschule Konstanz

XML-Spezialisierung: DTD und XSD

XML kann als DSL verwendet werden.

Der Sprachumfang kann (und sollte unbedingt) formal spezifiziert werden:

• entweder mittels Metasprache DTD (Document Type Definition)

• oder mittels Metasprache XSD (XML Schema Definition).

Die XML-Spezialisierung betrifft:

• Elemente und deren syntaktische Kombination (Schachtelung, Reihenfolge, ...) <element>...</element>

• Elementattribute und deren Wertebereiche <element attribut="wert">

• Entities (Textbausteine, nur mittels DTD definierbar) &entity;

Page 9: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-16

Hochschule Konstanz

Beispiel DTD (1)

Beispiel zur Verwendung einer DTD (Document Type Definition):

• auf der Metaebene legt joi.dtd den Sprachumfang fest

<!ELEMENT joi (component)*> <!ELEMENT component (interface+, body?)> <!ATTLIST component name ID #REQUIRED singleton (true|false) "false" > <!ELEMENT interface EMPTY> <!ATTLIST interface name NMTOKEN #REQUIRED > <!ELEMENT body (#PCDATA)>

Das Wurzelelement joi enthält beliebig viele component-Elemente, diese wiederum mindestens ein interface-Element sowie eine optionales body-Element.

ID ist ein eindeutiger Name, NMTOKEN ein Name, der mehrfach vorkommen darf.

#REQUIRED kennzeichnet ein Pflichtattribut.

singleton hat den Standardwert false.

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-17

Hochschule Konstanz

Beispiel DTD (2)

• konforme Verwendung der DTD in einmodell.joi

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE joi SYSTEM "joi.dtd">

<joi>

<component name="C">

<interface name="I" />

<body>

Beliebiger Text, auch mit Entities

</body>

</component>

</joi>

Page 10: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-18

Hochschule Konstanz

Beispiel XSD (1)

Das gleiche Beispiel wie zuvor mit XSD (XML Schema Definition):

• auf der Metaebene legt joi.xsd den Sprachumfang fest

<?xml version="1.0" encoding="ISO-8859-1"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="joi"> <xs:complexType> <xs:sequence> <xs:element name="component" type="componenttype" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> </xs:element>

...

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-19

Hochschule Konstanz

Beispiel XSD (2)

• Fortsetzung joi.xsd ... <xs:complexType name="componenttype"> <xs:sequence> <xs:element name="interface" type="interfacetype" maxOccurs="unbounded" /> <xs:element name="body" type="xs:string" minOccurs="0" /> </xs:sequence> <xs:attribute name="name" type="xs:ID" use="required" /> <xs:attribute name="singleton" type="xs:boolean" default="false" /> </xs:complexType>

<xs:complexType name="interfacetype"> <xs:attribute name="name" type="xs:string" use="required" /> </xs:complexType>

</xs:schema>

Page 11: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-20

Hochschule Konstanz

Beispiel XSD (3)

• konforme Verwendung in einmodell.joi wie bei der DTD-Version,

nur ohne <!DOCTYPE ...>-Zeile

die Schemadatei wird dann als Parameter an den Parser übergeben

• oder mit Angabe der Schemadatei im Wurzelelement:

<?xml version="1.0" encoding="ISO-8859-1"?>

<joi xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="joi.xsd">

<component name="C">

<interface name="I" />

<body>

Beliebiger Text, auch mit Entities

</body>

</component>

</joi>

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-21

Hochschule Konstanz

Interne DSL: Java

In Java können APIs (Application Programming Interfaces) so definiert werden, dass sie den Charakter einer DSL bekommen:

• Method-Chaining

API-Methoden liefern als Rückgabewert ihre this-Referenz,

um Aufrufketten innerhalb eines Ausdrucks zu ermöglichen

Beispiel: append-Methoden der Klasse java.lang.StringBuilder

String s = new StringBuilder()

.append("Hallo").append(" World!").toString();

• Method-Nesting

Rückgabewerte von API-Methoden als Argumente für API-Methodenaufrufe

dadurch sind rekursive Strukturen beschreibbar

• Object-Scoping

API-Methoden liefern als Rückgabewert jeweils ein Kontext-Objekt, das die als nächstes aufrufbaren Methoden festlegt und Zwischenergebnisse speichert

dadurch sind bestimmte Aufrufreihenfolgen für das Method-Chaining definierbar

Page 12: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-22

Hochschule Konstanz

Beispiel Interne DSL in Java: EasyMock

Beispiel: EasyMock-Bibliothek für die Domäne Unit-Tests

import static org.easymock.EasyMock.*;

public final class BeispielTest {

public interface Beispiel { boolean methode(); }

public static void main(String[] args) {

Beispiel mock = createMock(Beispiel.class);

expect(mock.methode()).andReturn(true).times(2);

replay(mock); mock.methode(); mock.methode(); verify(mock); }

}

Verwendung der internen DSL, um das Verhalten des Mock-Objekts zu spezifizieren:

• es sollen genau zwei Aufrufe von Beispiel.methode akzeptiert werden, die jeweils true zurückliefern

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-23

Hochschule Konstanz

Beispiel Interne DSL in Java: DOM-Baum (1)

• Konstruktion eines DOM-Baums (XML Document Object Model) mit konventioneller Aufrufsequenz:

org.jdom2.Element root = new org.jdom2.Element("joi");

org.jdom2.Element c = new org.jdom2.Element("component"); c.setAttribute("name","C"); c.setAttribute("singleton","false"); root.addContent(c);

org.jdom2.Element i = new org.jdom2.Element("interface"); i.setAttribute("name","I"); c.addContent(i);

org.jdom2.Element b = new org.jdom2.Element("body"); b.setText("Beliebiger Text"); c.addContent(b);

org.jdom2.Document d = new org.jdom2.Document(root);

Page 13: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-24

Hochschule Konstanz

Beispiel Interne DSL in Java: DOM-Baum (2)

• Konstruktion des gleichen DOM-Baums mit interner DSL:

import static joi.JdomBuilder.joi;

...

org.jdom2.Document d = joi().component("C").interfaces("I").body("Beliebiger Text").end();

• Implementierung der internen DSL in JdomBuilder.java:

package joi;

public final class JdomBuilder {

private final ComponentScope componentScope; private final InterfaceScope interfaceScope; private final BodyScope bodyScope;

... // Hilfsvariablen und privater Konstruktor ...

component() liefert ein Objekt, auf dem nur interfaces()aufrufbar ist

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-25

Hochschule Konstanz

Beispiel Interne DSL in Java: DOM-Baum (3)

...

public static ComponentScope joi() { return new JdomBuilder().componentScope; } public class ComponentScope {

public InterfaceScope component(String name) { ... }

public InterfaceScope singleton(String name) { ... }

public org.jdom2.Document end() { ... } } public class InterfaceScope { public BodyScope interfaces(String name, String... more) { ... } } public class BodyScope extends ComponentScope { public ComponentScope body(String s) { ... } } }

Endesymbol der internen DSL

Aufruf wegen Oberklasse optional

Startsymbol der internen DSL

Page 14: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-26

Hochschule Konstanz

Externe DSL: Reguläre Ausdrücke

Mit regulären Ausdrücken als Metasprache kann die konkrete Syntax einfacher textueller DSLs definiert werden (einfach heißt ohne rekursive Verschachtelungskonstrukte)

• Zeichenklassen:

• Quantifizierung:

• Verknüpfung:

r{2} zweimal hintereinander r{1,3} ein bis drei Wiederholungen r? entspricht r{0,1} r* entspricht r{0,}, d.h. beliebig oft inklusive keinmal r+ entspricht r{1,}, d.h. mindestens einmal

r ist ein beliebiger regulärer Ausdruck

r und s beliebige reguläre Ausdrücke

a das Zeichen 'a'

[abc-e] eines der Zeichen 'a', 'b', 'c', 'd' oder 'e'

[^abc-e] keines der Zeichen 'a', 'b', 'c', 'd' oder 'e'

. beliebiges Zeichen (außer Zeilenwechsel)

rs Konkatenation, d.h. erst r, dann s

r|s Alternative, d.h. r oder s

(r) Klammerung zum Überschreiben der Vorrangregeln (Quantifizierung vor Konkatenation vor Alternative)

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-27

Hochschule Konstanz

Externe DSL: EBNF

Mit der Erweiterten Backus-Naur-Form (EBNF) als Metasprache können kontextfreie Grammatiken für textuelle DSLs definiert werden

• Terminale:

• Nichtterminale:

• Symbolfolgen:

• Produktionsregeln:

s und t beliebige Symbolfolgen mit Terminalen und Nichtterminalen

"abc" die Zeichenfolge abc

Name metasprachliche Variable

st s gefolgt von t

s|t entweder s oder t

{s} beliebig viele s inklusive keinmal [s] kein oder ein s

(s) Klammerung zum Überschreiben der Vorrangregeln

Nichtterminal = Symbolfolge ;

Page 15: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-28

Hochschule Konstanz

Externe DSL: Parse-Tree versus AST

• ein Parse-Tree zeigt, mit welchen Regeln ein Parser seine Eingabe zerlegt hat

• ein AST (Abstract Syntax Tree) entsteht aus einem Parse-Tree, indem man die Knoten der Nicht-Terminale und der rein syntaktisch motivierten Terminale daraus entfernt

• Beispiel: Zuweisung in einer Programmiersprache

x = 0;

Parse-Tree: AST:

=

x 0

statement

assignment ;

name = expression

x 0

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-29

Hochschule Konstanz

Externe DSL: Implementierung

• mit reguläre Ausdrücken und EBNF die konkrete Syntax der DSL definieren

reguläre Ausdrücke für die Definition der Tokens (Schlüsselwörter, Zahlen, Namen, ...) und EBNF für die Definition der zulässigen Token-Folgen

daraus (in der Regel automatische) Erzeugung eines Parsers, der die Syntax prüft

• zusätzlich Rückgriff auf eine Programmiersprache, um die abstrakte Syntax und die statische Semantik einer DSL zu definieren

als Programmiersprache empfiehlt sich die Implementierungssprache des Parsers

EBNF und die erforderlichen Programmfragmente werden oft in einer Quelle gemischt, dann sogar automatische Erzeugung eines Parsers, der einen konsistenten abstrakten Syntaxgraph liefert

• Beispiele für Parser-Generatoren:

flex und bison (ehemals lex und yacc) Klassiker unter Linux / Unix

ANTLR bzw. ANTLWorks aktuell viel verwendet, besonders im Java-Umfeld

Page 16: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-30

Hochschule Konstanz

Externe DSL: Scanner-Generator flex

flex (fast lexical analyser) generiert einen Scanner, der Symbole (Tokens)

in einem Text findet

• Dateiformat der Scanner-Spezifikation:

%{ Anwendungscode

%}

Definitionen

%%

Regeln

%%

Anwendungscode

Anwendungscode und Aktionscode der Regeln wird in C geschrieben und wörtlich in den generierten Scanner übernommen

Name Wert

%s Startbedingung(en)

%x Startbedingung(en)

%option Option(en)

Textmuster Aktion

Textmuster { Aktion }

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-31

Hochschule Konstanz

Beispiel flex

/* number.l - einfache Scanner-Spezifikation für Zahlen und Einzelzeichen */ %{ enum token {NUMBER = 256};

%} %option noyywrap %% [+-]?[0-9]+("."[0-9]+)? return NUMBER;

[ \t\n] /* ignorieren */;

. return yytext[0];

%% int main (int argc, char *argv[]) {

int t;

while ((t = yylex()) != 0)

if (t == NUMBER)

printf("NUMBER(%s)", yytext);

else

printf("%c", t);

return 0;

}

Anwendungscode: NUMBER wird in einer Regel und in main gebraucht

Option: Scanner soll bei Eingabeende terminieren

Anwendungscode: yylex() ist der Aufruf des generierten Scanners

Regeln: Zahlen und Einzelzeichen sind Token, Zwischenraum nicht

Page 17: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-32

Hochschule Konstanz

Externe DSL: Parser-Generator bison

bison generiert einen Parser, der Tokenfolgen auf syntaktische Korrektheit prüft

• Dateiformat der Parser-Spezifikation:

%{ Prolog

%}

%union { Typdeklarationen

}

Definitionen

%%

Regeln

%%

Epilog

Prolog, Typdeklarationen, Aktionen der Regeln und Epilog werden in C geschrieben und wörtlich in den generierten Parser übernommen.

%token Terminalsymbol(e)

%left Terminalsymbol(e)

%right Terminalsymbol(e)

%type <TYP> Nichtterminal(e)

...

Nichtterminal: Symbole { Aktion } | Symbole { Aktion } ;

...

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-33

Hochschule Konstanz

Beispiel bison (1)

/* formel-parser.y - einfache Parser-Spezifikation für arithmetische Ausdrücke */ %{ #include <stdio.h>

int yylex(void);

void yyerror(const char *);

%} %token NUMBER %left '+' '-' %left '*' '/' %% expr: NUMBER { printf("NUMBER\n"); } | expr '+' expr { printf("+\n "); } | expr '-' expr { printf("-\n "); } | expr '*' expr { printf("*\n "); } | expr '/' expr { printf("/\n "); } | '(' expr ')' ; ;

Prolog: benötigte Prototypen.

Definitionen: Terminalsymbole mit aufsteigendem Vorrang und gegebenenfalls Assoziativität

Regel: zulässige Tokenfolgen

Page 18: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-34

Hochschule Konstanz

Beispiel bison (2)

/* Fortsetzung formel-parser.y ... */

%% int main(void) {

return yyparse();

}

void yyerror(const char *s) {

fprintf(stderr, "%s\n", s);

}

Anwendungscode:

yyparse() ist der Aufruf des generierten Parsers.

yyerror ruft der generierte Parser beim Entdecken eines Syntaxfehlers auf.

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-35

Hochschule Konstanz

Externe DSL: Parser-Generator ANTLR

ANTLR 4 (Another Tool for Language Recognition Version 4) generiert Klassen für

die Erkennung von Tokens (Lexer statt Scanner genannt) und die Syntaxanalyse.

Aus einer Grammatikbeschreibung Name.g4 entstehen im Falle von Java:

NameLexer.java NameParser.java

NameListener.java NameBaseListener.java

Anders als bei flex und bison (und älteren Versionen von ANTLR) soll die Grammatikbeschreibung keine Aktionen mit Programmcode enthalten.

Die Aktionen sollen statt dessen getrennt von der Grammatik in einer Listener-Implementierung bereitgestellt werden (alternativ auch Visitor-Implementierung).

Page 19: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-36

Hochschule Konstanz

Beispiel ANTLR (1)

// Joi.g4 grammar Joi;

joi : component* ; component : componentHead 'implements' componentInterface (',' componentInterface)* componentBody? ; componentHead : 'component' NAME # ComponentName | 'singleton' NAME # SingletonName ; componentInterface : NAME ; componentBody : BODY ;

BODY : '{' .*? '}' ; NAME : ('A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ; NEWLINE : '\r'? '\n' -> skip ; WHITESPACE : [ \t]+ -> skip ;

Namen der Lexer-Regeln in Großbuchstaben

Namen der Parser-Regeln in Kleinbuchstaben

Namen für die Regel-Alternativen

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-37

Hochschule Konstanz

Beispiel ANTLR (2)

Beispiel-Eingabe mit zugehörigem Parse-Tree:

component C implements I {

Beliebiger Text

}

Page 20: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-38

Hochschule Konstanz

Beispiel ANTLR (3)

Der Parse-Tree kann über eine Listener-Implementierung in einen Jdom-Baum transformiert und dann als XML serialisiert werden:

// JoiToXml.java import org.antlr.v4.runtime.*; // ANTLRInputStream, CommonTokenStream import org.antlr.v4.runtime.tree.*; // ParseTree, ParseTreeWalker import org.jdom2.*; // Document, Element import org.jdom2.output.*; // XMLOutputter

public final class JoiToXml { private JoiToXml() { }

public static void main(final String[] args) throws java.io.Exception { JoiLexer lexer = new JoiLexer(new ANTLRInputStream(System.in)); JoiParser parser = new JoiParser(new CommonTokenStream(lexer)); ParseTree tree = parser.joi();

JdomBuilder builder = new JdomBuilder(); new ParseTreeWalker().walk(builder, tree); new XMLOutputter().output(builder.document, System.out); } ...

Eingabe in Syntax der externen DSL

Ausgabe im XML-Format

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-39

Hochschule Konstanz

Beispiel ANTLR (4)

... private static final class JdomBuilder extends JoiBaseListener { private final Element root = new Element("joi"); private final Document document = new Document(root); private Element component;

public void enterComponent(JoiParser.ComponentContext c) { component = new Element("component"); root.addContent(component); }

public void exitComponentName(JoiParser.ComponentNameContext c) { component.setAttribute("name", c.NAME().getText()); component.setAttribute("singleton", "false"); }

public void exitSingletonName(JoiParser.SingletonNameContext c) { component.setAttribute("name", c.NAME().getText()); component.setAttribute("singleton", "true"); } ...

Alternative SingeltonName

Alternative ComponentName der Regel componentHead

Page 21: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-40

Hochschule Konstanz

Beispiel ANTLR (5)

...

public void exitComponentInterface(JoiParser.ComponentInterfaceContext c) { component.addContent( new Element("interface") .setAttribute("name", c.NAME().getText()) ); }

public void exitComponentBody(JoiParser.ComponentBodyContext c) { String t = c.BODY().getText(); t = t.substring(1, t.length() - 1).trim();

component.addContent(new Element("body").setText(t)); } } }

Für jede Parser-Regel bzw. benannte Regelalternative generiert ANTLR im Interface JoiListener eine enter- und eine exit-Methode und in der Klasse JoiBaseListener leere Default-Implementierungen dazu.

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-41

Hochschule Konstanz

DSLs: Empfehlungen (1)

• Modelle bevorzugt mit DSLs formulieren!

Modellerstellung wird kompakter, weniger fehleranfällig und für Domänenexperten verständlicher

aber: DSL niemals als Selbstzweck, denn das Entwickeln einer DSL kann je nach Sprachklasse sehr aufwendig sein, und für die Anwender bringt das Erlernen einer neuen Sprachen ebenfalls Aufwand mit sich

• Graphische oder textuelle DSL?

wenn vor allem komplexe Beziehungen zu modellieren sind, ist eine Graphik tendenziell anschaulicher

Werkzeugunterstützung für Text ist wesentlich einfacher

vor der Entscheidung für die eine oder andere konkrete Syntax sollten erst einmal abstrakte Syntax und statische Semantik entworfen werden, denn die sind entscheidend für die Nützlichkeit der DSL

Page 22: Grundlagen der modellgetriebenen Softwareentwicklung Teil ...drachen/mgse/MGSE-Teil-3.pdf · Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-2 Hochschule

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-42

Hochschule Konstanz

DSLs: Empfehlungen (2)

• UML-Spezialisierung als DSL?

- Profile durch UML-Werkzeuge nicht wirklich gut unterstützt

- Einschränkung der Mächtigkeit von UML mittels OCL sehr mühsam

Profile sind eher geeignet, UML-Modelle mit Annotationen anzureichern (wir kommen darauf bei den Modelltransformationen zurück)

• XML-Spezialisierung als DSL?

- wenig Spielraum beim Sprachdesign

- großer syntaktischer Ballast

+ sehr gute und reichhaltige Werkzeugunterstützung vorhanden

XML-Dialekte sind eher als Datenaustausch- und Speicherungsformat geeignet, wegen des syntaktischen Ballasts nur in einfachen Fällen menschenlesbar/schreibar

Prof. Dr. H. Drachenfels Grundlagen der modellgetriebenen Softwareentwicklung 3-43

Hochschule Konstanz

DSLs: Empfehlungen (3)

• interne DSL?

- wenig Spielraum beim Sprachdesign

- beschränkt auf Zielgruppe Programmierer, die die Wirtssprache beherrschen

+ geringer Implementierungsaufwand durch Wiederverwendung der Werkzeuge

der Wirtssprache

+ geringer Lernaufwand für die Zielgruppe

• externe DSL?

+ maximaler Spielraum beim Sprachdesign

- Implementierungs-, Pflege- und Lernaufwand kann sehr groß werden

deshalb eher für kleine Domänen geeignet

erstrebenswert: Komposition von DSLs aus wiederverwendeten Teil-DSLs