Heiner Kücker

Domain-Parser

Home

Java-Seite

   Bit Packed Array

   ASM Improved

   heterogene
   Map, HMap

   Constraint
   Code Generator

   JSP WorkFlow
   PageFlow FlowControl
   Page Flow Engine
   Web Flow Engine
   Control_and_Command

   JSP_Spreadsheet

   Code-Generator
   für Option-Either-Stil
   in Java

   verbesserter
   Comparator

   Fluent-Interface
   Code-Generator
   auf Basis
   einer Grammatik

   Visitor mit Multidispatch

   for-Schleife mit
   yield-return

   Kognitions-Maschine
   semantisches Netz

   Domain Parser

   Codegenerator_für
   hierarchische
   Datenstrukturen

   Expression_Engine
   Formula_Parser

   Thread Preprocessor

   State Transition Engine

   AspectJ

   Java_Explorer

   DBF_Library

   Kalender_Applet

   SetGetGen

   BeanSetGet

   CheckPackage

   LineNumbers

   GradDms

   Excel-Export

   StringTokenizer

   JspDoc

   JspCheck

   JSP-Schulung
   Java Server Pages
   Struts

   Ascii-Tabellen-
   Layouter

   Ascii-Baum-
   Layouter

   Ascii-Art-Fluss-
   Diagramm-
   Parser

   AsciiArt
   AssignmentMatrix
   Layouter

   StringSerial

   Silbentrennung

   JDBC_Schlüssel-
   Generierung

   bidirektional/
   unidirektional
   gelinkte Liste

   Java_Sitemap
   Generator

   XmlBuilder

   RangeMap

   StringFormatter

   VersionSafe
   XCopy

   JTextField

   CommandLine-
   ParamReader

   Bitmap-Grafik

   MultiMarkable-
   Buffered-
   InputStream

   JavaCache

   JdomUtil

   CollectionUtil

   XML Really
   Pull Parser

   Log-Filter

   Remote-Protokoll

   Sudoku-Generator

   Delegation statt
   Mehrfachvererbung

   Disjunct
   Interval Set

   WebCam_Demo

   Weiterentwicklung_Java

Alaska-XBase++-Seite

Projekte

Philosophien
Techniken


Konzepte

Sudoku

Kontakt /
Impressum


Links

SiteMap





Letzte Aktualisierung:
25.08.2005

Domain Parser

Seit langem beschäftigt mich die Idee, dass eine spezielle Programiersprache die optimale Lösung zur Modellierung fachlicher Aspekte unter Trennung von der erforderlichen technischen Infrastruktur ist.
Eine grosse Hürde ist dabei das Implementieren eines korrekten Parsers für die jeweilige Fachsprache.
Wer wie ich nicht so gut mit javacc oder anderen grammatikbasierenden Werkzeugen zurechtkommt, kann gern meinen DomainParser benutzen.
Er ist ein Teil des Fluss-Steuerungs-Frameworks CnC, in dem er zusammen mit dem auf einer eigenen Page beschriebenen ExpressionParser die Fluss-Steuerdatei einliest.

Anleitung DomainParser

Schon seit ich die ersten Programmiersprachen kennenlernte, hatte ich die Idee zu fachspezifischen Schrachen, Domains Specific Languages genannt.

Das Ziel solcher Sprachen ist die Trennung von fachlicher Aussage und technischer Infrastruktur.

Ich stelle mir vor, dass eine mit einer solchen DSL (Domain Specific Language) realisierte Applikation stabil gegen Änderungen der fachlichen Logik oder der technischen Infrastruktur ist.

Die Fachlichkeit lässt sich unabhängig von der technischen Infrastruktur in der DSL ändern und die technische Infrastruktur unabhängig von der Fachlichkeit im Laufzeitsystem.

Einerseits kann man die technische Infrastruktur ohne Beeinträchtigung der fachlichen Logik auf andere Plattformen migrieren, solange die Schnittstellen-Spezifikation eingehalten wird. Andererseits haben Änderungen an der Fachlogik keine Auswirken auf die technische Infrastruktur, solange die Fachlogik ausschliesslich auf der spezifizierten Schnittstelle aufsetzt.

