как разобрать и проверить упорядоченный список целых чисел с помощью ци

Я разбираю текстовый файл,возможно, размером несколько ГБ, состоящий из следующих строк:

11 0.1
14 0.78
532 -3.5

Обычно, один int и один float на строку. Целые числа должны быть упорядоченными и неотрицательными. Я хотел бы убедиться, что данные соответствуют описанию, и вернули мне min и max int в диапазоне. Вот что я придумал:

#include <iostream>
#include <string>

#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>

namespace px = boost::phoenix;
namespace qi = boost::spirit::qi;

namespace my_parsers
{
using namespace qi;
using px::at_c;
using px::val;
template <typename Iterator>
struct verify_data : grammar<Iterator, locals<int>, std::pair<int, int>()>
{
    verify_data() : verify_data::base_type(section)
    {
        section
            =  line(val(0))    [ at_c<0>(_val) = _1]
            >> +line(_a)       [ _a = _1]
            >> eps             [ at_c<1>(_val) = _a]
            ;

        line
            %= (int_ >> other) [
                                   if_(_r1 >= _1)
                                   [
                                       std::cout << _r1 << " and "
                                       << _1 << val(" out of order\n")
                                   ]
                               ]
            ;

        other
            = omit[(lit(' ') | '\t') >> float_ >> eol];
    }
    rule<Iterator, locals<int>, std::pair<int, int>() > section;
    rule<Iterator, int(int)> line;
    rule<Iterator> other;
};
}

using namespace std;
int main(int argc, char** argv)
{
    string input("11 0.1\n"
                 "14 0.78\n"
                 "532 -3.6\n");

    my_parsers::verify_data<string::iterator> verifier;
    pair<int, int> p;
    std::string::iterator begin(input.begin()), end(input.end());
    cout << "parse result: " << boolalpha
         << qi::parse(begin, end, verifier, p) << endl; 
    cout << "p.first: " << p.first << "\np.second: " << p.second << endl;
    return 0;
}

Я хотел бы знать следующее:

  • Есть ли лучший способ сделать это? Я использовал унаследованные и синтезированные атрибуты, локальные переменные и немного феникса вуду. Отлично; изучение инструментов - это хорошо, но я не могу не думать, что может быть гораздо более простой способ добиться того же: / (в парсере PEG, который ...)
  • Как это можно было сделать, например, без локальной переменной?

Дополнительная информация: У меня есть другие форматы данных, которые анализируются одновременно, поэтому я хотел бы сохранить возвращаемое значение как атрибут анализатора. На данный момент это std :: pair, другие форматы данных при синтаксическом анализе, например, будут открывать свои собственные пары std :: pair, и это я хотел бы поместить в std :: vector.

5
задан dpj 23 June 2011 в 15:58
поделиться