Bibliothek zum Transformieren eines Knotenbaums

8

Ich würde gerne eine allgemeine Transformation von einem Baum in einen anderen ausdrücken können, ohne einen Haufen repetitiven Spaghetti-Code zu schreiben. Gibt es Bibliotheken, die bei diesem Problem helfen? Meine Zielsprache ist Python, aber ich werde mir andere Sprachen anschauen, solange es möglich ist, nach Python zu portieren.

Beispiel: Ich möchte diesen Knotenbaum transformieren: (bitte entschuldigen Sie die S-Ausdrücke )

%Vor%

In diesen:

%Vor%

Solange der Elternteil A ist und der zweite Vorfahre C ist, unabhängig vom Kontext (es kann mehr Eltern oder Vorfahren geben). Ich möchte diese Transformation auf einfache, prägnante und wiederverwendbare Weise zum Ausdruck bringen. Natürlich ist dieses Beispiel sehr spezifisch. Bitte versuchen Sie, den allgemeinen Fall anzusprechen.

Bearbeiten: RefactoringNG ist die Art von Dingen, die ich suche, obwohl es eine völlig neue Grammatik einführt um das Problem zu lösen, das ich gerne vermeiden würde. Ich suche immer noch nach mehr und / oder besseren Beispielen.

Hintergrund:

Ich kann Python und Cheetah (nicht fragen!) Dateien in tokenisierte Baumdarstellungen konvertieren und diese wiederum in lxml Bäume. Ich plane dann, den Baum neu zu organisieren und die Ergebnisse auszuschreiben, um automatisiertes Refactoring zu implementieren. XSLT scheint das Standardwerkzeug zu sein, um XML umzuschreiben, aber die Syntax ist schrecklich (meiner Meinung nach, offensichtlich) und niemand in unserem Geschäft würde es verstehen.

Ich könnte einige Funktionen schreiben, die einfach die lxml-Methoden (.xpath und so) verwenden, um meine Refactorings zu implementieren, aber ich mache mir Sorgen, dass ich mit einer Reihe von speziell entwickelten Spaghetti-Codes enden werde, die nicht repliziert werden können -used.

    
bukzor 18.01.2012, 21:28
quelle

2 Antworten

2

Versuchen wir das in Python-Code. Ich habe Strings für die Blätter verwendet, aber dies funktioniert mit allen Objekten.

%Vor%

Diese Art von Baumtransformation wird im Allgemeinen besser in einem funktionalen Stil ausgeführt - wenn Sie eine Menge dieser Funktionen erstellen, können Sie sie explizit erstellen oder eine Kompositionsfunktion erstellen, um mit ihnen punktfrei zu arbeiten. p>

Da Sie s-Ausdrücke verwendet haben, gehe ich davon aus, dass Sie Bäume als verschachtelte Listen darstellen (oder das Äquivalent - wenn ich mich nicht irre, sind lxml-Knoten auf diese Weise iterierbar). Offensichtlich beruht dieses Beispiel auf einer bekannten Eingabestruktur, aber Ihre Frage impliziert das. Sie können flexiblere Funktionen schreiben und immer noch komponieren, solange sie diese einheitliche Schnittstelle haben.

Hier ist der Code in Aktion: Ссылка

Nun, hier ist eine Funktion, um Kinder umzukehren, und mit dieser und der oben genannten Funktion, eine zu heben und umzukehren:

%Vor%     
Marcin 03.07.2013 14:41
quelle
1

Was Sie wirklich wollen IMHO ist ein Programmtransformationssystem , mit dem Sie Code analysieren und transformieren können Verwenden der in der Oberflächensyntax des Quellcodes (und sogar der Zielsprache) ausgedrückten Muster, um die Umschreibungen direkt auszudrücken.

