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
#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
Post a Comment