I think you are quite close to your goal so I will skip the combinatorial part :-)
The parser will do the things it is supposed to do ... to check the syntax and to tokenize data then it passes keys, values and output map ( multimap ) arguments into phoenix function inserter
where you can insert whatever
you need in your map ( multimap )
#if __cplusplus >= 201103L
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <vector>
#include <map>
namespace qi = boost::spirit::qi;
namespace ascii=boost::spirit::ascii;
typedef std::map< std::string,std::string > TMap;
//typedef std::multimap< std::string,std::string > TMap;
struct SMapInsert
{
template <typename Arg1,typename Arg2,typename Arg3>
struct result
{
typedef void type;
};
template <typename Arg1,typename Arg2,typename Arg3>
void operator()( Arg1&out, Arg2&keys, Arg3&vals ) const
{
std::cout << "Keys:" << std::endl;
for( const auto &key : keys )
std::cout << std::left << "`" << key << "`" << std::endl;
std::cout << "Vals:" << std::endl;
for( const auto &val : vals )
std::cout << std::left << "`" << val << "`" << std::endl;
// your map here...
// out.insert
}
};
boost::phoenix::function< SMapInsert > inserter;
int main()
{
std::string input = "{A [B C] -> F [D E], C ->E,B->Z}";
TMap data;
std::string::const_iterator iter = input.begin();
std::string::const_iterator last = input.end();
qi::rule< std::string::const_iterator,std::string() > token=+qi::alnum;
qi::rule< std::string::const_iterator,ascii::space_type,std::vector< std::string >() >
keyOrvalue = +( token | ( '[' >> qi::lexeme[ +qi::char_("a-zA-Z0-9 ") ] >> ']' ) );
qi::rule< std::string::const_iterator,ascii::space_type, TMap() >
root = '{' >> ( ( keyOrvalue >> "->" >> keyOrvalue )[ inserter( qi::_val, qi::_1, qi::_2 ) ] ) % ',' >> '}';
std::cout << "input: `" << input << "`" << std::endl;
if( qi::phrase_parse( iter, last, root, ascii::space, data ) && iter==last )
{
for( const auto &keyValue : data )
std::cout << std::left << std::setw(10) << keyValue.first << std::setw(10) << keyValue.second << std::endl;
}
else
std::cout << "parsing failed:" << std::string( iter,last ) << std::endl;
return 0;
}