A number of issues here.
The message
error: macro "BOOST_FUSION_ADAPT_STRUCT_FILLER_0" passed 3 arguments, but takes just 2
occurs because of the
,
in the template arguments forvariant<>
. You can fix it using a typedef:namespace client { namespace type { enum code{NUMBER, STRING, BOOL}; } struct node_type { type::code type_id; typedef boost::variant<int, std::string> vt_type; vt_type value; }; } BOOST_FUSION_ADAPT_STRUCT( client::node_type, (client::type::code, type_id) (client::node_type::vt_type, value) )
You were assigning an int to the attribute of enum type. The implicit conversion is not allowed. Instead, supply the required enum type:
expr = int_ [at_c<0>(qi::_val) = client::type::NUMBER, at_c<1>(qi::_val) = qi::_1];
At this point, everything compiles and works: Live On Coliru
using namespace client;
pair_grammar<std::string::const_iterator> grammar;
std::string const input = "123";
auto f(input.begin()), l(input.end());
node_type node;
bool ok = qi::phrase_parse(f, l, grammar, ascii::space, node);
assert(ok);
assert(f == l);
assert(node.type_id == type::NUMBER);
assert(node.value == node_type::vt_type(123));
I don't think this solution is optimal, though.
Consider using the Spirit directives where possible, and staying away from Semantic actions that uglify the grammar, are a frequent source of errors/UB, make compile times even longer... [1]:
pair_grammar() : pair_grammar::base_type(expr)
{
expr = qi::attr(client::type::NUMBER) >> qi::int_;
}
See that Live On Coliru too:
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = qi::ascii;
namespace client
{
namespace type
{
enum code{NUMBER, STRING, BOOL};
}
struct node_type
{
type::code type_id;
typedef boost::variant<int, std::string> vt_type;
vt_type value;
};
}
/*Adapter and grammar:*/
BOOST_FUSION_ADAPT_STRUCT(
client::node_type,
(client::type::code, type_id)
(client::node_type::vt_type, value)
)
namespace client
{
struct or_op
{
node_type left, right;
};
// Grammar
template <typename Iterator>
struct pair_grammar : qi::grammar<
Iterator,
node_type(), // Grammar generates node_type
ascii::space_type
>
{
pair_grammar() : pair_grammar::base_type(expr)
{
expr = qi::attr(client::type::NUMBER) >> qi::int_;
}
qi::rule<Iterator, node_type(), ascii::space_type> expr;
};
}
int main()
{
using namespace client;
pair_grammar<std::string::const_iterator> grammar;
std::string const input = "123";
auto f(input.begin()), l(input.end());
node_type node;
bool ok = qi::phrase_parse(f, l, grammar, ascii::space, node);
assert(ok);
assert(f == l);
assert(node.type_id == type::NUMBER);
assert(node.value == node_type::vt_type(123));
}