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