Um eine eigene Fachsprache zu entwickeln muss man folgende Schritte abarbeiten:

1. Sprache definieren

2. Parser bauen

3. Übersetzen, wobei dies als Interpreter oder als Compiler erfolgen kann.
Das Compilieren kann in eine spezielle Zwischensprache (Bytecode, Steuertabelle) oder in eine Hochsprache (MDA) erfolgen.

4. Bereitstellen einer Laufzeitumgebung (Klassenbibliothek, Applikationscontainer)

5. Deployen, Testen, iterative Weiterentwicklung

Für den zweiten Schritt, nämlich das Parsen, habe ich diesen kleinen Parser, GenericParser, der sich an die Java-Notation anlehnt, geschrieben.

Eine wesentliche Eigenschaften aller programmiersprachlichen Grammatiken ist die Wohlgeformtheit, das heisst, zu jeder öffnenden Klammer muss es eine entsprechende schliessende Klammer geben.

Dementsprechend kann mein kleiner Parser auch als XML-Ersatz, zumindest soweit es die Datendarstellung angeht verwendet werden.


Anwendungsgebiete

Durch eine Fachsprache will man natürlich ein vorhandenes Problem lösen.

Mit der JSP-Fluss-Steuerung Control-and-Command wird das Problem des Zerfallens des Steuerflusses durch die ereignisbasierte Abarbeitung des Request-Response-Zyklus zwischen Browser und Server gelöst.

Eine andere Anwendungsmöglichkeit ist die Steuerung asynchroner Vorgänge (Web-Services) in einem synchronen Script.

Ich könnte mir vorstellen, dass Client-Server-Applikationen wie allein-stehende Applikationen entwickelt werden könnten, aber verteilt deployt werden.

In GUI-Applikationen könte man Abläufe über spezielle Scripte statt über Status-Merker steuern.


Demos

Die JSP-Fluss-Steuerung Control-and-Command ist das Musterbeispiel einer fachspezifischen Sprache mit Compiler(FlowControlCompiler.java) und Laufzeitsystem(FlowControl.java), denn dafür habe ich den Domain-Parser speziell entwickelt.

Weitere Demos finden sich im Package de.cnc.domainparser.demo in der Klasse DomainParserDemo. Hier sind die Pfadangaben zu den Beispieldateien test.script und test.hierarchicproperties eventuell anzupassen.

Ein Beautifier zum formatierten Ausgeben geparster Unit´s Beautifier.java.

Eine Konfigurationsklasse als Alternative zu Properties-Files oder XML-Files HierarchicProperties.

Codegenerator hierarchische Strukturen

Die von Markus Völter im Artikel im Javaspektrum 04/2004 (siehe auch das PDF) aufgezeigte Verwendung von textuellen Spezifikationen für die modellgetriebene Entwicklung ist mit meinem Domainparser auch realisierbar.

Aufbau des Domain-Parsers

Mein Domain-Parser lehnt sich an den Aufbau der Sprache Java an.

Die Java-Klasse Unit stellt eine einzulesende Datei dar.
Es ist geplant, darüber eine Struktur Package (ein Verzeichnis)
und darüber wiederum eine Struktur Project (ein Verzeichnisbaum) zu legen.

Eine Unit kann beliebig viele Segmente entahlten.
Ein Segment entspricht einer Deklaration (package, import, variable) oder Klasse, Methode .

Ein Segment wird entweder durch ein Semikolon oder ein BracesArea abgeschlossen.

Segment ; // Beispiel package-Deklaration, Anweisung

oder

... { ... } // Beispiel Klassen- oder Methoden-Deklaration

Ein Segment kann aus beliebig vielen AbstractElementen bestehen.

AbstractElemente können entweder terminal (nicht weiter unterteilbar) oder
nichtterminal (aus weiteren terminalen oder nichtterminalen AbstractElementen bestehend) sein.

