Zum Inhalt springen

Spirit (Parser)

aus Wikipedia, der freien Enzyklopädie

Vorlage:Hinweisbaustein

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]

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]

Spirit.Classic[Bearbeiten]

Vorlage:Hinweisbaustein

<syntaxhighlight lang="cpp" style="font-size:75%;">

  1. include <boost/spirit.hpp>
  2. include <boost/spirit/actor.hpp>
  3. include <string>
  4. 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";

} </syntaxhighlight>

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]

Das folgende Programm gibt für Eingabestrings (gegeben als Kommandozeilenargument) "OKAY" aus, wenn sie der Regel <math>\left\{a^nb^n \mid n\in \mathbb{N}_0\right\}</math> entsprechen, andernfalls "NOT OKAY":

<syntaxhighlight lang="cpp">

  1. include <boost/spirit/include/qi.hpp>
  2. include <string>
  3. 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;

}

</syntaxhighlight>

Weblinks[Bearbeiten]