I'm trying to parse the following:
[SOFT] AQUA+
[FORWARD_SPEED] 0.00
[some other key] string value
[PERIODS_NUMBER] 6
[HEADINGS_NUMBER] 13
[LOWEST_HEADINGS] 0.00
[HIGHEST_HEADINGS] 180.00
I don't know in advance what the keys are.
I want to parse them in a structure of vectors.
namespace hdb
{
typedef std::string Header;
template <typename T> struct Key
{
Header header;
T value;
};
struct AST
{
std::vector<Key<std::string> > string_keys;
std::vector<Key<double> > value_keys;
}
}
I wrote the adaptors:
BOOST_FUSION_ADAPT_STRUCT(
hdb::Key<std::string>,
(hdb::Header, header)
(std::string, value)
)
BOOST_FUSION_ADAPT_STRUCT(
hdb::Key<double>,
(hdb::Header, header)
(double, value)
)
namespace boost { namespace spirit { namespace traits {
template<>
struct is_container<hdb::AST, void> : mpl::true_ { };
template<>
struct container_value<hdb::AST, void> {
typedef boost::variant<
hdb::Key<std::string>
,hdb::Key<double>
> type;
};
template <>
struct push_back_container<hdb::AST, hdb::Key<std::string>, void> {
static bool call(hdb::AST& f, const hdb::Key<std::string>& val) {
f.string_keys.push_back(val);
return true;
}
};
template <>
struct push_back_container<hdb::AST, hdb::Key<double>, void> {
static bool call(hdb::AST& f, const hdb::Key<double>& val) {
f.value_keys.push_back(val);
return true;
}
};
The grammar is the following:
template <typename Iterator>
struct hdb_grammar : qi::grammar<Iterator, hdb::AST(), ascii::space_type>
{
hdb_grammar() : hdb_grammar::base_type(ast)
{
ast %= string_key | value_key;
header %= lexeme['[' >> +(char_ - '[' - ']') >> ']'];
string_key %= header >> +(char_ - '[' - ']');
value_key %= header >> double_;
}
qi::rule<Iterator, hdb::AST(), ascii::space_type> ast;
qi::rule<Iterator, hdb::Header(), ascii::space_type> header;
qi::rule<Iterator, hdb::Key<double>(), ascii::space_type> value_key;
qi::rule<Iterator, hdb::Key<std::string>(), ascii::space_type> string_key;
};
I call the parser like this:
const std::string contents = "[key 1] value 1\n"
"[key 2] value 2\n";
typedef hdb_grammar<std::string::const_iterator> grammar;
grammar g; // Our grammar
hdb::AST ast; // Our tree
using boost::spirit::ascii::space;
std::string::const_iterator begin = contents.begin(), end = contents.end();
bool success = qi::phrase_parse(begin, end, g.ast, space, ast); // Only fills "key 1" & not "key 2"
I think the problem lies with my grammar, but I can't for the life of me see what's wrong with it. Any help would be greatly appreciated.