Spirit cannot assign an attribute to a singleton structure (or merge sequence)

My goal is to return the qi::grammar attribute. I have serious difficulties with this with spirit::lexer , though.

I would expect that with this grammar below, if I named it with spirit::qi::parse(begin, end, grammar, output); that struct ident output will have the contents of the parsed token.

The error seems to mainly stem from this line: start %= lexer.identifier;

System notes

  • Boost 1.47.0
  • Mac OS X 10.7.2
  • clang ++ or g ++ (errors shown below from clang ++)

Compilation command

 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 

Source

 #include <boost/fusion/include/adapt_struct.hpp> #include <boost/spirit/home/lex.hpp> #include <boost/spirit/home/lex/lexer/lexertl/lexer.hpp> #include <boost/spirit/home/qi.hpp> 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<std::string> identifier; }; struct my_grammar : spirit::qi::grammar<my_lexer::iterator_type, ident()> { my_grammar(const my_lexer & lexer) : my_grammar::base_type(start) { start %= lexer.identifier; } spirit::qi::rule<my_lexer::iterator_type, ident()> start; }; 

2 Reported errors

 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<ident, char const *, void>::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<char const *, ident>' 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_::na>, mpl_::bool_<1>, unsigned long>, void>::call' requested here assign_to_attribute_from_value<Attribute, T>::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_::na>, mpl_::bool_<1>, 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_::na>, mpl_::bool_<1>, 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_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0<mpl_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > const &, boost::spirit::context<boost::fusion::cons<ident &, boost::fusion::nil>, boost::fusion::vector0<void> > &, 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>, char, unsigned long> const, unsigned long>, mpl_::bool_<1> > >' 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_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0<mpl_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > const &, boost::spirit::context<boost::fusion::cons<ident &, boost::fusion::nil>, boost::fusion::vector0<void> > &, 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>, char, unsigned long> const, unsigned long>, mpl_::bool_<1> > >' 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_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0<mpl_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > const &, boost::spirit::context<boost::fusion::cons<ident &, boost::fusion::nil>, boost::fusion::vector0<void> > &, 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>, char, unsigned long> const, unsigned long>, mpl_::bool_<1> > >' requested here lhs.f = detail::bind_parser<Auto>( ^ /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_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > >, ident (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>::define<mpl_::bool_<1>, boost::spirit::lex::token_def<std::basic_string<char>, char, unsigned long> >' requested here define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>()); ^ ../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>, 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<ident, void>::call' requested here return is_empty_container<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<ident>' 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<ident, char const *, void>::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<char const *, ident>' 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_::na>, mpl_::bool_<1>, unsigned long>, void>::call' requested here assign_to_attribute_from_value<Attribute, T>::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_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0<mpl_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > const &, boost::spirit::context<boost::fusion::cons<ident &, boost::fusion::nil>, boost::fusion::vector0<void> > &, 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>, char, unsigned long> const, unsigned long>, mpl_::bool_<1> > >' 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_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0<mpl_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > const &, boost::spirit::context<boost::fusion::cons<ident &, boost::fusion::nil>, boost::fusion::vector0<void> > &, 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>, char, unsigned long> const, unsigned long>, mpl_::bool_<1> > >' 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_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > &, boost::spirit::lex::lexertl::iterator<boost::spirit::lex::lexertl::functor<boost::spirit::lex::lexertl::token<char const *, boost::mpl::vector0<mpl_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > > const &, boost::spirit::context<boost::fusion::cons<ident &, boost::fusion::nil>, boost::fusion::vector0<void> > &, 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>, char, unsigned long> const, unsigned long>, mpl_::bool_<1> > >' requested here lhs.f = detail::bind_parser<Auto>( ^ /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_::na>, mpl_::bool_<1>, unsigned long>, lexertl::detail::data, char const *, mpl_::bool_<1>, mpl_::bool_<1> > >, ident (), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>::define<mpl_::bool_<1>, boost::spirit::lex::token_def<std::basic_string<char>, char, unsigned long> >' requested here define<mpl::true_>(r, expr, traits::matches<qi::domain, Expr>()); ^ ../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>, char, unsigned long> >' requested here start %= lexer.identifier; ^ 
+4
source share
1 answer

As a result, I realized that the structure I defined was used in the spirit of a tuple. Because the spirit will try to minimize groups (e.g. optional<int, int> - optional<int> ). So I guessed that a tuple<A> would be converted to A It seems that way.

I was able to further reduce the test code of the faulty code to the following:

 #include <boost/fusion/include/adapt_struct.hpp> #include <boost/spirit/home/qi.hpp> #include <string> struct ident { std::string a; }; BOOST_FUSION_ADAPT_STRUCT(ident, (std::string, a) ) int main() { boost::spirit::qi::rule<const char*, ident()> r; r = boost::spirit::lexeme["abc"]; } 

From the following mailing lists ( 1 , 2 ) that I found, I can work around this problem by following these steps:

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

While he is not very elegant, he solves the problem at least. If anyone has a method for creating a single element structure, I would be very interested.

+2
source

All Articles