2010-06-25 21 views
3

與提升精神的語法生成錯誤(提高1.43和g ++ 4.4.1)第三部分

我想建立一個語法,目前它看起來像這樣:

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

的剪斷構建錯誤如下,基本上它說,試圖初始化一個MockExpressionNode &(可能是push_back參數)與std :: vector < MockExpressionNode>,就像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' 

我試圖鳳::綁定僅嘗試這種原始形式後到std ::矢量::的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

建議使用phoenix :: push_back的第二種形式。問題在於定義了語義動作的地方。 -(whatever % ",")構造的屬性值類型爲vector<whatever>,然後將其作爲在vector<MockExpressionNode>上調用的push_back的參數傳遞。換句話說,精神不會改變論據,代碼基本上是vector<>.push_back(vector<>)。您可以在您發佈的最後一個錯誤塊的第三行看到:

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

調試編譯錯誤,這個東西有時需要字裏行間,從字面上;)

相反,附加的push_back行動直接使用parameter解析器,因爲此解析器具有屬性類型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) ] 
      % "," 
     ) 
    >> ")"; 
+0

謝謝!我閱讀這個文檔http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/spirit/qi/reference/operator/list.html,但我沒有注意到Vector <>是由複合返回的屬性,我必須閱讀關於複合屬性表示法! 謝謝! – lurscher 2010-06-25 21:21:09

+0

我在這裏添加了後續問題http://stackoverflow.com/questions/3125582/boost-spirit-qi-numeric-parsing-of-integer-and-floating-points – lurscher 2010-06-26 21:42:35