Spirit (Parser) – Wikipedia
Spirit ist ein mittels Templatemetaprogrammierung implementierter rekursiv absteigender Parsergenerator. Die Benutzung der erweiterten Backus-Naur-Form (EBNF) in C++ wird mithilfe von Ausdrucks-Templates ermöglicht. Die Parser-Objekte werden durch Überladen von Operatoren erstellt und ergeben einen LL-Parser, der in der Lage ist, mehrdeutige Ausdrücke auszuwerten.
Spirit kann zusammen und getrennt für lexikalische Analyse sowie auch für einfaches Parsen benutzt werden.
Der Spirit-Parser ist Bestandteil der freien Boost-Bibliothek.
Operatoren
[Bearbeiten | Quelltext bearbeiten]Aufgrund von Beschränkungen seitens der Programmiersprache C++ wurde die Spirit-Syntax um die Operatoren-Rangfolge aufgebaut, wobei Ähnlichkeiten zu EBNF sowie regulären Ausdrücken erhalten bleiben.
Syntax | Erläuterung |
---|---|
x >> y | Entspricht x gefolgt von y. |
*x | Entspricht x null oder mindestens einmal. (Repräsentiert die kleenesche Hülle; C++ hat keinen unären Postfix-Operator * ) |
x | y | Entspricht x oder y. |
+x | Entspricht x mindestens einmal. |
-x | Entspricht x null oder einmal. |
x & y | Entspricht x und y. |
x - y | Entspricht x, aber nicht y. |
x ^ y | Entspricht x, y oder beiden zusammen (in beliebiger Reihenfolge). |
x [ Funktionsausdruck ] | Ruft die Funktion (oder den Funktor) auf, die (oder der) function_expression zurückgibt, wenn x wahr ist. |
( x ) | Entspricht x (kann für Rangfolgen-Gruppierungen benutzt werden) |
x % y | Entspricht eine oder mehrere Wiederholungen von x, getrennt durch Vorkommnisse von y. |
~x | Entspricht allem außer x (nur mit Zeichenklassen wie ch_p oder alnum_p) |
Beispiel
[Bearbeiten | Quelltext bearbeiten]Spirit.Classic
[Bearbeiten | Quelltext bearbeiten]#include <boost/spirit.hpp> #include <boost/spirit/actor.hpp> #include <string> #include <iostream> using namespace std; using namespace boost::spirit; int main() { string input; cout << "Gib eine Zeile ein.\n"; getline(cin, input); cout << "Eingabe: '" << input << "'.\n"; unsigned count = 0; /* Die nächste Zeile parst die Eingabe (input.c_str()) mittels folgender Semantik (Einrückung entspricht dem Quellcode zwecks Übersichtlichkeit): Null oder mehr Vorkommnisse von ( Buchstabenfolge "Katze" (wenn wahr, erhöhe Zählvariable "count") oder jedes anderen Zeichens (fortschreiten, um nächstes Vorkommnis von "Katze" zu finden) ) */ parse(input.c_str(), *( str_p("Katze") [ increment_a(count) ] | anychar_p )); /* Der Parser wird mithilfe von Operatorüberladungen und Template-Matching gebaut, d.h. die eigentliche Arbeit wird in spirit::parse() erledigt und der Ausdruck, der mit * anfängt, initialisiert lediglich das Regelwerk, das die Parser-Funktion benutzt. */ // Zeige schließlich das Ergebnis. cout << "Die Eingabe hatte " << count << " Vorkommnisse von 'Katze'\n"; }
Es gibt andere Algorithmen, die zum Durchsuchen von Zeichenketten besser geeignet sind. Dieses Beispiel ist nur zur Veranschaulichung des Konzepts gedacht, wie Regeln erstellt und diesen Aktionen zugewiesen werden.
Spirit 2.x
[Bearbeiten | Quelltext bearbeiten]Das folgende Programm gibt für Eingabestrings (gegeben als Kommandozeilenargument) "OKAY" aus, wenn sie der Regel entsprechen, andernfalls "NOT OKAY":
#include <boost/spirit/include/qi.hpp> #include <string> #include <iostream> // shortcuts namespace qi = boost::spirit::qi; typedef qi::rule<std::string::const_iterator, std::string()> Rule; Rule ab0; Rule ab; int main(int argc, char** argv) { Rule ab_alias = ab0.alias(); ab0 = qi::char_('a') >> -ab_alias >> qi::char_('b'); ab = (ab0 | qi::eps) >> qi::eoi; const std::string input = argc>1 ? argv[1] : ""; auto begin = input.begin(); bool okay = qi::parse(begin, input.end(), ab ); std::cout << "String \"" << input << "\" is " << (okay ? "OKAY" : "NOT OKAY") << ".\n"; return okay != true; }
Weblinks
[Bearbeiten | Quelltext bearbeiten]- Spirit bei Sourceforge