2013-05-27 14 views
5

Nie mogłem uzyskać gramatyki do pracy, więc uprościłem ją, dopóki nie analizuje liczby całkowitej. Nadal nie mogę go uruchomić. To jest następująca gramatyka:Korzystanie z prostych gramatyk Boost :: Spirit?

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

ona ma po prostu przeanalizować liczbę całkowitą (wiem, mogę tylko powiedzieć, że funkcja parse używać int_ jako gramatyki, ale wa nie wiedzieć, co jest złego w tym przykład).

Moja funkcja parse jest:

/* 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; 

pojawia się następujący błąd kompilatora:

/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 *

nie może dowiedzieć się, na czym polega problem. Każda pomoc będzie bardzo ceniona.

+7

lol @ „prosty boost :: duch gramatyk” –

+2

Jak odkryli, nie ma prostych gramatyki doładowania ducha. Zamiast tego użyj ANTLR. –

+0

Pewnego dnia rozmawiałem z miłym facetem z "drużyny" na IRC i zapytałem, dlaczego Spirit ma tak niski zasięg dokumentacji. Wykrzyknął, że jest to bardzo dobrze udokumentowane ... +1 za użycie ANTLR. – Kivin

Odpowiedz

11

A: Istnieje nic trochę tak z gramatyki, ale używasz qi::phrase_parse która wymaga szypra. Użyj qi::parse, a problem zniknie.

Uwaga 1: Używanie [_val=_1] jest tam całkowicie nadmiarowe; zasady bez atrybutów semantycznych korzystają z automatycznej propagacji atrybutów .

Uwaga 2: Możesz chcieć użyć qi :: meczu zrobić parsowania tak:

#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 ]); 

Wreszcie za zainteresowanie, oto szkielet funkcja „doParse” z prowadzeniem testu, który pokazuje kilka elementów dobrej praktyki Qi:

#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

Dzięki za odpowiedź! Masz rację, parse_phrase() musi zawierać szypera, nie wiedziałem o tym. Zmieniłem kod, aby zamiast tego używał parse(), ale ten sam błąd nadal występuje. Jeśli czytasz pierwszy błąd, to mówi: "błąd: brak pasującej funkcji dla wywołania do 'boost :: spirit :: qi :: rule <..." może to ma coś wspólnego z jedyną regułą, którą mam? Ale nie widzę w tym nic złego. Jestem również świadomy, że istnieje znacznie prostszy sposób na wykonanie tego, co próbuję zrobić, ale uprościłem gramatykę, aby móc znaleźć mój błąd. – jay1189947

+0

W końcu to rozwiązałem. Błędem było to, że używałam iteratora przez ciąg, a nie ciąg const ... Czuję się naprawdę głupio. Twój kawałek kodu uświadomił mi to, dzięki jeszcze raz za odpowiedź! – jay1189947

+0

Miło słyszeć, że to działa :) – sehe

Powiązane problemy