2015-12-30 11 views
9

Um zu betonen, möchte ich nicht "parse mit einem Regex" - Ich möchte "eine Regex in einen symbolischen Baum zu analysieren." (Suche hat nur die ehemalige herauf gebracht ...)Python-Bibliothek, um Regex in AST zu analysieren?

Mein Anwendungsfall: Um eine Regex-Suche über eine Datenbank zu beschleunigen, würde ich gerne einen Regex wie (foo|bar)baz+(bat)* analysieren und alle Teilstrings herausziehen, die in einem erscheinen müssen Spiel. (In diesem Fall ist es nur baz, weil foo/bar sind Alternationen und bat kann 0 mal erscheinen.)

Um dies zu tun, brauche ich ein gewisses Verständnis von Regex-Operatoren/Semantik. re.DEBUG am nächsten kommt:

In [7]: re.compile('(foo|bar)baz+(bat)', re.DEBUG) 
subpattern 1 
    branch 
    literal 102 
    literal 111 
    literal 111 
    or 
    literal 98 
    literal 97 
    literal 114 
literal 98 
literal 97 
max_repeat 1 4294967295 
    literal 122 
subpattern 2 
    literal 98 
    literal 97 
    literal 116 

Allerdings ist es den Ausdruck nur, und die c-Implementierung erhält nicht die Struktur danach soweit ich das beurteilen kann. Irgendwelche Ideen, wie ich das analysieren kann, ohne meinen Parser zu schreiben?

+2

wie über einen regulären Ausdruck über die regeg mit Muster? – Netwave

+4

@DanielSanchez Sie können keine regulären Ausdrücke mit einem regulären Ausdruck analysieren. – BlackJack

+0

@BlackJack, Sie können die Regex-Zeichenfolge regex, ich meine, wenn ich "1 | 2" für meine Regex haben y kann diese Zeichenfolge regex. – Netwave

Antwort

2

Sie können nur einen (klassisch) Regex mit einer kontextfreien Grammatik angeben:

regex = { alternatives }; 
alternatives = primitive { '|' alternatives } ; 
primitive = '(' regex ')' | '[' character_set ']' | ... 

Das heißt, Sie einen regulären Ausdruck mit einem regex nicht analysieren kann (Perl ist eine Ausnahme, aber dann seine „Regexes "sind weit über" klassisch "hinaus").

Also, um eine Regex zu parsen, müssen Sie Ihren eigenen Parser erstellen und eine Art Baum (re.Debug kommt ziemlich nah) oder die magische Bibliothek, die Sie sich erhoffen.

Ich vermute, das ist der einfache Teil. Das ist nicht sehr schwer selbst zu tun; siehe Is there an alternative for flex/bison that is usable on 8-bit embedded systems? für ein einfaches Schema zum Aufbau solcher Parser.

Um die Semantik der Regex zu verstehen (zB „notwendig Substrings“, um herauszufinden), Sie könnten in der Lage sein, um wegzukommen mit einem Analysator die Spaziergänge über den Parsing-Baum bauen, und für jeden Unterbaum (unten up), berechnet die Common-String. Andernfalls müssen Sie möglicherweise die klassische NDFA-Konstruktion implementieren und dann darüber hinweggehen oder die NDFA in die DFA-Konstruktion implementieren und über die DFA gehen. Echte Regexes neigen dazu, viele unordentliche Komplikationen wie integrierte Zeichensätze, Erfassungsgruppen usw. zu enthalten.

Die "gemeinsame Zeichenkette" ist möglicherweise nicht nur eine zusammenhängende Folge von Zeichen, obwohl Sie sie als solche eng definieren könnten. Es könnte mehrere konstante Teil durch feste oder variable Länge Lücken von Zeichen getrennt sind zB Ihre notwendigen Teilzeichenfolge könnte sich immer als eine „einfache regex“ der Form ausdrückbar sein:

(<character>+ ?+) <character>+ 
+0

Ja, ich hatte gehofft, dass es eine Regex-Bibliothek gibt, die mich über den NDFA- oder Parse-Baum laufen lässt; Ich habe ANTLR und dergleichen ein paar Mal benutzt und vermisse es überhaupt nicht ...re: the "simple regex", Sie treffen Komplikationen mit Beispielen wie '(ab +) *', wo am Ende des Tages keine Teilstrings benötigt werden. Wie auch immer, danke für die Perspektive, das ist nützlich (obwohl die Frage offen bleibt, falls jemand Ideen hat, die mich davon abhalten, mich selbst zu analysieren) – munchybunch

Verwandte Themen