Boolescher Ausdruck (Grammatik) Parser in C ++
Möchte ich analysieren, ein boolescher Ausdruck (in C++). Input form:
a and b xor (c and d or a and b);
Ich will nur analysieren, diesen Ausdruck in einen Baum, wissend, dass die Vorrang-Regel (not,and,xor,or).
Also der obige Ausdruck soll so Aussehen:
(a and b) xor ((c and d) or (a and b));
den parser.
Und die Struktur der form:
a
and
b
or
c
and
d
xor
a
and
b
Wird die Eingabe entweder über die Befehlszeile oder in der form einer Zeichenfolge.
Ich brauche nur den parser.
Gibt es irgendwelche Quellen, die mir helfen können, dies zu tun?
InformationsquelleAutor der Frage A Gore | 2012-01-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist eine Umsetzung basierend auf Boost Geist.
Weil Boost Geist erzeugt rekursiven Abstieg Parser basiert auf expression templateszu Ehren der 'eigenwilligen' (sic) Vorrang (wie von anderen erwähnt) ist ziemlich langweilig. Deshalb ist die Grammatik fehlt eine gewisse Eleganz.
Abstrakten Datentyp
Definierte ich eine Baumstruktur mit Boost Variante der rekursiven Variante unterstützen, beachten Sie die definition von expr:
(source unten)
Grammatik-Regeln
Im folgenden ist die (etwas mühsame) Grammatik definition, wie bereits erwähnt.
Obwohl ich nicht betrachten dieser Grammatik optimal, es ist durchaus lesbar, und wir haben uns ein statisch kompiliert parser mit stark typisierten AST-Datentyp in etwa 50 Zeilen code. Dinge könnten wesentlich schlechter.
Betriebssystem auf dem syntax-Baum
Offensichtlich wollen Sie auswerten der Ausdrücke. Für jetzt, ich beschlossen, zu stoppen auf Druck, so dass ich nicht haben, um die lookup-Tabelle für die Variablen bezeichnet 🙂
Durchqueren eine rekursive Variante sieht vielleicht kryptisch auf den ersten, aber die
boost::static_visitor<>
ist überraschend einfach, sobald Sie den Dreh raus:Test Ausgabe:
Für die Testfälle im code folgende Ausgabe demonstriert richtige Umgang mit den Vorrang-Regeln durch hinzufügen von (unnötigen) Klammern:
Vollständige Code:
Bonus:
Für bonus-Punkte zu bekommen, ein Baum-genau wie im OP:
Ergebnis:
InformationsquelleAutor der Antwort sehe
Entweder einen parser-generator wie Oli Charlesworth bereits erwähnt (yacc, bison, antlr; die letztere ist meiner Erfahrung nach besser geeignet, C++ als die beiden anderen ist es zwar eine Weile, ich sah jeden von Ihnen) oder erstellen eines einfachen recursive descent parsers: eine Sprache so einfach wie die Eure, kann dies der einfachere Ansatz.
InformationsquelleAutor der Antwort Dietmar Kühl
Sehen meine Antwort, wie man code einfach recursive-descent-Parser.
Dieser Ansatz ist sehr praktisch für einfache Sprachen wie Boolesche Ausdrücke. Und die Konzepte sind so ziemlich unabhängig von der Programmiersprache.
InformationsquelleAutor der Antwort Ira Baxter
Wenn Sie, wie ich, finden die overhead-und die Eigenheiten der parsing-libraries zu viel für so einen kleinen job haben, können Sie sehr einfach schreiben Sie Ihre eigenen parser für ein einfaches Szenario, wie Sie Sie präsentieren. Sehen hier für einen parser schrieb ich in C# zu analysieren, einfache C# - Ausdrücke, die Analog zu Ihren Anforderungen.
InformationsquelleAutor der Antwort Kent Boogaart
Haben Sie einen Blick auf die Mini-C-Beispiel-code https://github.com/boostorg/spirit/tree/master/example/qi/compiler_tutorial/mini_c.
Vor allem haben Sie einen Blick auf die expression.cpp Ausdruck.hpp, expression_def.hpp, und ast.hpp. Es gibt ein tolles Beispiel, wie das Parsen von Ausdrücken in eine AST.
InformationsquelleAutor der Antwort gvd