2015-08-27 2 views
4

Я пишу boost :: spirit :: qi grammar для синтаксического анализа даты.boost :: phoenix try_ catch_all construct не удается скомпилировать

#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 построить грамматику компилирует ОК, но я хотел бы анализатору, чтобы поймать исключение и установить _pass флаг ложь, чтобы сделать грамматику потерпеть неудачу.

OS и составитель информация:

$ 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; 
} 
Смежные вопросы