Wie benutzt man Parsec auf gierige Weise?

9

In meiner Arbeit stoße ich auf eine Menge knorriger SQL, und ich hatte die gute Idee, ein Programm zu schreiben, um die SQL zu parsen und sauber auszudrucken. Ich habe das meiste ziemlich schnell gemacht, aber ich stieß auf ein Problem, das ich nicht zu lösen weiß.

Lassen Sie uns also so tun, als wäre die SQL-Tabelle "Wählen Sie foo von der Bar wo 1". Mein Gedanke war, dass es immer ein Schlüsselwort gibt, gefolgt von Daten dafür, also muss ich nur ein Schlüsselwort analysieren und dann das ganze Kauderwelsch vor dem nächsten Schlüsselwort erfassen und das für spätere Säuberung speichern, wenn es sich lohnt. Hier ist der Code:

%Vor%

Der Schlüssel hier ist der Stuffparser. Das ist das Zeug zwischen den Schlüsselwörtern, die von Spaltenlisten bis zu Kriterien reichen können. Diese Funktion fängt alle Zeichen ab, die zu einem Schlüsselwort führen. Aber es braucht noch etwas, bevor es fertig ist. Was ist, wenn es einen Subselect gibt? "ID auswählen, (Produkt von Produkten auswählen) von Bar". Nun, in diesem Fall, wenn es dieses Schlüsselwort trifft, verschraubt es alles, parst es falsch und verschraubt meine Einrückung. Auch Where-Klauseln können Klammern haben.

Also muss ich den anyChar in einen anderen Kombinator ändern, der die Zeichen nacheinander auffüllt, aber auch nach Klammern sucht, und wenn er sie findet, traverse und erfasse all das, aber auch, wenn es mehr Klammern gibt bis wir die Klammer vollständig geschlossen haben, verketten wir alles und geben es zurück. Hier ist, was ich versucht habe, aber ich kann es nicht richtig zum Laufen bringen.

%Vor%

Dies wird wie folgt aussehen:

%Vor%

Aber ich kann mir keine Möglichkeit vorstellen, das so umzuschreiben, dass es funktioniert. Ich habe versucht, vieleTill auf den Klammerteil zu verwenden, aber ich habe Probleme damit, es zur Typüberprüfung zu bringen, wenn ich beide Zeichenfolgen als Alternative zu Parens und einzelnen Zeichen erzeuge. Hat jemand irgendwelche Vorschläge, wie das geht?

    
David McHealy 18.07.2011, 11:34
quelle

1 Antwort

5

Ja, between funktioniert möglicherweise nicht für das, wonach Sie suchen. Für Ihren Anwendungsfall würde ich natürlich dem Vorschlag von hammar folgen und einen Standard-SQL-Parser verwenden. (persönliche Meinung: oder, versuchen Sie nicht, SQL zu verwenden, es sei denn, Sie müssen wirklich; die Idee, Strings für Datenbankabfragen zu verwenden, war ein historischer Fehler).

Hinweis: Ich füge einen Operator namens <++> hinzu, der die Ergebnisse zweier Parser verketten wird, unabhängig davon, ob es sich um Zeichenfolgen oder Zeichen handelt. (Code unten.)

Erstens, für die Aufgabe Parsen zu analysieren: Die oberste Ebene wird einige Dinge zwischen den relevanten Zeichen analysieren, was genau der Code sagt,

%Vor%

Dann sollte die inner -Funktion alles andere parsen: Nicht-Parens, möglicherweise einschließlich eines anderen Satzes von Klammern, und nicht-Paren-Junk, der folgt.

%Vor%

Ich nehme an, dass für den Rest der Lösung das, was Sie tun wollen, analog ist, Dinge durch SQL-Schlüsselwörter der obersten Ebene aufzuteilen. (d. h. ignorieren diese in Klammern). Wir haben nämlich einen Parser, der sich so verhält,

%Vor%

Angenommen, wir haben einen parseKw Parser, der% com_de% usw. erhält. Nachdem wir ein Schlüsselwort konsumiert haben, müssen wir bis zum nächsten [top-level] Schlüsselwort lesen. Der letzte Trick für meine Lösung besteht darin, mit dem select -Kombinator festzustellen, ob das nächste Wort ein Schlüsselwort ist, und es zurückzusetzen, wenn dies der Fall ist. Wenn dies nicht der Fall ist, nehmen wir eine Klammer oder ein anderes Zeichen und suchen dann den Rest.

%Vor%

Meine gesamte Lösung ist wie folgt

%Vor%

edit - Version mit Zitatunterstützung

Sie können dasselbe tun wie bei den Parens, um Zitate zu unterstützen,

%Vor%

Ich habe es mit lookAhead versucht. Prost

    
gatoatigrado 19.07.2011, 04:35
quelle

Tags und Links