Benötigt die Sprache regulärer Ausdrücke Push-Down-Automaten, um sie zu analysieren?

12

Ich möchte einen von einem Benutzer eingegebenen regulären Ausdruck in einen NFA konvertieren, damit ich den NFA dann zu Übereinstimmungszwecken für eine Zeichenfolge ausführen kann. Was ist die minimale Maschine, die verwendet werden kann, um reguläre Ausdrücke zu analysieren?

Ich gehe davon aus, dass es sich um einen Push-Down-Automaten handeln muss, da das Vorhandensein von Klammern eine Zählung erforderlich macht und ein DFA / NFA keine willkürliche Zählung durchführen kann. Ist diese Annahme richtig? Zum Beispiel würde der Ausdruck a (bc *) d einen PDA erfordern, damit der Unterausdruck in Klammern korrekt behandelt wird.

Phil Wright
quelle
1
Was genau meinst du mit "Parsen"? Wollen Sie überprüfen, ob es sich bei der Eingabe wirklich um einen regulären Ausdruck handelt, oder haben Sie etwas Komplizierteres im Sinn, z. B. eine Maschine, die eine Beschreibung der entsprechenden NFA ausgibt? (Wenn Sie nicht sicher sind, ob die Eingabe wirklich ein regulärer Ausdruck ist und Sie sie überprüfen müssen, müssen Sie in der Lage sein, zu überprüfen, ob die Klammern korrekt sind und normalerweise einen Stapel verwenden.)
Kaveh
Für eine praktische Antwort, schauen Sie auf die könnte für grep.y Plan 9 Grep Quelle .
Bruce Ediger

Antworten:

8

Du hast Recht. Es ist leicht zu zeigen, dass die Syntax regulärer Ausdrücke mit Standardtechniken nicht regulär ist .

REG(p)p

Allerdings möchten Sie wahrscheinlich keinen PDA von Hand codieren. Erwägen Sie die Verwendung eines Parser-Generators wie ANTLR oder byacc . Wenn Sie andererseits das Parsen von Sprachen untersuchen möchten, indem Sie Parser selbst programmieren, sollten Sie mit anderen grundlegenden Parsing-Algorithmen wie CYK , Earley , rekursiver Abstieg und LR fortfahren .

Raphael
quelle
Vielen Dank. Das Schreiben von Code für diese Aufgaben schafft ein besseres Verständnis und soll nicht so effizient sein wie vorhandene Dienstprogramme wie Lex, Yacc, Bison usw.
Phil Wright
@ PhilWright: Ich verstehe, schön! Ich habe in weiteren Zeigern für diesen Fall bearbeitet.
Raphael
Ich würde einen handcodierten rekursiven Abstiegsparser für diesen bevorzugen.
Dave Clarke
Wenn Sie hierfür einen Parser von Hand schreiben, kann der LCC-Parser für C < sites.google.com/site/lccretargetablecompiler > rekursives Absteigen (nach Faktorisierung und Massieren) für die Verarbeitung vieler Operatoren in Betracht ziehen . Am einfachsten für die manuelle Erstellung ist das Parsen der Prioritäten.
Vonbrand
3

Ich schlage vor, die schöne Antwort von Jukka auf die Frage " Übereinstimmende reguläre Ausdrücke mit regulären Ausdrücken " auf cstheory zu lesen. Ein Ausschnitt:

Beispielsweise können wir die Standardnotation wie folgt ändern, um "komprimierte" reguläre Ausdrücke zu erhalten :

  • Sie dürfen jedes Präfix entfernen, das aus einer Folge von ('s besteht
  • Sie dürfen jedes Suffix entfernen, das aus einer Folge von) besteht

Das heißt, ((a|b)*c)de(f|g)kann in der "komprimierten" Notation zum Beispiel unter Verwendung einer der folgenden Formen ausgedrückt werden: a|b)*c)de(f|goder ((a|b)*c)de(f|goder (a|b)*c)de(f|g).

[...]

Die "komprimierte" Notation (eines regulären Ausdrucks) ist eine reguläre Sprache.

Dies ist nur ein Link zu einer interessanten (meiner Meinung nach) "anderen Sichtweise" auf die Sprache des regulären Ausdrucks; Wie in den Kommentaren unten unterstrichen, ist es nicht nützlich, um einen Syntaxbaum zu erstellen. Wenn Sie Ihren Parser aus der Hand geben möchten, empfehle ich Ihnen diesen einfachen Artikel über das Codeprojekt " Schreiben eines eigenen Parsers für reguläre Ausdrücke ".

Vor
quelle
Jukka beseitigt im Wesentlichen das Erfordernis, dass Klammern ausgeglichen sind. Ich kenne keinen Fall, in dem dies tatsächlich geschieht, aber es ist erwähnenswert, dass Sie durch Ändern der Semantik die Syntax "vereinfachen" können.
Raphael
4
Sie (und Jukka) analysieren keine regulären Ausdrücke, sondern erkennen sie nur. "Yup, das ist ein (komprimierter) regulärer Ausdruck."
Gilles '