2013-05-27 4 views
5

Ich konnte keine Grammatik zum arbeiten bekommen, also habe ich es vereinfacht, bis es nur eine Ganzzahl analysiert. Kann es immer noch nicht zur Arbeit bringen. Es ist die folgende Grammatik:Mit einfachen Boost :: Spirit Grammatiken?

template<typename Iterator> 
struct rangeGrammar : qi::grammar<Iterator, int()> 
{ 
    rangeGrammar() : 
    rangeGrammar::base_type(number) 
    { 
     using qi::int_; 
     using qi::_1; 
     using qi::_val; 

     number = int_[_val = _1]; 
    } 
    qi::rule<Iterator, int()> number; 
}; 

Es soll nur eine ganze Zahl parsen (ich weiß, dass ich nur die Parsing-Funktion sagen könnte, wie die Grammatik verwenden int_, aber ich wan't zu wissen, was in dieser falsch ist Beispiel).

Meine Parse-Funktion ist:

/* n is a std::string provided by the user */ 
rangeGrammar<std::string::const_iterator> grammar; 
int num = 0; 
qi::phrase_parse(n.start(), n.end(), grammar, num); 
std::cout << "Number: " << num << std::endl; 

ich den folgenden Compiler-Fehler:

/boost/spirit/home/qi/reference.hpp: In member function ‘bool boost::spirit::qi::reference::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator >, Context = boost::spirit::context, boost::spirit::locals<> >, Skipper = boost::spirit::unused_type, Attribute = int, Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator >, int(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>]’: /boost/spirit/home/qi/parse.hpp:89:82: instantiated from ‘bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator >, Expr = rangeGrammar<__gnu_cxx::__normal_iterator > >, Attr = int]’ ../parameter_parser.h:95:46: instantiated from here boost/spirit/home/qi/reference.hpp:43:71: error: no matching function for call to ‘boost::spirit::qi::rule<__gnu_cxx::__normal_iterator >, int(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>::parse(__gnu_cxx::__normal_iterator >&, const __gnu_cxx::__normal_iterator >&, boost::spirit::context, boost::spirit::locals<> >&, const boost::spirit::unused_type&, int&) const’ cc1plus: warnings being treated as errors /boost/spirit/home/qi/reference.hpp:44:9: error: control reaches end of non-void function * exit status 1 *

Kann nicht herausfinden, was das Problem ist. Jede Hilfe würde sehr geschätzt werden.

+7

lol @ "simple boost :: spirit Grammatiken" –

+2

Wie Sie entdeckt haben, gibt es keine einfachen Boost-Geist-Grammatiken. Verwenden Sie stattdessen ANTLR. –

+0

Ich sprach neulich mit einem netten Kerl vom Boost "Team" im IRC und fragte, warum Spirit eine so geringe Dokumentationsabdeckung hat. Er rief aus, dass es tatsächlich sehr gut dokumentiert ... +1 für den Einsatz ANTLR. – Kivin

Antwort

11

A: Es gibt nichts wenig falsch mit der Grammatik, aber Sie verwenden qi::phrase_parse, die einen Skipper erfordert. Verwenden Sie qi::parse und das Problem verschwindet.

Hinweis 1: Die Verwendung von [_val=_1] ist dort vollständig redundant; Regeln ohne semantische Attribute genießen automatische Attributausbreitung.

Anmerkung 2: Sie könnten Qi :: Spiel verwenden möchten, wie dies zu tun Parsen:

#include <boost/spirit/include/qi_match.hpp> 

const std::string input = "1234"; 
std::istringstream iss(input); 
iss >> qi::match(qi::int_ [ std::cout << qi::_1 ]); 

Schließlich Für Ihr Interesse, hier ist eine Skelett-Funktion ‚doParse‘ mit, dass zeigt Test läuft einige weitere Elemente guter Qi Praxis:

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 

template<typename Iterator> 
struct rangeGrammar : qi::grammar<Iterator, int()> 
{ 
    rangeGrammar() : rangeGrammar::base_type(number) 
    { 
     number = qi::int_; 
    } 
    qi::rule<Iterator, int()> number; 
}; 

bool doParse(const std::string& input) 
{ 
    typedef std::string::const_iterator It; 
    It f(begin(input)), l(end(input)); 

    try 
    { 
     rangeGrammar<It> p; 
     int data; 

     bool ok = qi::parse(f,l,p,data); 
     if (ok) 
     { 
      std::cout << "parse success\n"; 
      std::cout << "data: " << data << "\n"; 
     } 
     else  std::cerr << "parse failed: '" << std::string(f,l) << "'\n"; 

     if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n"; 
     return ok; 
    } catch(const qi::expectation_failure<It>& e) 
    { 
     std::string frag(e.first, e.last); 
     std::cerr << e.what() << "'" << frag << "'\n"; 
    } 

    return false; 
} 

int main() 
{ 
    bool ok = doParse("1234"); 
    return ok? 0 : 255; 
} 
+0

Danke für die Antwort! Sie haben Recht, parse_phrase() muss einen Skipper enthalten, das war mir nicht bewusst. Ich habe meinen Code geändert, um stattdessen parse() zu verwenden, aber derselbe Fehler bleibt bestehen. Wenn Sie den ersten Fehler lesen, heißt es: "Fehler: keine passende Funktion für den Aufruf von 'boost :: spirit :: qi :: rule <..." Vielleicht hat es etwas mit der einzigen Regel zu tun, die ich habe? Aber ich sehe nichts falsch daran. Ich bin mir auch bewusst, dass es viel einfachere Wege gibt, um das zu erreichen, was ich versuche, aber ich habe die Grammatik vereinfacht, um meinen Fehler zu finden. – jay1189947

+0

Endlich ist es gelöst. Der Fehler war, dass ich einen Iterator über eine Zeichenkette und nicht eine konstante Zeichenkette verwendete ... Ich fühle mich wirklich dumm. Dein Code hat mir das klar gemacht, danke nochmal für die Antwort! – jay1189947

+0

Freut mich zu hören, dass es funktioniert :) – sehe