6

The following code is a streamlined version of what i'm trying to do. Basically, I have struct (int_holder in the toy code), with a container data member. I want to insert an object (int in this case) and return to the parent qi::rule a pointer to the newly inserted object.

I pass the int_holder to the grammar by reference, in order to fill it with values while parsing, therefore the int_holder will be an inherited attribute of the grammar. Code:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <vector>

namespace qi=boost::spirit::qi;
namespace phoenix=boost::phoenix;

struct int_holder
{
    int_holder() {}
    std::vector<int> ints;
};


struct insert_impl
{
    template<class, class>
    struct result { typedef int* type; };
    int* operator() (int_holder& holder, int i) const
    {
        holder.ints.push_back (i);
        return &holder.ints.back();
    }
};

template<class Iterator>
struct my_grammar : qi::grammar<Iterator, int*(int_holder&)>
{
    my_grammar () : my_grammar::base_type (start)
          , insert (insert_impl())
    {
        using qi::_val;
        using qi::int_;
        using qi::_r1;
        using qi::_1;

        using phoenix::ref;

        start = +next(_val) [_val = _1];
        next = int_ [_val = insert(_r1, _1)];
    }
    qi::rule<Iterator, int*(int_holder&)> start, next;
    phoenix::function<insert_impl> insert;
};


int main ()
{
    using phoenix::ref;

    const char* p="1";
    int* last;
    int_holder holder;
    my_grammar<const char*> g;
    qi::parse (p, p+1, g(ref(holder)), last);
}

The code does not compile, with the following error message:

