Re: multi containers and arbitrary insertion.
Mikael Asplund <[email protected]> Wed, 28 Mar 2018 08:03:58 +0000
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <[email protected]> |
From your example, and your structs and your parser rules, I can't figure out what you're trying to achieve. Could you describe it with pure English? Are you trying to parse a list of "vect"s and "map"s, in mixed order, and get a struct with a two lists, one with all the "vects" and one with all the "map"? /Mikael -----Original Message----- From: Dan Bloomquist <[email protected]> Sent: Wednesday, March 28, 2018 04:34 To: Spirit General Mailing List <[email protected]> Subject: [Spirit-general] multi containers and arbitrary insertion. I've really tried to get this to work. I have learned a lot but I'm still stuck. I have comments in the code below, see: 'This is what I would really like to parse'. I'm so close! Thanks, Dan. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include <boost/spirit/home/x3.hpp> //must fuse std::pair for maps #include <boost/fusion/include/std_pair.hpp> #include <boost/spirit/home/x3/support/ast/variant.hpp> #include <iostream> #include <unordered_map> namespace ast { namespace x3 = boost::spirit::x3; //struct nil{}; //struct Dual; //struct Dual2; //struct Holder; //typedef x3::variant < // nil, // x3::forward_ast<Dual>, // x3::forward_ast<Dual2> //> Type; // ......................................................... struct Dual { std::string name; int num; int another; // not used.... bool operator < (const Dual& d) { return d.name < name; } }; using DualMap = std::unordered_map<std::string, Dual>; // ......................................................... struct Dual2 { std::string name; int num; }; using Dual2Vect = std::vector<Dual2>; // ......................................................... struct Holder { std::string dummy; std::unordered_map<std::string, Dual> themap; std::vector<Dual2> thevect; }; }// namespace ast BOOST_FUSION_ADAPT_STRUCT(ast::Dual, name, num ) BOOST_FUSION_ADAPT_STRUCT(ast::Dual2, name, num ) BOOST_FUSION_ADAPT_STRUCT(ast::Holder, dummy, thevect, themap ) // ......................................................... // parser namespace......................................... using namespace boost::spirit::x3; using namespace ast; #define DEF_RULE( RuleName, Attr ) static auto const RuleName = rule<struct Attr##_def, Attr>( #RuleName ) auto const bare_word = lexeme[+char_("a-zA-Z0-9_")]; auto const quoted_string = lit('"') >> bare_word >> lit('"'); DEF_RULE(dual_rule, Dual) = bare_word >> int_; DEF_RULE(dual2_rule, Dual2) = lit("vect") >> bare_word >> int_; static auto const dual_map_rule = lit("map") >> quoted_string >> dual_rule; //this works but not what I'm after static auto const all_rule = x3::skip(x3::space)[ bare_word >> +dual2_rule >> +dual_map_rule]; //would like this, but can't get it to be the right size for the 'Holder' class static auto const all_rule2 = x3::skip(x3::space)[bare_word >> +dual2_rule | +dual_map_rule]; DEF_RULE(holder_rule, Holder) = bare_word >> all_rule; BOOST_SPIRIT_DEFINE(dual_rule, dual2_rule, holder_rule) // ......................................................... // ......................................................... //This is what I would really like to parse. const static std::string thestr( R"( hold_name vect name1 123 map "test1" namea 234 map "test2" nameb 345 vect name2 456 )" ); //And in that case I really don't want to use the plus type Kleene, but containers expect it!?? int main() { std::cout << "fusion::size: " << boost::fusion::result_of::size<traits::attribute_of<decltype(quoted_string >> dual_rule >> -lit(',')), unused_type>::type>::value << std::endl; //test { std::string str("map \"mark1\" name 123\n map \"mark2\" and 234"); auto begin = str.begin(); auto end = str.end(); std::unordered_map< std::string, Dual > map; auto r = phrase_parse(begin, end, +dual_map_rule, space, map); std::cout << std::boolalpha << "pass: " << r << " at: " << std::string(begin, end) << std::endl; } { std::string str("vect name1 1 vect name2 2\n\r vect name3 3"); auto begin = str.begin(); auto end = str.end(); std::vector< Dual2 > vect; auto r = phrase_parse(begin, end, +dual2_rule, space, vect); std::cout << std::boolalpha << "pass: " << r << " at: " << std::string(begin, end) << std::endl; size_t x = 0; } { std::string str("hold_name vect stuff1 21 vect stuff2 22\n vect stuff3 33 map \"mark1\" name 123\n vect more 42"); // ^ //stops here with success //str = thestr; std::string::iterator begin = str.begin(); std::string::iterator end = str.end(); Holder hdual; bool r = phrase_parse(begin, end, all_rule, space, hdual); std::cout << std::boolalpha << "pass: " << r << " at: " << std::string(begin, end) << std::endl; //and... for (auto& item : hdual.thevect) std::cout << item.name << ", " << item.num << std::endl; } return 0; } ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Spirit-general mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/spirit-general ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot