Espíritu no puede asignar atributo a la estructura de un solo elemento (o secuencia de fusión)

Mi objective es que mi qi::grammar devuelva un atributo. Estoy teniendo dificultades significativas para hacer esto con un spirit::lexer sin embargo.

Esperaría que con la gramática dada a continuación, si la llamara con spirit::qi::parse(begin, end, grammar, output); , que la struct ident output tendría el contenido del lexema analizado.

El error parece fluir principalmente fuera de esta línea: start %= lexer.identifier;

Notas del sistema

  • Impulso 1.47.0
  • Mac OS X 10.7.2
  • clang ++ o g ++ (los errores que se muestran a continuación son de clang ++)

Comando de comstackción

 g++ -g -c -O0 -Wall -DBOOST_SPIRIT_DEBUG -DBOOST_SPIRIT_LEXERTL_DEBUG -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT reduced.cpp 

Código fuente

 #include  #include  #include  #include  namespace spirit = boost::spirit; struct ident { std::string value; }; BOOST_FUSION_ADAPT_STRUCT(ident, (std::string, value) ) struct my_lexer : spirit::lex::lexer< spirit::lex::lexertl::actor_lexer > { spirit::lex::token_def identifier; }; struct my_grammar : spirit::qi::grammar { my_grammar(const my_lexer & lexer) : my_grammar::base_type(start) { start %= lexer.identifier; } spirit::qi::rule start; }; 

2 errores reportados

 In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:13: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer.hpp:14: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/token_def.hpp:20: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/detail/assign_to.hpp:38:24: error: no matching constructor for initialization of 'ident' attr = Attribute(first, last); ^ ~~~~~~~~~~~ /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/detail/assign_to.hpp:94:13: note: in instantiation of member function 'boost::spirit::traits::assign_to_attribute_from_iterators::call' requested here call(first, last, attr); ^ In file included from ../reduced-example/reduced.cpp:4: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/lexertl/lexer.hpp:20: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/lexertl/token.hpp:530:13: note: in instantiation of function template specialization 'boost::spirit::traits::assign_to' requested here spirit::traits::assign_to(t.value().begin(), t.value().end(), attr); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:13: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer.hpp:14: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/token_def.hpp:20: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/detail/assign_to.hpp:330:59: note: in instantiation of member function 'boost::spirit::traits::assign_to_attribute_from_value<ident, boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, void>::call' requested here assign_to_attribute_from_value::call(val, attr); ^ /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/detail/assign_to.hpp:353:9: note: in instantiation of function template specialization 'boost::spirit::traits::detail::assign_to<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, ident>' requested here detail::assign_to(val, attr, is_not_wrapped_container()); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:13: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer.hpp:14: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/token_def.hpp:106:21: note: in instantiation of function template specialization 'boost::spirit::traits::assign_to<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, ident>' requested here spirit::traits::assign_to(t, attr); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:13: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer.hpp:14: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/token_def.hpp:21: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/reference.hpp:16: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/reference.hpp:43:20: note: (skipping 5 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all) return ref.get().parse(first, last, context, skipper, attr); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/tokenize_and_parse.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/grammar.hpp:18: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/rule.hpp:16: In file included from /home/wlynch/Boost/1.47.0/include/boost/function.hpp:64: In file included from /home/wlynch/Boost/1.47.0/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:67: In file included from /home/wlynch/Boost/1.47.0/include/boost/function/detail/function_iterate.hpp:14: In file included from /home/wlynch/Boost/1.47.0/include/boost/function/detail/maybe_include.hpp:33: /home/wlynch/Boost/1.47.0/include/boost/function/function_template.hpp:1042:5: note: in instantiation of function template specialization 'boost::function4<bool, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > const &, boost::spirit::context<boost::fusion::cons, boost::fusion::vector0 > &, boost::spirit::unused_type const &>::function4<boost::spirit::qi::detail::parser_binder<boost::spirit::lex::reference<boost::spirit::lex::token_def<std::basic_string, char, unsigned long> const, unsigned long>, mpl_::bool_ > >' requested here base_type(f) ^ /home/wlynch/Boost/1.47.0/include/boost/function/function_template.hpp:1083:5: note: in instantiation of function template specialization 'boost::function<bool (boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > const &, boost::spirit::context<boost::fusion::cons, boost::fusion::vector0 > &, boost::spirit::unused_type const &)>::function<boost::spirit::qi::detail::parser_binder<boost::spirit::lex::reference<boost::spirit::lex::token_def<std::basic_string, char, unsigned long> const, unsigned long>, mpl_::bool_ > >' requested here self_type(f).swap(*this); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/tokenize_and_parse.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/grammar.hpp:18: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/rule.hpp:182:19: note: in instantiation of function template specialization 'boost::function<bool (boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > const &, boost::spirit::context<boost::fusion::cons, boost::fusion::vector0 > &, boost::spirit::unused_type const &)>::operator=<boost::spirit::qi::detail::parser_binder<boost::spirit::lex::reference<boost::spirit::lex::token_def<std::basic_string, char, unsigned long> const, unsigned long>, mpl_::bool_ > >' requested here lhs.f = detail::bind_parser( ^ /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/rule.hpp:230:13: note: in instantiation of function template specialization 'boost::spirit::qi::rule<boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > >, ident (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>::define<mpl_::bool_, boost::spirit::lex::token_def<std::basic_string, char, unsigned long> >' requested here define(r, expr, traits::matches()); ^ ../reduced-example/reduced.cpp:23:9: note: in instantiation of function template specialization 'boost::spirit::qi::operator%=<boost::spirit::lex::token_def<std::basic_string, char, unsigned long> >' requested here start %= lexer.identifier; ^ ../reduced-example/reduced.cpp:9:8: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided struct ident { ^ ../reduced-example/reduced.cpp:9:8: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:13: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer.hpp:14: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/token_def.hpp:17: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/parser.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/domain.hpp:18: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/support/context.hpp:18: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/support/nonterminal/expand_arg.hpp:20: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/support/string_traits.hpp:16: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/support/container.hpp:368:22: error: no member named 'empty' in 'ident' return c.empty(); ~ ^ /home/wlynch/Boost/1.47.0/include/boost/spirit/home/support/container.hpp:375:47: note: in instantiation of member function 'boost::spirit::traits::is_empty_container::call' requested here return is_empty_container::call(c); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:13: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer.hpp:14: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/token_def.hpp:20: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/detail/assign_to.hpp:37:17: note: in instantiation of function template specialization 'boost::spirit::traits::is_empty' requested here if (traits::is_empty(attr)) ^ /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/detail/assign_to.hpp:94:13: note: in instantiation of member function 'boost::spirit::traits::assign_to_attribute_from_iterators::call' requested here call(first, last, attr); ^ In file included from ../reduced-example/reduced.cpp:4: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/lexertl/lexer.hpp:20: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/lexertl/token.hpp:530:13: note: in instantiation of function template specialization 'boost::spirit::traits::assign_to' requested here spirit::traits::assign_to(t.value().begin(), t.value().end(), attr); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:13: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer.hpp:14: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/lexer/token_def.hpp:20: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/detail/assign_to.hpp:330:59: note: in instantiation of member function 'boost::spirit::traits::assign_to_attribute_from_value<ident, boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, void>::call' requested here assign_to_attribute_from_value::call(val, attr); ^ /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/detail/assign_to.hpp:353:9: note: (skipping 7 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all) detail::assign_to(val, attr, is_not_wrapped_container()); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/tokenize_and_parse.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/grammar.hpp:18: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/rule.hpp:16: In file included from /home/wlynch/Boost/1.47.0/include/boost/function.hpp:64: In file included from /home/wlynch/Boost/1.47.0/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:67: In file included from /home/wlynch/Boost/1.47.0/include/boost/function/detail/function_iterate.hpp:14: In file included from /home/wlynch/Boost/1.47.0/include/boost/function/detail/maybe_include.hpp:33: /home/wlynch/Boost/1.47.0/include/boost/function/function_template.hpp:1042:5: note: in instantiation of function template specialization 'boost::function4<bool, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > const &, boost::spirit::context<boost::fusion::cons, boost::fusion::vector0 > &, boost::spirit::unused_type const &>::function4<boost::spirit::qi::detail::parser_binder<boost::spirit::lex::reference<boost::spirit::lex::token_def<std::basic_string, char, unsigned long> const, unsigned long>, mpl_::bool_ > >' requested here base_type(f) ^ /home/wlynch/Boost/1.47.0/include/boost/function/function_template.hpp:1083:5: note: in instantiation of function template specialization 'boost::function<bool (boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > const &, boost::spirit::context<boost::fusion::cons, boost::fusion::vector0 > &, boost::spirit::unused_type const &)>::function<boost::spirit::qi::detail::parser_binder<boost::spirit::lex::reference<boost::spirit::lex::token_def<std::basic_string, char, unsigned long> const, unsigned long>, mpl_::bool_ > >' requested here self_type(f).swap(*this); ^ In file included from ../reduced-example/reduced.cpp:3: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/lex/tokenize_and_parse.hpp:15: In file included from /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/grammar.hpp:18: /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/rule.hpp:182:19: note: in instantiation of function template specialization 'boost::function<bool (boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > > const &, boost::spirit::context<boost::fusion::cons, boost::fusion::vector0 > &, boost::spirit::unused_type const &)>::operator=<boost::spirit::qi::detail::parser_binder<boost::spirit::lex::reference<boost::spirit::lex::token_def<std::basic_string, char, unsigned long> const, unsigned long>, mpl_::bool_ > >' requested here lhs.f = detail::bind_parser( ^ /home/wlynch/Boost/1.47.0/include/boost/spirit/home/qi/nonterminal/rule.hpp:230:13: note: in instantiation of function template specialization 'boost::spirit::qi::rule<boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0, mpl_::bool_, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_, mpl_::bool_ > >, ident (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>::define<mpl_::bool_, boost::spirit::lex::token_def<std::basic_string, char, unsigned long> >' requested here define(r, expr, traits::matches()); ^ ../reduced-example/reduced.cpp:23:9: note: in instantiation of function template specialization 'boost::spirit::qi::operator%=<boost::spirit::lex::token_def<std::basic_string, char, unsigned long> >' requested here start %= lexer.identifier; ^ 

Terminé dándome cuenta de que la estructura que definí se está utilizando espiritualmente como una tupla. Porque el espíritu intentará minimizar los grupos (por ejemplo, un optional optional es un optional ). Por lo tanto, supuse que una tuple se convertirá en una A Lo que parece ser el caso.

Pude reducir aún más el caso de prueba de código roto a lo siguiente:

 #include  #include  #include  struct ident { std::string a; }; BOOST_FUSION_ADAPT_STRUCT(ident, (std::string, a) ) int main() { boost::spirit::qi::rule r; r = boost::spirit::lexeme["abc"]; } 

De las siguientes publicaciones de la lista de correo ( 1 , 2 ) que encontré, puedo solucionar este problema haciendo:

 r = boost::spirit::lexeme["abc"] >> boost::spirit::eps; 

Si bien no es realmente elegante, al menos resuelve el problema. Si alguien más tiene un método para hacer la estructura de un solo elemento, estaría muy interesado.