2014-02-22 7 views
6
#include <iostream> 
#include <boost/spirit/include/qi.hpp> 

namespace qi = boost::spirit::qi; 
int main() 
{ 
    using qi::string; 

    std::string input("a"); 
    std::string::iterator strbegin = input.begin(); 
    std::string p; 
    bool ok = qi::phrase_parse(strbegin, input.end(), 
      ((string("a") >> string("a")) | string("a")), 
      qi::space,     
      p);        

    if (ok && strbegin == input.end()) { 
     std::cout << p << std::endl; 
     std::cout << p.size() << std::endl; 
    } else { 
     std::cout << "fail" << std::endl; 
     std::cout << std::string(strbegin, input.end()) << std::endl; 
    } 
} 

Dieses Programm gibt aa aus. Wie ist es möglich? Eingabezeichenfolge ist a. Parser sollte aa oder a entsprechen. Ich habe string("a") nur zum Testen von Betreibern geschrieben.Boost.spirits String-Parser verstehen

Das gleiche gilt, wenn char_ anstelle von string verwendet wird.

+0

Gerade stolperte wieder in diese sehr ähnliche Frage: http://stackoverflow.com/q/13869978/85371 – sehe

Antwort

6

Es ist nicht der String-Matcher an sich. Es ist [attribute propagation] + [backtracking] in Aktion.

Ein Zeichenfolgenattribut ist ein Containerattribut, und viele Elemente können von verschiedenen Parserunterausdrücken zugewiesen werden. Aus Gründen der Effizienz setzt Spirit die Werte der emittierten Attribute beim Backtracking nicht zurück.

Oft ist das überhaupt kein Problem, aber wie Sie sehen können, bleibt das 'a' aus dem gescheiterten ersten Zweig der Alternative stecken.

Entweder umformulieren oder verwenden, um die ‚große Kanone‘ qi::hold[] Richtlinie:

(qi::hold [ string("a") >> string("a") ] | string("a")), 

Umformulierung aussehen könnte:

qi::string("a") >> -qi::string("a"), 

Auch wenn Sie wirklich nur versuchen, bestimmte Textzeichenfolgen übereinstimmen, betrachten:

(qi::raw [ qi::lit("aa") | "a" ]), 
// or even just 
qi::string("aa") | qi::string("a"), 

Nun, die eine davon die meisten gilt, auf Ihrem Gramm hängt beschädigen.