2015-08-27 56 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; 
}