In file included from     
/opt/local/include/boost/fusion/sequence/intrinsic/detail/segmented_begin.hpp:16:0,
         from /opt/local/include/boost/fusion/sequence/intrinsic/begin.hpp:17, from
         /opt/local/include/boost/fusion/iterator/segmented_iterator.hpp:12, from
         /opt/local/include/boost/fusion/sequence/intrinsic/detail/segmented_end.hpp:11, from
         /opt/local/include/boost/fusion/sequence/intrinsic/end.hpp:17, from
         /opt/local/include/boost/fusion/sequence/intrinsic/back.hpp:11, from
         /opt/local/include/boost/fusion/sequence/intrinsic.hpp:11, from
         /opt/local/include/boost/fusion/include/intrinsic.hpp:10, from
         /opt/local/include/boost/proto/fusion.hpp:22, from
         /opt/local/include/boost/proto/core.hpp:21, from
         /opt/local/include/boost/proto/proto.hpp:12, from
         /opt/local/include/boost/spirit/home/support/meta_compiler.hpp:19, from
         /opt/local/include/boost/spirit/home/qi/meta_compiler.hpp:14, from
         /opt/local/include/boost/spirit/home/qi/action/action.hpp:14, from
         /opt/local/include/boost/spirit/home/qi/action.hpp:14, from
         /opt/local/include/boost/spirit/home/qi.hpp:14, from
         /opt/local/include/boost/spirit/include/qi.hpp:16, from test_qi.cpp:1:
         /opt/local/include/boost/fusion/container/list/cons.hpp: In instantiation of
         'boost::fusion::cons<Car, Cdr>::cons(const boost::fusion::cons<Car2, Cdr2>&) [with Car2 =
         int*&; Cdr2 = boost::fusion::nil; Car = int_holder&; Cdr = boost::fusion::nil]':
         /opt/local/include/boost/spirit/home/support/context.hpp:117:20: required from
         'boost::spirit::context<Attributes, Locals>::context(typename Attributes::car_type, const
         Args&, Context&) [with Args =
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_>; Context = boost::spirit::context<boost::fusion::cons<int*&,
         boost::fusion::cons<int_holder&, boost::fusion::nil> >, boost::fusion::vector0<> >;
         Attributes = boost::fusion::cons<int*&, boost::fusion::cons<int_holder&,
         boost::fusion::nil> >; Locals = boost::fusion::vector0<>; typename Attributes::car_type =
         int*&]' /opt/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:343:67: required
         from 'bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const
         Iterator&, Context&, const Skipper&, Attribute&, const Params&) const [with Context =
         boost::spirit::context<boost::fusion::cons<int*&, boost::fusion::cons<int_holder&,
         boost::fusion::nil> >, boost::fusion::vector0<> >; Skipper = boost::spirit::unused_type;
         Attribute = int*; Params =
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_>; Iterator = const char*; T1 = int*(int_holder&); T2 =
         boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 =
         boost::spirit::unused_type]'
         /opt/local/include/boost/spirit/home/qi/nonterminal/detail/parameterized.hpp:48:79:
         required from 'bool boost::spirit::qi::parameterized_nonterminal<Subject,
         Params>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const
         [with Iterator = const char*; Context = boost::spirit::context<boost::fusion::cons<int*&,
         boost::fusion::cons<int_holder&, boost::fusion::nil> >, boost::fusion::vector0<> >;
         Skipper = boost::spirit::unused_type; Attribute = int*; Subject =
         boost::spirit::qi::rule<const char*, int*(int_holder&), boost::spirit::unused_type,
         boost::spirit::unused_type, boost::spirit::unused_type>; Params =
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_>]' /opt/local/include/boost/spirit/home/qi/action/action.hpp:65:13:
         required from 'bool boost::spirit::qi::action<Subject, Action>::parse(Iterator&, const
         Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = const char*;
         Context = boost::spirit::context<boost::fusion::cons<int*&,
         boost::fusion::cons<int_holder&, boost::fusion::nil> >, boost::fusion::vector0<> >;
         Skipper = boost::spirit::unused_type; Attribute = boost::spirit::unused_type; Subject =
         boost::spirit::qi::parameterized_nonterminal<boost::spirit::qi::rule<const char*,
         int*(int_holder&), boost::spirit::unused_type, boost::spirit::unused_type,
         boost::spirit::unused_type>,
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_> >; Action =
         boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
         boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >
         >]' /opt/local/include/boost/spirit/home/qi/detail/fail_function.hpp:38:72: required from
         'bool boost::spirit::qi::detail::fail_function<Iterator, Context,
         Skipper>::operator()(const Component&, Attribute&) const [with Component =
         boost::spirit::qi::action<boost::spirit::qi::parameterized_nonterminal<boost::spirit::qi::rule<const
         char*, int*(int_holder&), boost::spirit::unused_type, boost::spirit::unused_type,
         boost::spirit::unused_type>,
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_> >,
         boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
         boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >
         > >; Attribute = boost::spirit::unused_type; Iterator = const char*; Context =
         boost::spirit::context<boost::fusion::cons<int*&, boost::fusion::cons<int_holder&,
         boost::fusion::nil> >, boost::fusion::vector0<> >; Skipper = boost::spirit::unused_type]'
         /opt/local/include/boost/spirit/home/qi/detail/pass_container.hpp:263:38: [ skipping 10
         instantiation contexts ] /opt/local/include/boost/function/function_template.hpp:1042:16:
         required from 'boost::function<R(T0, T1, T2, T3)>::function(Functor, typename
         boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value,
         int>::type) [with Functor =
         boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::action<boost::spirit::qi::parameterized_nonterminal<boost::spirit::qi::rule<const
         char*, int*(int_holder&), boost::spirit::unused_type, boost::spirit::unused_type,
         boost::spirit::unused_type>,
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_> >,
         boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
         boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >
         > > >, mpl_::bool_<false> >; R = bool; T0 = const char*&; T1 = const char* const&; T2 =
         boost::spirit::context<boost::fusion::cons<int*&, boost::fusion::cons<int_holder&,
         boost::fusion::nil> >, boost::fusion::vector0<> >&; T3 = const
         boost::spirit::unused_type&; typename
         boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value,
         int>::type = int]' /opt/local/include/boost/function/function_template.hpp:1083:5:
         required from 'typename
         boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value,
         boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2,
         T3)>::operator=(Functor) [with Functor =
         boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::action<boost::spirit::qi::parameterized_nonterminal<boost::spirit::qi::rule<const
         char*, int*(int_holder&), boost::spirit::unused_type, boost::spirit::unused_type,
         boost::spirit::unused_type>,
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_> >,
         boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
         boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >
         > > >, mpl_::bool_<false> >; R = bool; T0 = const char*&; T1 = const char* const&; T2 =
         boost::spirit::context<boost::fusion::cons<int*&, boost::fusion::cons<int_holder&,
         boost::fusion::nil> >, boost::fusion::vector0<> >&; T3 = const
         boost::spirit::unused_type&; typename
         boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value,
         boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(const char*&, const
         char* const&, boost::spirit::context<boost::fusion::cons<int*&,
         boost::fusion::cons<int_holder&, boost::fusion::nil> >, boost::fusion::vector0<> >&,
         const boost::spirit::unused_type&)>&]'
         /opt/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:182:13: required from
         'static void boost::spirit::qi::rule<Iterator, T1, T2, T3,
         T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_)
         [with Auto = mpl_::bool_<false>; Expr =
         boost::proto::exprns_::expr<boost::proto::tagns_::tag::unary_plus,
         boost::proto::argsns_::list1<const
         boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
         boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
         boost::proto::argsns_::term<boost::spirit::qi::parameterized_nonterminal<boost::spirit::qi::rule<const
         char*, int*(int_holder&), boost::spirit::unused_type, boost::spirit::unused_type,
         boost::spirit::unused_type>,
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_> > >, 0l>&,
         boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
         boost::proto::argsns_::term<const
         boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
         boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >
         >&>, 0l> >, 2l>&>, 1l>; Iterator = const char*; T1 = int*(int_holder&); T2 =
         boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 =
         boost::spirit::unused_type; boost::spirit::qi::rule<Iterator, T1, T2, T3, T4> =
         boost::spirit::qi::rule<const char*, int*(int_holder&), boost::spirit::unused_type,
         boost::spirit::unused_type, boost::spirit::unused_type>; mpl_::true_ =
         mpl_::bool_<true>]' /opt/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:220:13:
         required from 'boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&
         boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr =
         boost::proto::exprns_::expr<boost::proto::tagns_::tag::unary_plus,
         boost::proto::argsns_::list1<const
         boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript,
         boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
         boost::proto::argsns_::term<boost::spirit::qi::parameterized_nonterminal<boost::spirit::qi::rule<const
         char*, int*(int_holder&), boost::spirit::unused_type, boost::spirit::unused_type,
         boost::spirit::unused_type>,
         boost::fusion::vector<boost::phoenix::actor<boost::spirit::attribute<0> >,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_> > >, 0l>&,
         boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
         boost::proto::argsns_::term<const
         boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval,
         boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
         boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >
         >&>, 0l> >, 2l>&>, 1l>; Iterator = const char*; T1 = int*(int_holder&); T2 =
         boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 =
         boost::spirit::unused_type; boost::spirit::qi::rule<Iterator, T1, T2, T3, T4> =
         boost::spirit::qi::rule<const char*, int*(int_holder&), boost::spirit::unused_type,
         boost::spirit::unused_type, boost::spirit::unused_type>]' test_qi.cpp:41:3: required from
         'my_grammar<Iterator>::my_grammar() [with Iterator = const char*]' test_qi.cpp:57:26:
         required from here /opt/local/include/boost/fusion/container/list/cons.hpp:83:40: error:
         invalid initialization of reference of type 'boost::fusion::cons<int_holder&,
         boost::fusion::nil>::car_type {aka int_holder&}' from expression of type 'int*'

There is obviously a problem when passing _r1 to the phoenix::function, but I have no idea how to solve it. Thanks in advance.

Giuliano
  • 640
  • 3
  • 15
  • please post your finding as an answer to your own question in the text box below, rather than making an update. This is to make it easier for googlers to find this answer. Or, vote to close this question. – vidstige Aug 14 '12 at 14:19

1 Answers1

3

Sorry, I have just discovered the error, the line of code

start = +next(_val) [_val = _1];

needed to be changed to

start = +next(_r1) [_val = _1];

and then it works. Sorry for wasting you time! Bye!

Giuliano
  • 640
  • 3
  • 15