2016-04-14 6 views
1

Я пытаюсь написать синтаксический анализатор для файла csv, используя библиотеку boost.spirit. следующая ошибка компиляции Я новичок в boost.spirit, поэтому кто-то может определить причиныboost.spirit ошибка компиляции: невозможно преобразовать аргумент 1 из «const char *» в «std :: _ String_iterator <std :: _ String_val>

сообщение об ошибке:.? C2664

ошибка: «BOOL повышение :: дух :: ци :: правила :: parse (Итератор &, const Итератор &, Контекст &, const Skipper &, Атрибут &) cons т ': не удается преобразовать аргумент 1 из 'сопзЬ символ *' в 'станд :: _ String_iterator >> &'

И мой код:

#pragma once 
#define BOOST_SPIRIT_USE_PHOENIX_V3 

#include<vector> 
#include<string> 
#include<memory> 
#include<boost/iostreams/device/mapped_file.hpp> // for mmap 
#include<boost/utility/string_ref.hpp> 
#include<boost/spirit/include/qi.hpp> 
#include<boost/spirit/include/qi_grammar.hpp> 
#include<boost/spirit/include/qi_real.hpp> 
#include<boost/spirit/include/phoenix.hpp> 
#include<boost/spirit/include/qi_symbols.hpp> 

typedef boost::string_ref CsvField; 
typedef std::vector<CsvField> CsvLine; 
typedef std::vector<CsvLine> CsvFile; 
namespace qi = boost::spirit::qi; 

template <typename T> struct CsvParser : qi::grammar<T, CsvFile()> { 
    CsvParser() : CsvParser::base_type(lines) { 
     using namespace qi; 
     using boost::phoenix::construct; 
     using boost::phoenix::size; 
     using boost::phoenix::begin; 
     using boost::spirit::qi::float_; 

     field = raw[*~char_(",\r\n")][_val = construct<CsvField>(begin(qi::_1), size(qi::_1))]; // semantic action 
     //field = qi::float_; 
     line = field % ','; 
     lines = line % eol; 
    } 
    // declare: line, field, fields 
    qi::rule<T, CsvFile()> lines; 
    qi::rule<T, CsvLine()> line; 
    qi::rule<T, CsvField()> field; 
}; 

код действительно заимствованы из Simplest way to read a CSV file mapped to memory?, так У меня нет никакой подсказки. Я использую Microsoft Visual Studio 2015 и увеличиваю 1.16.0.

Эта же ошибка возникает, если я заменил typedef boost::string_ref CsvField на typedef std::string или заменил синтаксический анализатор на поле field = *(~char_(",\r\n")).

Кроме того, файл, который я обрабатываю, действительно является стандартным CSV-файлом, поэтому любое предложение альтернативных методов анализа приветствуется. Единственный улов в том, что файл имеет миллионы строк, поэтому стандартный поэтапный разбор не работает для меня.

ответ

0

Вы не показываете соответствующий код. Все, что у вас есть, это класс шаблонов, но независимо от того, является ли какое-либо инстанцирование даже корректным, зависит от того, с чем вы его создаете.

Прямо сейчас я предполагаю, что вы пытаетесь создать экземпляр с помощью std::string::const_iterator в качестве типа итератора - что немного смешно w.r.t. упоминание о картографии памяти и string_ref (что подразумевает, что вы хотите сделать все с нулевой копией).

Тем не менее, вопрос то в том, что raw[] выставляет iterator_range типа итератора источника, то есть вы передаете std::string::const_iterator в качестве первого аргумента string_ref (псевдоним) CsvField конструктора. Это не сработает.

В затруднительном:

field = raw[*~char_(",\r\n")][_val = construct<CsvField>(&*begin(qi::_1), size(qi::_1))]; // semantic action 

Чтобы быть действительно хорошо вы должны обернуть std::addressof в феникс актера и использовать его вместо operator&. Я оставлю это как упражнение для читателя.

Live On Coliru

#define BOOST_SPIRIT_USE_PHOENIX_V3 
#include<boost/utility/string_ref.hpp> 
#include<boost/spirit/include/qi.hpp> 
#include<boost/spirit/include/phoenix.hpp> 

typedef boost::string_ref CsvField; 
typedef std::vector<CsvField> CsvLine; 
typedef std::vector<CsvLine> CsvFile; 

namespace qi = boost::spirit::qi; 

template <typename T> struct CsvParser : qi::grammar<T, CsvFile()> { 
    CsvParser() : CsvParser::base_type(lines) { 
     using namespace qi; 
     using boost::phoenix::construct; 
     using boost::phoenix::size; 
     using boost::phoenix::begin; 
     using boost::spirit::qi::float_; 

     field = raw[*~char_(",\r\n")][_val = construct<CsvField>(&*begin(qi::_1), size(qi::_1))]; // semantic action 
     //field = qi::float_; 
     line = field % ','; 
     lines = line % eol; 
    } 
    // declare: line, field, fields 
    qi::rule<T, CsvFile()> lines; 
    qi::rule<T, CsvLine()> line; 
    qi::rule<T, CsvField()> field; 
}; 

int main() 
{ 
    using It = std::string::const_iterator; 
    CsvParser<It> p; 

    std::string const input = R"([section1] 
key1=value1 
key2=value2 
[section2] 
key3=value3 
key4=value4 
)"; 

    CsvFile parsed; 
    auto f = input.begin(), l = input.end(); 
    bool ok = parse(f, l, p, parsed); 

    if (ok) { 
     std::cout << "Parsed: " << parsed.size() << " stuffs\n"; 
    } else { 
     std::cout << "Parse failed\n"; 
    } 

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

Печать:

Parsed: 7 stuffs 

 Смежные вопросы

  • Нет связанных вопросов^_^