3

好的

我正在尝试构建语法,目前它看起来像这样:

#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 */

构建错误的片段如下,基本上它说正在尝试使用 std::vector< MockExpressionNode > 初始化 MockExpressionNode& (可能是 push_back 参数),就像某种方式 phoenix::bind 切换对象的顺序和参数参数。

../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'

仅在尝试了以下原始形式后,我才尝试将 phoenix::bind 绑定到 std::vector::push_back :

    >> -(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 )
        ]
    >>  ")";

我得到了这个错误(只有最后一部分)关于 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::fusion::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'
4

1 回答 1

4

建议使用 phoenix::push_back 的第二种形式。问题在于语义动作的定义位置。该-(whatever % ",")构造的属性值类型为vector<whatever>,然后您将其作为在 上调用的 push_back 的参数传递vector<MockExpressionNode>。换句话说,精神不是切换参数,代码本质上是vector<>.push_back(vector<>). 您可以在您发布的最后一个错误块的第三行中看到这一点:

/home/.../container.hpp:492:错误:没有匹配的调用函数
 'std::vector<...>::push_back(const std::vector<...>&)'

用这些东西调试编译错误有时需要在字面上阅读;)

相反,直接将 push_back 操作附加到parameter解析器,因为此解析器具有属性 type MockExpressionNode。尝试:

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 ) ] 
            %   ","
       )
    >>  ")";
于 2010-06-25T04:33:28.833 回答