2015-08-27 53 views
4

我正在爲日期解析編寫boost :: spirit :: qi語法。boost :: phoenix try_ catch_all構造無法編譯

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/date_time.hpp> 

template < typename InputIterator > 
struct date_rfc1123_grammar : 
      boost::spirit::qi::grammar< InputIterator, boost::gregorian::date()> { 
    typedef boost::gregorian::date value_type; 
    date_rfc1123_grammar() : date_rfc1123_grammar::base_type(date) 
    { 
     namespace qi = boost::spirit::qi; 
     namespace phx = boost::phoenix; 
     using qi::_pass; 
     using qi::_val; 
     using qi::_2; 
     using qi::_3; 
     using qi::_4; 

     _2digits = qi::uint_parser< std::uint32_t, 10, 2, 2 >(); 
     _4digits = qi::uint_parser< std::uint32_t, 10, 4, 4 >(); 
     date = (weekday >> ' ' >> _2digits >> ' ' >> month >> ' ' >> _4digits) 
      [ 
       phx::try_[ 
       _val = phx::construct<value_type>(_4, _3, _2) 
       ].catch_all[ 
       _pass = false 
       ] 
      ]; 
    } 
    boost::spirit::qi::rule< InputIterator, value_type()> date; 
    weekday_grammar weekday; 
    month_grammar month; 
    boost::spirit::qi::rule< InputIterator, std::int32_t() > _2digits; 
    boost::spirit::qi::rule< InputIterator, std::int32_t() > _4digits; 
}; 

我依靠boost::gregorian::date構造函數的參數檢查,並希望解析器在異常情況下失敗。但boost::phoenix::try_[ ].catch_all[ ]構建失敗,出現以下消息編譯:

/path_to_file/datetime_parse.hpp:102:8: required from ‘tip::http::grammar::parse::date_rfc1123_grammar<InputIterator>::date_rfc1123_grammar() [with InputIterator = boost::spirit::multi_pass<std::istreambuf_iterator<char, std::char_traits<char> > >]’ 
/path_to_file/grammar_parse_test.hpp:17:7: required from here 
/usr/local/include/boost/proto/traits.hpp:341:13: error: static assertion failed: 0 == Expr::proto_arity_c 
      BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); 
      ^

沒有try_.catch_all構建語法編譯OK,但我想分析器捕獲異常,並設置_pass標誌設置爲false,使語法失敗。

操作系統和編譯器的信息:

$ uname -a 
Linux zmij 3.19.0-27-generiC#29-Ubuntu SMP Fri Aug 14 21:43:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux 
$ g++ -v 
Thread model: posix 
gcc version 4.9.2 (Ubuntu 4.9.2-10ubuntu13) 

增壓版本1.58

+0

我想你低估了時間它需要隨機幫助者準確找出您省略的標題以及缺少哪些其他位來測試您的代碼。你應該總是包含一個SSCCE(又名MCVE)。特別是因爲在這種情況下這是微不足道的(對你!)。 – sehe

+0

對不起@sehe,解決了這個問題。 – zmij

回答

4

我以前見過這個,可能是當地某些升壓/編譯器版本。

一種解決方法將包括使其成爲一個序列的無操作語句(如_pass=_pass):

date = (weekday >> ' ' >> _2digits >> ' ' >> month >> ' ' >> _4digits) 
     [ 
      _pass = _pass, 
      phx::try_[ 
      _val = phx::construct<value_type>(_4, _3, _2) 
      ].catch_all[ 
      _pass = false 
      ] 
     ]; 

看到它Live On Coliru

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/date_time/gregorian/greg_date.hpp> 

template <typename InputIterator> 
struct date_rfc1123_grammar : boost::spirit::qi::grammar< InputIterator, boost::gregorian::date()> 
{ 
    typedef boost::gregorian::date value_type; 
    date_rfc1123_grammar() : date_rfc1123_grammar::base_type(date) 
    { 
     namespace qi = boost::spirit::qi; 
     namespace phx = boost::phoenix; 
     using qi::_pass; 
     using qi::_val; 
     using qi::_2; 
     using qi::_3; 
     using qi::_4; 

     date = (weekday >> ' ' >> _2digits >> ' ' >> month >> ' ' >> _4digits) 
      [ 
       _pass = _pass, 
       phx::try_[ 
       _val = phx::construct<value_type>(_4, _3, _2) 
       ].catch_all[ 
       _pass = false 
       ] 
      ]; 
    } 
    boost::spirit::qi::rule< InputIterator, value_type()> date; 
    boost::spirit::qi::rule< InputIterator, uint()> weekday, month; 
    boost::spirit::qi::uint_parser< std::uint32_t, 10, 2, 2 > _2digits; 
    boost::spirit::qi::uint_parser< std::uint32_t, 10, 4, 4 > _4digits; 
}; 

int main() { 
    using It = std::string::const_iterator; 
    std::string const input; 

    date_rfc1123_grammar<It> g; 

    It f = input.begin(), l = input.end(); 

    boost::gregorian::date d; 
    bool ok = boost::spirit::qi::parse(f, l, g, d); 

    return ok?1:2; 
}