我正在为计算器编写一个简单的解析器,我希望有一个变体运算符作为参数传递以构造表达式。
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/home/support/attributes_fwd.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
namespace client {
namespace ast {
namespace x3 = boost::spirit::x3;
struct PlusOp {};
struct MinusOp {};
struct BinaryOp : x3::variant<PlusOp, MinusOp> {
using base_type::base_type;
using base_type::operator=;
};
} // namespace ast
} // namespace client
BOOST_FUSION_ADAPT_STRUCT(client::ast::BinaryOp)
namespace client {
namespace parser {
namespace x3 = boost::spirit::x3;
using x3::ascii::char_;
x3::rule<class BinOp, ast::BinaryOp> const binaryOp = "BinaryOp";
x3::rule<class PlusOp, ast::PlusOp> const plusOp = "PlusOp";
x3::rule<class MinusOp, ast::MinusOp> const minusOp = "MinusOp";
auto const plusOp_def = &char_('+');
auto const minusOp_def = &char_('-');
auto const binaryOp_def = plusOp | minusOp;
BOOST_SPIRIT_DEFINE(plusOp, binaryOp, minusOp);
} // namespace parser
} // namespace client
int main(int argc, char *argv[]) {
using boost::spirit::x3::phrase_parse;
using boost::spirit::x3::ascii::space;
std::string plus = "+";
client::ast::BinaryOp op;
phrase_parse(plus.begin(), plus.end(), client::parser::binaryOp, space, op);
return 0;
}
In file included from /usr/include/boost/spirit/home/x3/auxiliary/any_parser.hpp:17,
from /usr/include/boost/spirit/home/x3/auxiliary.hpp:11,
from /usr/include/boost/spirit/home/x3.hpp:62,
from spirit.cc:3:
/usr/include/boost/spirit/home/x3/support/traits/move_to.hpp: In instantiation of ‘void boost::spirit::x3::traits::move_to(Source&&, Dest&) [with Source = client::ast::PlusOp; Dest = client::ast::BinaryOp]’:
/usr/include/boost/spirit/home/x3/nonterminal/detail/transform_attribute.hpp:30:28: required from ‘static void boost::spirit::x3::default_transform_attribute<Exposed, Transformed>::post(Exposed&, Transformed&&) [with Exposed = client::ast::BinaryOp; Transformed = client::ast::PlusOp]’
/usr/include/boost/spirit/home/x3/nonterminal/rule.hpp:156:32: required from ‘bool boost::spirit::x3::rule<ID, Attribute, force_attribute>::parse(Iterator&, const Iterator&, const Context&, boost::spirit::x3::unused_type, Attribute_&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag>, boost::spirit::x3::unused_type>; Attribute_ = client::ast::BinaryOp; ID = client::parser::PlusOp; Attribute = client::ast::PlusOp; bool force_attribute_ = false]’
/usr/include/boost/spirit/home/x3/nonterminal/detail/rule.hpp:209:31: required from ‘static bool boost::spirit::x3::detail::rule_parser<Attribute, ID, skip_definition_injection>::parse_rhs_main(const RHS&, Iterator&, const Iterator&, const Context&, RContext&, ActualAttribute&, mpl_::false_) [with RHS = boost::spirit::x3::rule<client::parser::PlusOp, client::ast::PlusOp>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag>, boost::spirit::x3::unused_type>; RContext = client::ast::BinaryOp; ActualAttribute = client::ast::BinaryOp; Attribute = client::ast::BinaryOp; ID = client::parser::BinOp; bool skip_definition_injection = true; mpl_::false_ = mpl_::bool_<false>]’
/usr/include/boost/spirit/home/x3/nonterminal/detail/rule.hpp:265:34: required from ‘static bool boost::spirit::x3::detail::rule_parser<Attribute, ID, skip_definition_injection>::parse_rhs_main(const RHS&, Iterator&, const Iterator&, const Context&, RContext&, ActualAttribute&) [with RHS = boost::spirit::x3::rule<client::parser::PlusOp, client::ast::PlusOp>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag>, boost::spirit::x3::unused_type>; RContext = client::ast::BinaryOp; ActualAttribute = client::ast::BinaryOp; Attribute = client::ast::BinaryOp; ID = client::parser::BinOp; bool skip_definition_injection = true]’
/usr/include/boost/spirit/home/x3/nonterminal/detail/rule.hpp:279:34: required from ‘static bool boost::spirit::x3::detail::rule_parser<Attribute, ID, skip_definition_injection>::parse_rhs(const RHS&, Iterator&, const Iterator&, const Context&, RContext&, ActualAttribute&, mpl_::false_) [with RHS = boost::spirit::x3::rule<client::parser::PlusOp, client::ast::PlusOp>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag>, boost::spirit::x3::unused_type>; RContext = client::ast::BinaryOp; ActualAttribute = client::ast::BinaryOp; Attribute = client::ast::BinaryOp; ID = client::parser::BinOp; bool skip_definition_injection = true; mpl_::false_ = mpl_::bool_<false>]’
/usr/include/boost/spirit/home/x3/nonterminal/detail/rule.hpp:328:37: required from ‘static bool boost::spirit::x3::detail::rule_parser<Attribute, ID, skip_definition_injection>::call_rule_definition(const RHS&, const char*, Iterator&, const Iterator&, const Context&, ActualAttribute&, ExplicitAttrPropagation) [with RHS = boost::spirit::x3::rule<client::parser::PlusOp, client::ast::PlusOp>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag>, boost::spirit::x3::unused_type>; ActualAttribute = client::ast::BinaryOp; ExplicitAttrPropagation = mpl_::bool_<false>; Attribute = client::ast::BinaryOp; ID = client::parser::BinOp; bool skip_definition_injection = true]’
spirit.cc:38:1: required from ‘bool client::parser::parse_rule(boost::spirit::x3::detail::rule_id<BinOp>, Iterator&, const Iterator&, const Context&, boost::spirit::x3::rule<BinOp, client::ast::BinaryOp>::attribute_type&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag>, boost::spirit::x3::unused_type>; boost::spirit::x3::rule<BinOp, client::ast::BinaryOp>::attribute_type = client::ast::BinaryOp]’
/usr/include/boost/spirit/home/x3/nonterminal/rule.hpp:155:27: required from ‘bool boost::spirit::x3::rule<ID, Attribute, force_attribute>::parse(Iterator&, const Iterator&, const Context&, boost::spirit::x3::unused_type, Attribute_&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::char_class<boost::spirit::char_encoding::ascii, boost::spirit::x3::space_tag>, boost::spirit::x3::unused_type>; Attribute_ = client::ast::BinaryOp; ID = client::parser::BinOp; Attribute = client::ast::BinaryOp; bool force_attribute_ = false]’
/usr/include/boost/spirit/home/x3/core/parse.hpp:119:36: required from ‘bool boost::spirit::x3::phrase_parse_main(Iterator&, Iterator, const Parser&, const Skipper&, Attribute&, skip_flag) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Parser = rule<client::parser::BinOp, client::ast::BinaryOp>; Skipper = char_class<boost::spirit::char_encoding::ascii, space_tag>; Attribute = client::ast::BinaryOp]’
/usr/include/boost/spirit/home/x3/core/parse.hpp:151:33: required from ‘bool boost::spirit::x3::phrase_parse(const Iterator&, Iterator, const Parser&, const Skipper&, Attribute&, skip_flag) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Parser = rule<client::parser::BinOp, client::ast::BinaryOp>; Skipper = char_class<boost::spirit::char_encoding::ascii, space_tag>; Attribute = client::ast::BinaryOp]’
spirit.cc:48:15: required from here
/usr/include/boost/spirit/home/x3/support/traits/move_to.hpp:196:71: error: ambiguous template instantiation for ‘struct boost::spirit::x3::traits::attribute_category<client::ast::BinaryOp, void>’
196 | detail::move_to(src, dest, typename attribute_category<Dest>::type());
| ^~~~~~
In file included from /usr/include/boost/spirit/home/x3/support/traits/move_to.hpp:12:
/usr/include/boost/spirit/home/x3/support/traits/attribute_category.hpp:60:12: note: candidates are: ‘template<class T> struct boost::spirit::x3::traits::attribute_category<T, typename boost::enable_if<boost::mpl::and_<boost::fusion::traits::is_sequence<Sequence>, boost::mpl::not_<boost::fusion::traits::is_associative<Sequence1> > > >::type> [with T = client::ast::BinaryOp]’
60 | struct attribute_category< T
| ^~~~~~~~~~~~~~~~~~~~~
61 | , typename enable_if<
| ~~~~~~~~~~~~~~~~~~~~~
62 | mpl::and_<
| ~~~~~~~~~~
63 | fusion::traits::is_sequence<T>
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
64 | , mpl::not_<fusion::traits::is_associative<T> >
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65 | > >::type >
| ~~~~~~~~~~~
/usr/include/boost/spirit/home/x3/support/traits/attribute_category.hpp:69:12: note: ‘template<class T> struct boost::spirit::x3::traits::attribute_category<T, typename boost::enable_if<boost::spirit::x3::traits::is_variant<T> >::type> [with T = client::ast::BinaryOp]’
69 | struct attribute_category<T,
| ^~~~~~~~~~~~~~~~~~~~~
70 | typename enable_if<traits::is_variant<T>>::type>
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/spirit/home/x3/support/traits/move_to.hpp:196:71: error: invalid use of incomplete type ‘struct boost::spirit::x3::traits::attribute_category<client::ast::BinaryOp, void>’
196 | detail::move_to(src, dest, typename attribute_category<Dest>::type());
| ^~~~~~
/usr/include/boost/spirit/home/x3/support/traits/attribute_category.hpp:38:12: note: declaration of ‘struct boost::spirit::x3::traits::attribute_category<client::ast::BinaryOp, void>’
38 | struct attribute_category
| ^~~~~~~~~~~~~~~~~~
真的不知道这里发生了什么,因为我已经将二进制操作声明为变体并且应该进行编译。我已经研究了几个小时,但根本没有任何线索。任何帮助将不胜感激。非常感谢。
变种已经被精神合成了。序列适应(
BOOST_FUSION_ADAPT_STRICT
)没有增加任何值(根据定义,没有结构成员)。但是,它确实使属性传播含糊不清:应该使用变体支持,还是序列支持?
我的预测是放弃适应会使错误消失。
确实如此:
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
namespace x3 = boost::spirit::x3;
namespace client::ast {
struct PlusOp {};
struct MinusOp {};
struct BinaryOp : x3::variant<PlusOp, MinusOp> {
using base_type::base_type;
using base_type::operator=;
};
} // namespace client::ast
namespace client::parser {
using x3::ascii::char_;
x3::rule<class BinOp, ast::BinaryOp> const binaryOp = "BinaryOp";
x3::rule<class PlusOp, ast::PlusOp> const plusOp = "PlusOp";
x3::rule<class MinusOp, ast::MinusOp> const minusOp = "MinusOp";
auto const plusOp_def = &char_('+');
auto const minusOp_def = &char_('-');
auto const binaryOp_def = plusOp | minusOp;
BOOST_SPIRIT_DEFINE(plusOp, binaryOp, minusOp)
} // namespace client::parser
int main() {
using x3::space;
std::string plus = "+";
client::ast::BinaryOp op;
phrase_parse(plus.begin(), plus.end(), client::parser::binaryOp, space, op);
}