Ich arbeite an einem Parser für eine Sprache im C-Stil, und für diesen Parser benötige ich den regulären Ausdruck, der mit C-Stil / ** / Kommentare übereinstimmt. Jetzt habe ich diesen Ausdruck im Web gefunden:
/\*([^\*]*\*+[^\*/])*([^\*]*\*+|[^\*]*\*/
Wie Sie sehen, ist dies jedoch ein ziemlich chaotischer Ausdruck, und ich habe keine Ahnung, ob er tatsächlich genau dem entspricht, was ich möchte.
Gibt es eine andere Möglichkeit, reguläre Ausdrücke (rigoros) zu definieren, die leicht von Hand überprüft werden können, ob sie wirklich korrekt sind, und die dann in den obigen regulären Ausdruck konvertierbar ("kompilierbar") sind?
compilers
parsers
regular-languages
Alex ten Brink
quelle
quelle
(!\*)
beabsichtigt? Meinen Sie die häufigere Notation[^*]
? Und was ist(!*|!/)
?Antworten:
Ich kann mir vier Möglichkeiten vorstellen:
Definieren Sie einen Automaten für die Sprache, die Sie interessiert. Konvertieren Sie den regulären Ausdruck in einen Automaten (unter Verwendung von Brzozowskis Ableitungen). Überprüfen Sie, ob beide Automaten dieselbe Sprache akzeptieren (bestimmen und minimieren oder verwenden Sie ein Bisimulationsargument).
Schreiben Sie viele Testfälle und wenden Sie Ihren regulären Ausdruck auf sie an.
Konvertieren Sie den in Punkt 1 definierten Automaten mithilfe von Standardtechniken in einen regulären Ausdruck.
Eine Kombination der oben genannten.
quelle
Wenn Sie sicher sein möchten, dass Sie C-Kommentare analysieren, müssen Sie Ihr Modell mit der C-Spezifikation konfrontieren. C99 §6.4.9 definiert die Syntax von Kommentaren wie folgt:
Dies ist englische Prosa, keine formale Definition, aber es gibt eine einigermaßen klare Interpretation in Bezug auf einen nichtdeterministischen endlichen Automaten (NFA), der einen Kommentar verbraucht:
/
gefolgt von dem*
Eintritt in den mehrzeiligen Kommentarzustand und/
gefolgt von dem/
Eintritt in den einzeiligen Kommentarzustand ein.*
gefolgt vom/
Status "Post-Kommentar".Beachten Sie, dass Sie, um zu wissen, ob der Anfangszustand zutrifft, etwas mehr Analysen durchführen müssen, um Zeichenfolgen- und Zeichenliterale zu erkennen.
Sobald Sie eine NFA haben, können Sie Standardtechniken verwenden, um einen regulären Ausdruck zu erstellen (ich sehe sie nicht in den Wikipedia-Artikeln, aber sie sollten in Lehrbüchern besprochen werden).
Wenn Sie bereits einen regulären Ausdruck haben und ihn testen möchten, können Sie seine generierte Sprache mit der aus der NFA abgeleiteten Sprache vergleichen, die aus der Sprachspezifikation abgeleitet wurde: Die Gleichheit der regulären Sprachen ist entscheidbar. Eine Möglichkeit, die Gleichheit zu bestimmen, besteht darin, für jeden einen minimalen deterministischen Automaten zu erstellen. Wenn die Sprachen äquivalent sind, sind die minimalen DFAs isomorph.
quelle
Wenn Sie einen Parser schreiben, werden diese Dinge vom lexikalischen Analysator verarbeitet. Und dort können Sie dies durch reguläre Ausdrücke ausdrücken oder (wie die
flex
Beispiele, die ich gesehen habe) einfach "in die zugrunde liegende Sprache entkommen" und den Job dort beenden. Das heißt,/*
wenn Sie sehen, springen Sie einfach weiter, bis Sie es finden*/
(ein DFA dafür ist einfach zu erstellen, und von dort aus ist ein C-Fragment einfach zu schreiben).quelle