2009-10-04 7 views
5

Ich würde gerne wissen, gute Strategien für die Bereitstellung einer domänenspezifischen Sprache, die in mindestens 2 Sprachen (Java, C#) und wahrscheinlich mehr (Python und möglicherweise Javascript) ausgeführt werden muss.eine portable domänenspezifische Sprache schreiben

Einige Hintergrund. Wir haben eine domänenspezifische Sprache entwickelt und implementiert, die derzeit in C# geschrieben ist. Es wird durch eine Reihe von Methodenaufrufen bereitgestellt, deren Argumente entweder gemeinsame Sprachgrundelemente (String, Double usw.), Sammlungen (IEnumerable, HashSet, ...) oder Objekte in einer domänenspezifischen Bibliothek (CMLMolecule, Point3, RealSquareMatrix) sind. Die Bibliothek ist gut getestet und die Objekte müssen einem stabil implementierten XML-Schema entsprechen, so dass Änderungen evolutionär und verwaltet werden (zumindest ist das die Hoffnung).

Wir hoffen, dass die Sprache von einer breiten und teilweise computerkundigen Community genutzt wird, die es gewohnt ist, ihre eigenen Lösungen ohne zentrale Kontrolle zu hacken. Idealerweise wird das DSL einen Grad an Kapselung erzeugen und die wesentliche Funktionalität erzeugen, die sie benötigen. Die Bibliotheken werden die detaillierten Algorithmen verwalten, die vielfältig und doch ziemlich gut bekannt sind. Mit den Anforderungen des DSL in Domain-specific languages vs. library of functions ist viel gemeinsam.

Ich würde gerne Ideen für die beste Architektur (klar, sobald es im Einsatz ist, können wir nicht einfach zurückverfolgen). Die Auswahlmöglichkeiten umfassen mindestens:

  • Erstellung eines IDL (z. B. durch CORBA). Das W3C hat dies für das XML-DOM getan - ich hasste es - und es scheint übertrieben zu sein, manuelle Erstellung ähnlicher Signaturen für jede Plattform und das beste Bemühen, sie synchron zu halten,
  • .
  • Erstellung einer parsable Sprache (z. B. CSS).
  • deklarative Programmierung in XML (vgl. XSLT). Dies ist meine bevorzugte Lösung, da sie gesucht, manipuliert usw. werden kann.

Leistung ist nicht wichtig. Klarheit des Zwecks ist.

BEARBEITEN Es wurde diskutiert, ob bei Anwendungsanrufen ein DSL eingerichtet wird. Ich habe Martin Fowlers Einführung in DSLs (http://martinfowler.com/dslwip/Intro.html) entdeckt, wo er argumentiert, dass einfache Methodenanrufe (oder verkettete Anrufe) als DSL bezeichnet werden können. So eine Serie wie:

point0 = line0.intersectWith(plane); 
point1 = line1.intersectWith(plane); 
midpoint = point0.midpoint(point1); 

eine DSL in Betracht gezogen werden könnte

+1

Ein großer negativ in jede Sprache in XML ausgedrückt. Sie möchten, dass ein Entwickler direkt mit dem XML arbeitet oder das Speicher-/Laufzeitformat? Der Typ, der ANT erfunden hat, sagte, XML sei die falsche Wahl und er würde sich anders entscheiden, wenn er etwas ändern könnte. – SteveD

+0

@stevendick. Danke, ich höre was du sagst. Ich bin persönlich ein XML-Süchtiger, aber ich versuche, offen zu bleiben. –

+0

Werfen Sie einen Blick auf das, was der ursprüngliche Autor von ANT zu sagen hat: http://web.archive.org/web/20040602210721/x180.net/Articles/Java/AntAndXML.html Verfolgen Sie nicht blind die XML- Goldenes Hammer-Paradigma. Wenn Sie eine DSL-Datei erstellen, die von tatsächlichen Personen gelesen und geschrieben wird, sollten Sie einen der vielen schönen Lexer/Parser-Tools anstelle von XML verwenden. Es gibt heutzutage viele schöne Werkzeuge (wie ANTLR), die das praktisch machen. Das Schreiben von Lexer/Parsern ist nicht mehr so ​​schmerzhaft wie einst, als lex/yacc Stand der Technik war. –

Antwort

6

Es scheint eine Zweideutigkeit in der Frage zwischen Sprache und Bibliothek zu geben. Die Begriffe "internes DSL" und "externes DSL" sind nützlich, und ich denke, dass sie auf Martin Fowler zurückzuführen sind.

Eine "externe" DSL ist möglicherweise ein eigenständiges Befehlszeilentool. Es wird eine Zeichenfolge der Quelle übergeben, es analysiert es irgendwie und tut etwas damit. Es gibt keine wirklichen Grenzen, wie die Syntax und die Semantik funktionieren können. Es kann auch als eine Bibliothek bereitgestellt werden, die hauptsächlich aus einer eval-ähnlichen Methode besteht; Ein übliches Beispiel wäre das Erstellen einer SQL-Abfrage als String und das Aufrufen einer execute-Methode in einer RDBMS-Bibliothek. kein sehr angenehmes oder bequemes Nutzungsmuster, und schrecklich, wenn es sich um ein Programm in großem Umfang verbreitet.

Eine "interne" DSL ist eine Bibliothek, die so geschrieben ist, dass sie die Eigenheiten einer Host-Sprache nutzt, um den Eindruck zu erwecken, dass eine neue Sprache in eine bestehende Sprache eingebettet werden kann. In syntaktisch komplexen Sprachen (C++, C#) bedeutet dies, dass das Überladen von Operatoren auf eine Weise verwendet wird, die die üblichen Bedeutungen der Operatorsymbole ernsthaft dehnt (oder ignoriert). Es gibt viele Beispiele in C++; ein paar in C# auch - die Irony parser toolkit simuliert BNF auf eine ziemlich zurückhaltende Weise, die gut funktioniert.

Schließlich gibt es eine einfache alte Bibliothek: Klassen, Methoden, Eigenschaften, mit gut gewählten Namen.

Ein externes DSL würde Ihnen erlauben, sprachübergreifende Integrationsprobleme vollständig zu ignorieren, da der einzige bibliotheksähnliche Teil eine eval Methode wäre. Aber eine eigene Werkzeugkette zu erfinden ist nicht trivial. Die Leute vergessen immer die große Bedeutung von Debugging, Intellisense, Syntaxhervorhebung usw.

Eine interne DSL ist wahrscheinlich ein sinnloses Unterfangen, wenn Sie es gut auf C# und Java machen wollen. Das Problem ist, dass Sie, wenn Sie die Macken einer Hostsprache ausnutzen, nicht in der Lage sein werden, den Trick in einer anderen Sprache zu wiederholen. z.B. Java hat keinen Operator überladen.

Was hinterlässt eine einfache alte Bibliothek. Wenn Sie C# und Java (zumindest) überspannen wollen, dann stecken Sie etwas in der Wahl der Implementierungssprache fest. Wollen Sie die Bibliothek wirklich zweimal schreiben? Eine Möglichkeit besteht darin, die Bibliothek in Java zu schreiben und sie dann mit IKVM zu .NET-Assemblys zu kompilieren. Dies garantiert Ihnen eine identische Schnittstelle auf beiden Plattformen.

Auf der negativen Seite würde die API in den kleinsten gemeinsamen Nenner Features ausgedrückt werden - das heißt, Java-Funktionen :). Keine Eigenschaften, nur getX/setX-Methoden. Vermeiden Sie Generika, da die beiden Systeme in dieser Hinsicht sehr unterschiedlich sind. Auch die Standardmethode der Namensgebung unterscheidet sich zwischen den beiden (camelCase gegenüber PascalCase), so dass eine Gruppe von Benutzern eine Ratte riechen würde.

+0

@Earwicker +1 sehr nützliche Übersicht. Die Beteiligung von Java und C# ist gegeben (unglücklich). Ich werde das IKVM sicherlich versuchen. Ich habe nichts dagegen, Eigenschaften zu verlieren und die Generika sind einfach. Die Namenskonvention kann hoffentlich automatisiert werden. Ich bin mir der Probleme bewusst, meine eigene Toolchain zu erfinden und dies ist eine nützliche Zusammenfassung. –

+0

Ja, zweifellos könnten Sie ein Werkzeug schreiben, das die Namenskonvention beheben würde. Sie könnten sogar etwas ähnliches für Eigenschaften tun - suchen Sie nach getX/setX-Methodenpaaren (obwohl vielleicht ein Attributmarker notwendig wäre, da nicht alle getX-Methoden für die Eigenschaftensyntax geeignet sind, z. B. manchmal sichtbare Nebenwirkungen haben). –

+1

@Earwicker. Das ist meine derzeitige Idee. Reduzieren Sie die Aufrufe auf eine gemeinsame Teilmenge von so vielen Sprachen wie möglich (z. B. keine Eigenschaften verwenden, schon gar nicht das Überladen von Operatoren). –

1

Fähigkeit zur Umsetzung Sprache im Fall, dass Sie etwas tun müssen, um zu entkommen, die einfach nicht von Ihrem DSL unterstützt wird, oder aus Performance-Gründen (obwohl mir klar ist, dass das keine Priorität ist).

Ich recherchiere DSL für die Implementierung von Regeln in einer Regelengine in C#, einige der Regeln sind wirklich komplex und können sich in der Zukunft wesentlich ändern, so dass es wirklich nützlich ist, nach C# zu entkommen. Natürlich ist dies eine plattformübergreifende Kompatibilität, aber es ist wirklich nur eine Möglichkeit, um Edge Cases zu hacken, ohne dass Sie Ihr DSL ändern müssen.

+1

@Dale. Ja!Es wird Grenzfälle geben, und es gibt keinen Grund, warum sie nicht auf diese Art und Weise akkretiert und dann möglicherweise später abstrahiert und verallgemeinert werden sollten. Ich würde erwarten, dass die wichtigsten Bibliotheksfunktionen ohnehin offen gelegt würden, so dass wir kein einziges Gateway hätten. –

0

würden Sie am besten aus der Bibliothek in C zu schreiben (oder eine Sprache wie rpython die C-Code generiert) und dann unter Verwendung von SWIG oder ähnlich die sprachspezifischen Bindungen für C#, Java Python etc.

zu erzeugen

Beachten Sie, dass dieser Ansatz nicht hilft, wenn Sie Javascript im Browser verwenden - Sie müssen die Javascript-Bibliothek separat schreiben. Wenn Sie JavaScript über Rhino verwenden, können Sie einfach die Java-Bindungen verwenden.

0

Es ist möglich, JavaScript innerhalb eines Java-Programms direkt mit der Skript-Engine und offensichtlich auch mit C# zu interpretieren. Python kann auf der JVM und der .NET-Engine ausgeführt werden.

Ich würde vorschlagen, dass Sie diese Optionen untersuchen und dann Ihre Bibliothek in eine gemeinsame Teilmenge der Ausführungspfade schreiben, die für die von Ihnen gewählte Sprache verfügbar sind. Ich würde es nicht in Erwägung ziehen, es in einer Sprache zu schreiben, die Nachübersetzung und Konvertierung erfordert, da Sie einen Schritt einleiten, der im Fall von Problemen sehr, sehr schwierig zu debuggen ist.

2

Obwohl ich mein eigenes Projekt nicht zu sehr fördern möchte, möchte ich PIL, a Platform Independent Language erwähnen, eine Zwischensprache, an der ich gearbeitet habe, um die Unterstützung mehrerer Softwareplattformen (wie Java, Python, ...) zu ermöglichen. , speziell für externe DSLs.Die allgemeine Idee ist, dass Sie Code in PIL (eine Teilmenge von Java) erzeugen, den der PIL-Compiler dann in eine von vielen anderen Sprachen übersetzen kann, derzeit nur Java oder Python, aber in Zukunft werden weitere hinzugefügt.

Ich habe ein Papier darüber auf der Software und Language Engineering Konferenz vor etwa 2 Tagen vorgestellt, Sie können einen Link zur Veröffentlichung der PIL-Website finden (pil-lang.org), wenn Sie interessiert sind.

+0

Ich habe so etwas vor ein paar Jahren versucht und es ist nützlich zu sehen, dass Leute es besser machen. –

3

Wenn Sie bereit sind, Ihre Sprache mit ANTLR neu zu beschreiben, können Sie Ihren DSL-Interpreter in mehreren Sprachen generieren, ohne sie manuell zu verwalten, einschließlich aller erwähnten Sprachen und mehr.

Antlr ist ein Parser/Lexer-Generator und hat eine große Anzahl von Zielsprachen. So können Sie Ihre Sprache einmal beschreiben, ohne mehrere Kopien davon verwalten zu müssen.

Siehe die vollständige Liste der Zielsprachen here.

+0

Ich mag diese Idee persönlich. Natürlich ist es ein großer Sprung und schwierig, sich von –

+0

zurückzuziehen. Wahr ist, es gibt eine Lernkurve mit Antlr und StringTemplate. Aber ich persönlich liebe es. Ich finde mehr und mehr Probleme können mit einer einfach beschriebenen Grammatik gelöst werden. Letztendlich wird die Zeit, die Sie im Umstellungsprozess verlieren, Ihre Wartungskosten mehr als wettmachen. –

0

Ich möchte Dariens Antwort erweitern. Ich denke, dass ANTLR etwas an den Tisch bringt, das nur wenige andere Lexer/Parser-Tools bieten (zumindest meines Wissens nach). Wenn Sie eine DSL erstellen möchten, die letztlich Java und C# -Code generiert, glänzt ANTLR wirklich.

ANTLR stellt vier grundlegende Komponenten:

  • Lexer Grammatik (aufgliedern Eingangsströme in Token)
  • Parsern Grammatik (organisieren Token in einen abstrakten Syntaxbaum)
  • Baum Grammatik (zu Fuß der abstrakte Syntax Baum und Rohr die Metadaten in eine Vorlage-Engine)
  • StringTemplate (eine Vorlage-Engine basierend auf funktionalen Programmierungsprinzipien)

Ihre Lexer-, Parser- und Baumgrammatiken können unabhängig von Ihrer zuletzt generierten Sprache bleiben. Tatsächlich unterstützt die StringTemplate-Engine logische Gruppen von Template-Definitionen. Es bietet sogar eine Schnittstellenvererbung von Vorlagengruppen. Das bedeutet, dass Sie Ihren ANTLR-Parser von Drittanbietern verwenden lassen können, um "say python", "assembly", "c" oder "ruby" zu erstellen, wenn Sie ursprünglich nur java und C# ausgegeben haben. Die Ausgabesprache Ihres DSL kann leicht erweitert werden, wenn sich die Anforderungen im Laufe der Zeit ändern.

Um das Beste aus ANTLR erhalten Sie folgendes lesen wollen:

The Definitive ANTLR Reference: Building Domain-Specific Languages

Language Implementation Patterns: Create Your Own Domain-Specific and General Programming Languages