c++ - Boost spirit qi integer with default value on literal -


i want parse numbers default values on specific literals. example if program receives "nan" or "n/a" integer default value -1.

// example program #include <iostream> #include <string>  #include <boost/fusion/adapted.hpp> #include <boost/fusion/include/adapted.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/include/phoenix_fusion.hpp> #include <boost/spirit/include/phoenix_object.hpp>  struct person {     std::string name;     int age;     std::string gender; };  boost_fusion_adapt_struct(     person,     (std::string, name)(int, age)(std::string, gender) )  template <typename iterator>     struct persongrammar : boost::spirit::qi::grammar<iterator, person(), boost::spirit::ascii::space_type> {     using skipper = boost::spirit::ascii::space_type;          persongrammar(std::ostream& error_stream = std::cerr)             : persongrammar::base_type(start, "person")         {             string = +boost::spirit::qi::char_("a-za-z0-9_ .()/-") | boost::spirit::qi::attr("(unspecified)");             integer = boost::spirit::qi::lit("n/a") [boost::spirit::qi::_val = int(-1)] | boost::spirit::qi::int_;             //integer = boost::spirit::qi::lexeme[boost::spirit::qi::no_case[boost::spirit::qi::eps > ( boost::spirit::qi::lit("n/a")[boost::spirit::qi::_val = -1] |  boost::spirit::qi::int_ ) ] ];              const char sep = ',';              start %= string >> boost::spirit::qi::lit(sep) >> integer >> boost::spirit::qi::lit(sep) >> string;              string.name("string");             integer.name("integer");          }  private:     boost::spirit::qi::rule<iterator, std::string(), skipper> string;     boost::spirit::qi::rule<iterator, int(), skipper> integer;     boost::spirit::qi::rule<iterator, person(), skipper> start; };  int main() {     std::string input_row = "jon snow, n/a, male";      std::string::const_iterator iterator = input_row.begin();     std::string::const_iterator end = input_row.end();      persongrammar<std::string::const_iterator> grammar;     person person;      bool success = boost::spirit::qi::phrase_parse(         iterator, end, grammar, boost::spirit::ascii::space, person);      std::cout << "parse status: " << std::boolalpha << success << std::endl;      std::cout << "person: " << person.name << std::endl << "age: " << person.age << std::endl << "gender: " << person.gender << std::endl;      return 0; } 

the output be:

parse status: true person: jonsnow age: -1 gender: male 

so it's okay. want feed number:

std::string input_row = "jon snow, 22, male"; 

the output be:

parse status: true person: jonsnow age: -2075995368 gender: male 

what problem here? hope not bug. maybe i'm using wrong. there commented lexeme in code. tried expression well. sadly didn't work.

thanks help!

just this:

> (qi::int_ | (no_case["n/a"] >> qi::attr(-1))) 

note:

integer_ = lexeme[no_case[eps > ( lit("n/a")[_val = -1] |  int_ ) ] ]; 

lacks semantic action on int_. or need force automatic propagation %=. first suggestion way more elegant, imo.

full demo

live on wandbox

#include <iostream> #include <string>  #include <boost/fusion/adapted.hpp> #include <boost/fusion/include/adapted.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/include/phoenix_fusion.hpp> #include <boost/spirit/include/phoenix_object.hpp>  struct person {     std::string name;     int age;     std::string gender; };  boost_fusion_adapt_struct(     person,     (std::string, name)(int, age)(std::string, gender) )  namespace qi = boost::spirit::qi;  template <typename iterator>     struct persongrammar : qi::grammar<iterator, person(), qi::ascii::space_type> {     persongrammar(std::ostream& /*error_stream*/ = std::cerr)         : persongrammar::base_type(start, "person")     {         using namespace qi;         string_ = +char_("a-za-z0-9_ .()/-") | attr("(unspecified)");         integer_ = int_ | no_case["n/a"] >> attr(-1);          const char sep = ',';          start = string_ >> sep >> integer_ >> sep >> string_;          boost_spirit_debug_nodes((string_)(integer_))     }      private:     using skipper = boost::spirit::ascii::space_type;     qi::rule<iterator, std::string(), skipper> string_;     qi::rule<iterator, int(), skipper> integer_;     qi::rule<iterator, person(), skipper> start; };  int main() {     std::string input_row = "jon snow, n/a, male";      std::string::const_iterator iterator = input_row.begin();     std::string::const_iterator end = input_row.end();      persongrammar<std::string::const_iterator> grammar;     person person;      bool success = qi::phrase_parse(         iterator, end, grammar, qi::ascii::space, person);      std::cout << "parse status: " << std::boolalpha << success << std::endl;     std::cout << "person: " << person.name << std::endl << "age: " << person.age << std::endl << "gender: " << person.gender << std::endl; } 

prints

parse status: true person: jonsnow age: -1 gender: male 

Comments

Popular posts from this blog

PHP and MySQL WP -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

go - golang pprof for c library code -