Spirit (parser)

from Wikipedia, the free encyclopedia

Spirit is a recursively descending parser generator implemented using template meta programming . The use of the extended Backus-Naur-Form (EBNF) in C ++ is made possible with the help of expression templates. The parser objects are created by overloading operators and result in an LL parser that is able to evaluate ambiguous expressions.

Spirit can be used together and separately for lexical analysis as well as simple parsing.

The Spirit parser is part of the free Boost library.

Operators

Due to restrictions on the part of the C ++ programming language, the Spirit syntax was built around the operator precedence, whereby similarities to EBNF and regular expressions are retained.

syntax Explanation
x >> y Matches x followed by y.
* x Matches x zero or at least once. (Represents the Kleen's shell ; C ++ does not have a unary postfix operator *)
x | y Matches x or y.
+ x Matches x at least once.
-x Matches x zero or one time.
x & y Matches x and y.
x - y Matches x but not y.
x ^ y Matches x, y, or both (in any order).
x [function_expression] Calls the function (or functor) that returns function_expression when x is true.
(x) Corresponds to x (can be used for precedence groupings)
x% y Matches one or more repetitions of x, separated by occurrences of y.
~ x Matches everything except x (only with character classes like ch_p or alnum_p)

example

Spirit.Classic

#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";
}

There are other algorithms that are more suitable for searching strings. This example is only intended to illustrate the concept of creating rules and assigning actions to them.

Spirit 2.x

The following program outputs "OKAY" for input strings (given as command line argument) if they match the rule , otherwise "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;
}

Web links