Sie werden feststellen, dass selbst wenn Sie eine XML-Repräsentation des Python-Baums in die Hände bekommen, dass der Aufwand, eine XSLT / XPath-Transformation zu schreiben, größer ist als erwartet; Bäume, die echten Code darstellen, sind unordentlicher als Sie erwarten würden, XSLT ist nicht so praktisch eine Notation, und es kann nicht direkt allgemeine Bedingungen auf Bäumen ausdrücken, die Sie überprüfen möchten (z. B. dass zwei Teilbäume gleich sind). Eine abschließende Komplikation mit XML: Angenommen, es wurde transformiert. Wie generierst du die Quellcodesyntax neu, aus der kam? Du brauchst eine Art hübschen Drucker.

Ein allgemeines Problem, unabhängig davon, wie der Code dargestellt wird, ist, dass ohne Informationen über Bereiche und Typen (wo Sie sie bekommen können), das Schreiben korrekter Transformationen ziemlich schwierig ist. Wenn Sie Python in eine Sprache umwandeln wollen, die für String Concat und Arithmetik verschiedene Operatoren verwendet (anders als Java, das "+" für beide verwendet), müssen Sie entscheiden können, welcher Operator generiert werden soll. Sie müssen also Informationen eingeben, um zu entscheiden. Python ist wohl typenlos, aber in der Praxis beinhalten die meisten Ausdrücke Variablen, die während ihrer gesamten Lebensdauer nur einen Typ haben. Sie benötigen also eine Flussanalyse, um Typen zu berechnen.

Unser DMS Software Reengineering Toolkit verfügt über alle diese Funktionen (Analyse, Flussanalyse, Mustererkennung / Umschreiben, Prettyprinting) und robusten Parsern für viele Sprachen einschließlich Python. (Während es für C, COBOL, Java instanziierte Flussanalysefunktionen gibt, wird diese für Python nicht instanziiert. Aber Sie haben dann gesagt, dass Sie die Umwandlung unabhängig vom Kontext durchführen möchten).

Um Ihre Umschreibung in DMS in Python-Syntax in der Nähe Ihres Beispiels auszudrücken (was nicht Python ist?)

%Vor%

Die obige Notation ist die DMS-Regel-Umschreibungssprache (RSL). Die "..." sind Metaquotes, die die Python-Syntax (innerhalb dieser Anführungszeichen kennt DMS Python wegen der Deklaration der Domain-Notation) aus der DMS RSL-Sprache trennen. Das \ n innerhalb des Meta-Zitats bezieht sich auf die Syntaxvariablen-Platzhalter des benannten Nichtterminal-Typs, der in der Regelparameterliste definiert ist. Ja, (...) innerhalb der Metaquotes sind Python () ... sie existieren in den Syntaxbäumen, soweit es DMS betrifft, weil sie, wie der Rest der Sprache, sind nur Syntax .

Die obige Regel sieht etwas merkwürdig aus, weil ich versuche, Ihrem Beispiel so nah wie möglich zu folgen, und aus der Sicht der Ausdruckssprache ist Ihr Beispiel gerade deshalb seltsam, weil es ungewöhnliche Klammern hat.

Mit dieser Regel kann DMS Python (mit seinem Python-Parser) wie

analysieren %Vor%

Erstellen Sie einen AST, passen Sie die Regel (geparst gegen AST) an diese AST an, schreiben Sie sie in einen anderen AST um, der entspricht:

%Vor%

und dann prettyprint die Oberflächensyntax (gültig) python zurück.

Wenn Sie Ihr Beispiel als Transformation für den LISP-Code betrachten würden, würden Sie das tun brauche eine LISP-Grammatik für DMS (nicht schwer zu bauen, aber wir haben nicht viel rufen Sie dazu auf) und schreiben Sie entsprechende Oberflächensyntax:

%Vor%

Sie können ein besseres Gefühl dafür bekommen, wenn Sie Algebra als DMS-Domäne ansehen.

Wenn Sie all das in Python implementieren wollen, habe ich nicht viel Hilfe. DMS ist ein ziemlich großes System, und es wäre eine Menge Mühe, es zu replizieren.

    
Ira Baxter 18.01.2012 23:55
quelle