Разбор в вектор> с boost:: spirit
мое намерение состоит в том, чтобы разобрать разделенный запятыми список значений на вложенный вектор. Этот список является двумерным. Основной вопрос:
можно ли разбирать вектор вектора с помощью boost:: spirit?
что-то вроде таблицы под "тягой":
'
' RPM
0,5000,10000,15000,20000,25000
'
' Temp
'
-40.,0.,20.,40.
'
' Traction
200.,175.,170.,165.,160.,150.
200.,175.,170.,165.,160.,150.
165.,165.,160.,155.,145.,145.
160.,155.,150.,145.,145.,140.
'
на следующем этапе я хотел бы прочитать в 4-мерных данных, но пока я борюсь со вторым измерением. Структура данных выглядит так этот:
struct table {
std::vector<double> index;
std::vector<double> index2;
std::vector<std::vector<double> > base;
};
грамматика ИМХО довольно проста следующим образом:
comment %= qi::lexeme[ ''' >> *(qi::standard::char_ - qi::eol)] >> qi::eol;
commentblock = comment >> *(comment);
doublevector = qi::double_ % ',' >> qi::eol ;
vectorblock = *doublevector;
start = commentblock >>
doublevector >>
commentblock >>
doublevector >>
commentblock >>
vectorblock >>
commentblock >>
qi::eoi
;
до сих пор у меня нет проблем с разбором двух векторов index
и index2
. Но проблема начинается с base
. Я думаю, что решающий раздел-это то, где я определяю vectorblock
:
vectorblock = *doublevector;
я пробовал несколько вариантов этого утверждения. Также %=
оператор этой вопрос ничего не меняет. Хотя атрибут распространение может быть правильным направлением.
если я буду следовать примеру документации boost "стиль", результат точно такой же:
vectorblock = doublevector % qi::eps;
список образцов Redux, которые используют push_back()
:
vectorblock = doublevector[phoenix::push_back(qi::_val, qi::_1)] % qi::eps;
спровоцировать поток ошибок компиляции, начиная с:
ошибка C2039: 'push_back': не является членом 'boost:: spirit:: unused_type'
обновление: проблема был при объявлении vectorblock
. Я забыл ()
после данного типа атрибута. Итак, определение должно выглядеть так:
qi::rule<Iterator, std::vector<std::vector<double> >(), Skipper> vectorblock;
(обновленный) рабочий пример находится здесь:
#include <iostream>
#include <string>
#include <vector>
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted.hpp>
struct table {
std::vector<double> index;
std::vector<double> index2;
std::vector<std::vector<double> > base;
};
BOOST_FUSION_ADAPT_STRUCT(
table,
(std::vector<double> , index)
(std::vector<double> , index2)
(std::vector<std::vector<double> >, base)
)
const std::string contents =
"'n"
"' RPMn"
"'n"
"0,5010,10000,15000,20000,25000n"
"'n"
"' Tempn"
"'n"
"-40.,0.,20.,40.n"
"'n"
"' Tractionn"
"200.,175.,170.,165.,160.,150.n"
"200.,175.,170.,165.,160.,150.n"
"165.,165.,160.,155.,145.,145.n"
"160.,155.,150.,145.,145.,140.n"
"'n"
;
int main()
{
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
typedef std::string::const_iterator Iterator;
typedef boost::spirit::ascii::blank_type Skipper;
qi::rule<Iterator, std::string(), Skipper> comment;
qi::rule<Iterator, Skipper> commentblock;
qi::rule<Iterator, std::vector<double>(), Skipper> doublevector;
qi::rule<Iterator, std::vector<std::vector<double> >, Skipper> vectorblock;
qi::rule<Iterator, table(), Skipper> start;
comment %= qi::lexeme[ ''' >> *(qi::standard::char_ - qi::eol)] >> qi::eol;
commentblock = comment >> *(comment);
doublevector = qi::double_ % ',' >> qi::eol ;
vectorblock = *doublevector;
start = commentblock >>
doublevector >>
commentblock >>
doublevector >>
commentblock >>
vectorblock >>
commentblock >>
qi::eoi
;
BOOST_SPIRIT_DEBUG_NODES((start)(doublevector)(vectorblock));
table tref;
bool rv = qi::phrase_parse(
std::begin(contents), std::end(contents),
start,
boost::spirit::ascii::blank,
tref
);
std::cout << "parse " << ((char *)rv?"success":"failure") << ".n";
for (auto i : tref.index)
std::cout << i << ", ";
std::cout << "n";
for (auto i : tref.index2)
std::cout << i << ", ";
std::cout << "nBase:n";
for (auto & i : tref.base)
{
for(auto & j : i)
std::cout << j << ", ";
std::cout << "n";
}
std::cout << std::endl;
}
1 ответов
ответ-да.
На самом деле довольно тривиально разбирать на vector<vector<double> >
для определения правила требуется тип функции, а не тип напрямую. Это просто объясняется здесь. Более подробное объяснение нашел в документации boost:: phoenix
выход программы выше теперь показывает красиво проанализированные значения:
parse success.
0, 5011, 10000, 15000, 20000, 25000,
-40, 0, 20, 40,
Base:
200, 175, 170, 165, 160, 150,
200, 175, 170, 165, 160, 150,
165, 165, 160, 155, 145, 145,
160, 155, 150, 145, 145, 140,