Boost Spirit X3 中属性类别的模板实例化不明确

问题描述 投票:0回答:1

我正在为计算器编写一个简单的解析器,我希望有一个变体运算符作为参数传递以构造表达式。

#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
      |            ^~~~~~~~~~~~~~~~~~

真的不知道这里发生了什么,因为我已经将二进制操作声明为变体并且应该进行编译。我已经研究了几个小时,但根本没有任何线索。任何帮助将不胜感激。非常感谢。

c++ boost boost-spirit
1个回答
0
投票

变种已经被精神合成了。序列适应(

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.