multi containers and arbitrary insertion.

Dan Bloomquist <[email protected]> Tue, 27 Mar 2018 19:33:50 -0700
Newsgroups gmane.comp.parsers.spirit.general
Message-ID <[email protected]>
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