我的AST节点是struct
struct node_type
{
type::code type_id;
boost::variant<int, std::string> value;
};
适配器和语法:
BOOST_FUSION_ADAPT_STRUCT(
client::node_type,
(client::type::code, id)
(boost::variant<int, std::string>, value)
)
namespace client
{
struct or_op
{
node_type left, right;
};
namespace type
{
enum code{NUMBER, STRING, BOOL};
}
// 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 // main 'rule'
)
{
using qi::lit;
using qi::lexeme;
using ascii::char_;
using qi::int_;
using ascii::string;
using namespace qi::labels;
using phoenix::at_c;
using phoenix::push_back;
expr = int_[at_c<0>(qi::_val) = 0, at_c<1>(qi::_val) = qi::_1];
}
qi::rule<Iterator, node_type(), ascii::space_type> expr;
};
}
上面的代码无法编译。首先,我得到警告
error: macro "BOOST_FUSION_ADAPT_STRUCT_FILLER_0" passed 3 arguments, but takes just 2
然后是很多错误,从
开始qi/nonterminal/rule.hpp:303:17: error: no match for call to '(const function_type {aka const boost::function<bool(const char*&, const char* const&, boost::spirit::context<boost::fusion::cons<client::node_type&, boost::fusion::nil>, boost::fusion::vector0<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)>}) (const char*&, const char* const&, boost::spirit::qi::rule<const char*, client::node_type(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type>::context_type&, const boost::spirit::unused_type&)'
我做错了什么?感谢。
编辑: 由于宏中的','出现了宏警告。 Typedef解决了问题
typedef boost::variant<int, std::string> node_value_t;
struct node_type
{
type::code type_id;
node_value_t value;
};
BOOST_FUSION_ADAPT_STRUCT(
client::node_type,
(client::type::code, type_id)
(client::node_value_t, value)
)
但代码仍然无法编译。我也试过
number = int_[qi::_val = phoenix::construct<node_type>(type::NUMBER, qi::_1)];
但那并没有帮助。
编辑2:简化原始规则。仍然没有成功。
答案 0 :(得分:1)
这里有很多问题。
消息
错误:宏“BOOST_FUSION_ADAPT_STRUCT_FILLER_0”传递了3个参数,但只需2个
是因为,
的模板参数中的variant<>
而发生的。您可以使用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)
)
您正在为枚举类型的属性分配一个int。不允许隐式转换。而是提供所需的枚举类型:
expr = int_ [at_c<0>(qi::_val) = client::type::NUMBER, at_c<1>(qi::_val) = qi::_1];
此时,所有内容都会编译并运行: 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));
我不认为这个解决方案是最佳的。
考虑在可能的情况下使用Spirit指令,并远离语法操作,使语法失败,是错误/ UB的常见来源,使编译时间更长...... [1] 强>:
pair_grammar() : pair_grammar::base_type(expr)
{
expr = qi::attr(client::type::NUMBER) >> qi::int_;
}
也可以看到 Live On Coliru :
#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));
}