Boost.Spirit.Qi — Проверка границ примитивных типов данных

Мне нужно проверить, что значение проанализировано qi::uint_ меньше 256


Я наткнулся на ТАК сообщение выделение следующего синтаксиса для запуска проверок после анализа примитивного типа (qi::double_ в этом примере).

raw [ double_ [_val = _1] ] [ _pass = !isnan_(_val) && px::size(_1)<=4 ]

Вот, raw[...] возвращает итератор в разобранный qi::double_ значение, и последнее семантическое действие используется для «проверки» результирующего значения.


Экстраполируя из предыдущего примера, я предположил, что могу проверить границы, используя аналогичный подход.

raw [ uint_ [_val = _1] ] [ _pass = _val<=256 ]

К сожалению, я получаю следующую ошибку.

boost.spirit.qi.bounds.cpp:51:105: error: invalid operands to binary expression ('const boost::spirit::_val_type'
(aka 'const actor<attribute<0> >') and 'int')
if (qi::parse(str.begin(), str.end(), qi::raw[qi::uint_[qi::_val = qi::_1]][qi::_pass = qi::_val<=256]).full)
~~~~~~~~^ ~~~

Документация и примеры хороши для базовых парсеров, но они начинают сужаться к более сложным темам; такие как это.

Как я могу преобразовать или извлечь целое число без знака из qi::_val проверить против 256?

1

Решение

Вы пропустили тот факт, что raw[] выставляет диапазон итератора. Другой ответ использовал это, потому что «дополнительное» ограничение относится к длине ввода (в символах).

Вам это не нужно, поэтому вы бы предпочли использовать что-то прямое, например:

Жить на Колиру

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;

int main ()
{
using It = std::string::const_iterator;
qi::rule<It, double()> r
= qi::double_ [ qi::_pass = (qi::_1 < 256.0), qi::_val = qi::_1 ];

for (std::string const s: { "1.23", ".123", "2.e6", "inf", "-inf", "3.2323", "nan" })
{
It f = s.begin(), l = s.end();

double result;
if (parse(f, l, r, result))
std::cout << "accepted: '" << s << "' -> " << result;
else std::cout << "rejected: '" << s << "'";

if (f!=l)
std::cout << " (remaining: '" << std::string(f,l) << "')\n";
else std::cout << "\n";
}
}

Печать

accepted: '1.23' -> 1.23
accepted: '.123' -> 0.123
rejected: '2.e6' (remaining: '2.e6')
rejected: 'inf' (remaining: 'inf')
accepted: '-inf' -> -inf
accepted: '3.2323' -> 3.2323
rejected: 'nan' (remaining: 'nan')

Заметки:

  1. [action1, action2] это способ подачи нескольких утверждений Феникс (в этом случае будет очень похоже на [action1][action2]).

  2. Вы даже можете обойтись без _val= назначение, потому что это только то, что распространение атрибутов по умолчанию.

    Чтобы включить распространение атрибута по умолчанию в правиле, которое семантическое действие (я), используйте operator%= определить это:

    r %= qi::double_ [ qi::_pass = (qi::_1 < 256.0) ];
    

    Жить на Колиру

    Это печатает тот же результат.

1

Другие решения

Других решений пока нет …