开发者

build error with boost spirit grammar (boost 1.43 and g++ 4.4.1) part III

Ok

i am trying to build a grammar and currently it looks like this:

#ifndef _INPUTGRAMMAR_H
#define _INPUTGRAMMAR_H

#include <boost/config/warning_disable.hpp>
#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_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/spirit/home/support/context.hpp>
#include <boost/spirit/home/phoenix.hpp>
#include <boost/foreach.hpp>

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

namespace sp = boost::spirit;
namespace qi = boost::spirit::qi;
using namespace boost::spirit::ascii;

namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;

using phoenix::at_c;
using phoenix::push_back;
using phoenix::bind;



template< typename Iterator , typename ExpressionAST >
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> {

    InputGrammar() : InputGrammar::base_type( command ) {

        identifier %= ( qi::char_("a-zA-Z_")  >> *qi::char_("a-zA-Z_0-9") ); 

        tag = identifier
          [
              at_c<0>(qi::_val) = qi::_1,
              phoenix::bind( &ExpressionAST::setAsTag , qi::_val )
          ];

        command =
        identifier
            [
               at_c<0>(qi::_val) = qi::_1,
               phoenix::bind( &ExpressionAST::setAsCommand , qi::_val )
            ]
        >>  "("
        >> -(parameter % ",")
            [
               //phoenix::push_back(at_c<1>(qi::_val) , qi::_1 )
                phoenix::bind( &std::vector< ExpressionAST , std::allocator< ExpressionAST > >::push_back, at_c<1>(qi::_val) , qi::_1 )
            ]
        >>  ")";


        parameter = ( command | tag ) [qi::_val = qi::_1];
    }
    qi::rule< Iterator , ExpressionAST() , space_type > tag;
    qi::rule< Iterator , std::string() , space_type > identifier;
    qi::rule< Iterator , ExpressionAST() , space_type > command;
    qi::rule< Iterator , ExpressionAST() , space_type > parameter;
};

#endif  /* _INPUTGRAMMAR_H */

a snip of the build error is the following, basically it says that is trying to initialise a MockExpressionNode& (likely the push_back argument) with a std::vector< MockExpressionNode >, like somehow phoenix::bind where switching the order of the object and the parameter arguments.

../InputParser/InputGrammar.h:63:   instantiated from ‘InputGrammar<Iterator, ExpressionAST>::InputGrammar() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ExpressionAST = MockExpressionNode]’
tests_main.cpp:202:   instantiated from here
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/bind/detail/member_function_ptr.hpp:103: error: invalid initialization of reference of type ‘const MockExpressionNode&’ from expression of type ‘std::vector<MockExpressionNode, std::allocator<MockExpressionNode> >’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/bind/detail/member_function_ptr.hpp:103: error: return-statement with a value, in function returning 'void'

I tried the phoenix::bind to std::vector::push_back only after trying this original form:

    >> -(parameter % ",")
        [
           phoenix::push_back(at_c<1>(qi::_val) , qi::_1 )
           // phoenix::bind( &std::vector< ExpressionAST , std::allocator< ExpressionAST > >::push_back, at_c<1>(qi::_val) , qi::_1 )
        ]
    >>  ")";

i got this error instead (only final portion) about no matching function for std::vector::push_back:

boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::optional<boost::spirit::qi::action<boost::spirit::qi::list<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false> >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::detail::function_eval<2>, boost::fusion::vector<boost::phoenix::value<boost::phoenix::stl::push_back>, boost::phoenix::composite<boost::phoenix::at_eval<1>, boost::fusion::vector<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::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::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil> > > > >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, T1 = const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, T2 = boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >&, T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&]’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/nonterminal/rule.hpp:201:   instantiated 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::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tag::subscript, boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::string(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::sequence_eval, boost::fusion::vector<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::phoenix::composite<boost::phoenix::at_eval<0>, boost::fusion::vector<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::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::f开发者_运维百科usion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::phoenix::composite<boost::phoenix::detail::function_eval<1>, boost::fusion::vector<boost::phoenix::value<boost::phoenix::detail::member_function_ptr<0, void, void (MockExpressionNode::*)()> >, 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::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >&>, 0l> >, 2l>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const char (&)[2]>, 0l> >, 2l>&, const boost::proto::exprns_::expr<boost::proto::tag::negate, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tag::modulus, boost::proto::argsns_::list2<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const char (&)[2]>, 0l> >, 2l>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::detail::function_eval<2>, boost::fusion::vector<boost::phoenix::value<boost::phoenix::stl::push_back>, boost::phoenix::composite<boost::phoenix::at_eval<1>, boost::fusion::vector<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::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >&>, 0l> >, 2l>&>, 1l>&>, 2l>&, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const char (&)[2]>, 0l> >, 2l>, Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = MockExpressionNode(), T2 = boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, T3 = boost::fusion::unused_type, T4 = boost::fusion::unused_type]’
../InputParser/InputGrammar.h:63:   instantiated from ‘InputGrammar<Iterator, ExpressionAST>::InputGrammar() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ExpressionAST = MockExpressionNode]’
tests_main.cpp:202:   instantiated from here
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/stl/container/container.hpp:492: error: no matching function for call to ‘std::vector<MockExpressionNode, std::allocator<MockExpressionNode> >::push_back(const std::vector<MockExpressionNode, std::allocator<MockExpressionNode> >&)’
/usr/include/c++/4.4/bits/stl_vector.h:733: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = MockExpressionNode, _Alloc = std::allocator<MockExpressionNode>]
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/stl/container/container.hpp:492: error: return-statement with a value, in function returning 'void'


The second form using phoenix::push_back is the suggested one. The problem is where the semantic action is defined. The -(whatever % ",") construct has an attribute value type of vector<whatever>, which you then pass as the parameter of push_back called on the vector<MockExpressionNode>. In other words, spirit is not switching the arguments, the code is essentially vector<>.push_back(vector<>). You can see this in the third line of the last error block you posted:

/home/.../container.hpp:492: error: no matching function for call to
 ‘std::vector<...>::push_back(const std::vector<...>&)’

Debugging compile errors with this stuff sometimes requires reading between the lines, literally ;)

Instead, attach the push_back action to the parameter parser directly, since this parser has the attribute type MockExpressionNode . Try:

command =
    identifier
        [
           at_c<0>(qi::_val) = qi::_1,
           phoenix::bind( &ExpressionAST::setAsCommand , qi::_val )
        ]
    >>  "("
    >> -(
                parameter[ phoenix::push_back(at_c<1>(qi::_val) , qi::_1 ) ] 
            %   ","
       )
    >>  ")";
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