Es gibt die nicht-terminalen Elemente
BracesArea (in geschwungene Klammern eingeschlossener Bereich)
BracketArea (in eckige Klammern eingeschlossener Bereich)
CommaSeparatedList (durch Kommas getrennte Liste)
ComplexIdentifier (vorgesehen für die Punktschreibweise mit Members und Operatoren (nicht fertig) )
ElementList (durch Whitespaces getrennte Liste)
ParenthesisArea (in runde Klammern eingeschlossener Bereich)
Segment (durch Semikolon oder BracesArea beendeter Bereich)

Es gibt die terminalen Elemente
BracketComment (Kommentar /*...*/)
HighCommaStringLiteral (String in Hochkommas eingeschlossen)
Identifier (Bezeichner)
InlineComment (Inline-Kommentar //...)
Number (Zahl mit oder ohne Dezimalstellen)
Operator (+ - * / und so weiter)
QuoteStringLiteral (String in Quotes(Apostrophe) eingeschlossen)

Aufbau eines Compilers

Im CnC-Flusssteuerungs-Framework ist der Aufbau eines Compilers als Beispiel vorhanden. Die Klasse Unit liefert einen Syntaxbaum und sorgt für Wohlgeformheit der Quelldatei.

Der Aufbau des Compilers ähnelt dem Vorgehen in einem SAX-Parser und sollte deshalb mit normalem Programmierkenntnissen beherrschbar sein.

Die Methode FlowControlCompiler#resolveLabels() zeigt das Auflösen symbolischer Referenzen, ähnlich einem Link-Vorgang.

Aufbau eines Laufzeitumgebung

Die Klasse FlowControl des CnC-Systems zeigt den Aufbau eines Fluss-Prozessors, der die in einer FlowControlTable abgelegten FlowControlInstructions abarbeitet.

Speichern des Compilates

Das Kompilieren erfolgt in Java-Klassen und nicht in Bytecode.
Die erzeugten Java-Klassen können serialisiert und abgespeichert werden.
Im CnC-JSP-Flusssteuerungs-System dauerte das Kompilieren im Verhältnis zum notwendigen Tomcat-Neustart nur sehr kurze Zeit, so dass ein Caching des Compiliervorganges nicht nötig war.

Einbindung der Expression-Engine

Der CnC-Compiler übersetzt im Gegensatz zu bekannten Programmierspachen keine Ausdrücke, sondern übergibt diese zum Compilieren der Expression-Engine.
Dies hat historische Gründe darin, dass ich die Expression-Engine getrennt vom CnC-System entwicklet habe.
Teilweise sind zum Trennen der beiden Compiler runde Klammern um Ausdrücke erforderlich.

  return ( a + b );
Das ParenthesisArea enthält den zu parsenden Ausdruck.

Die compilierten Ausdrücke werden über die Methode Expression#eval abgearbeitet.

noch zu tun

zuschaltbare Operatoren (nach Länge, längste zuerst sortieren) )

Option zeilenweise (mit schalter case-sensitive)

  begin xxx
    yyy
  end xxx

  if <bool_expression>
    <code_block>
  end if

javadoc

clone-Methoden

#include-Anweisung

#include-Anweisung mit Parametern


Download

Download der Quelldateien DomainParser.zip

Zum Kompilieren und Starten müssen noch die Sourcen der SharedUtil's eingebunden werden.

Achtung: Erweiterungen und Fixes stelle ich ohne Historie und ohne Ankündigung hier bereit.
Deshalb am besten immer die letzte Version runterladen.

Lizenzbedingungen:

Die Programme, Quelltexte und Dokumentationen können ohne irgendwelche Bedingungen kostenlos verwendet werden.
Sie sind Freeware und Open Source. Für Fehler und Folgen wird keinerlei Haftung übernommen.

Hinweise zur Fehlerbeseitigung und Verbesserung sind mir willkommen.

Ich freue mich auch über Feedback bezüglich der erfolgreichen Verwendung meiner Sourcen.

Bei Fragen helfe ich gern mit Hinweisen oder zusätzlicher Dokumentation, falls ich dafür Zeit habe.