я пытаюсь понять следующий результат. Код тестового сценария
#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 <cstdlib>
#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 P>
void test_parser(
char const* input, P const& p, bool full_match = true)
{
using boost::spirit::qi::parse;
char const* f(input);
char const* l(f + strlen(f));
if (parse(f, l, p) && (!full_match || (f == l)))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
int main() {
test_parser("+12345", qi::int_ ); //Ok
test_parser("+12345", qi::double_ - qi::int_ ); //failed, as expected
test_parser("+12345.34", qi::int_ ); // failed, as expected
test_parser("+12345.34", qi::double_ - qi::int_ ); //failed but it should be Ok!
};
мотивация здесь - то, что я хочу соответствовать числам '12345' как целые числа и НИКОГДА как плавающие точки. '12345.34' будет соответствовать double_ и никогда int_, но взаимный случай не верен; '12345' соответствия оба целых числа (int_) и плавающая точка (double_). Я попробовал double_ - int_, и ему успешно не удалось соответствовать '12345'. Однако моя надежда состояла в том, что последний тестовый сценарий '12345.34' будет положительно соответствовать double_ - интервал _, но результатом, который я получаю, является сбой для соответствия.
Почему это так, и как я получаю синтаксический анализатор, который только соответствует целым числам и другому, который только соответствует плавающим точкам (как в c, 5.0 был бы интерпретирован как плавающая точка),
Что касается вашего конкретного примера, я думаю, он фактически описан в документации Boost Spirit в разделе RealPolicies
Specialization. Для того, чтобы сделать вещи немного проще для вас, я выхватила быстрый «реальный» парсер, что только разбирает действительные числа, а не целые числа (или, по крайней мере, он работал с упрощенными примерами):
template <typename T>
struct strict_real_policies : qi::real_policies<T>
{
static bool const expect_dot = true;
};
qi::real_parser< double, strict_real_policies<double> > real;
И вы можете использовать это так же, как любой другой парсер (например, int_ и double_). Возможно, вам придется добавить:
#include <boost/spirit/include/qi_numeric.hpp>
Чтобы он скомпилировался.
Проблема с double-not-int qi :: double_ - qi :: int_
заключается в том, что отдельный синтаксический анализатор не должен сопоставлять весь ввод для успешного сопоставления. Для «+12345,34» qi :: double_ обеспечивает успешное сопоставление для всего, а qi :: int выполняет успешное сопоставление для «+12345», так что qi :: double_ - qi :: int_
не совпадает. Для оператора различия подумайте о применении каждого синтаксического анализатора отдельно и о том, существует ли для каждого действительное совпадение даже для первой части ввода.
Вы можете добиться желаемого поведения, установив некую границу после qi :: int_. Что следует, когда qi :: int_ соответствует первой части числа с плавающей запятой, является допустимым числом с плавающей запятой (например, qi :: int_ на «+12345,34» соответствует «+12345», оставляя «.34» следующим в потоке). Следовательно, вы можете сделать отрицательный прогноз для числа с плавающей запятой:
int_rule %= qi::int_ >> !qi::double_;
double_rule %= qi::double_ - int_rule;
или
double_rule %= qi::double_ - (qi::int_ >> !qi::double_);
! Qi :: double
также верно для пробелов и eoi, поэтому я думаю, что это должно быть довольно общим для стандартного формата. Однако это не сработает для научных обозначений.