Advertisement
Guest User

Boost C++ parsing of a CSV

a guest
Jan 15th, 2015
472
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.45 KB | None | 0 0
  1. #define BOOST_SPIRIT_DEBUG
  2. #include <iostream>
  3. #include <boost/spirit/include/qi.hpp>
  4. #include <boost/spirit/include/phoenix.hpp>
  5. #include <string>
  6. #include <vector>
  7.  
  8. namespace qi = boost::spirit::qi;
  9. namespace phx = boost::phoenix;
  10.  
  11. using std::string;
  12.  
  13. enum LineItems {
  14.     NAME, AGE, UNUSED
  15. };
  16.  
  17. struct CsvLine {
  18.     string name;
  19.     int age;
  20. };
  21.  
  22. using Column = std::string;
  23. using Columns = std::vector<Column>;
  24. using CsvFile = std::vector<CsvLine>;
  25.  
  26. template<typename It>
  27. struct CsvGrammar: qi::grammar<It, CsvFile(), qi::locals<std::vector<LineItems>>, qi::blank_type> {
  28.     CsvGrammar() :
  29.             CsvGrammar::base_type(start) {
  30.         using namespace qi;
  31.  
  32.         static const char colsep = ',';
  33.  
  34.         start = qi::omit[header[qi::_a = qi::_1]] >> eol >> line(_a) % eol;
  35.         header = (lit("Name")[phx::push_back(phx::ref(qi::_val), LineItems::NAME)]
  36.                 | lit("Age")[phx::push_back(phx::ref(qi::_val), LineItems::AGE)]
  37.                 | column[phx::push_back(phx::ref(qi::_val), LineItems::UNUSED)]) % colsep;
  38.         line = (column % colsep)[phx::bind(&CsvGrammar<It>::convertFunc, this, qi::_1, qi::_r1,
  39.                 qi::_val)];
  40.         column = quoted | *~char_(",\n");
  41.         quoted = '"' >> *("\"\"" | ~char_("\"\n")) >> '"';
  42.  
  43.         BOOST_SPIRIT_DEBUG_NODES((header)(column)(quoted));
  44.     }
  45.  
  46.     void convertFunc(const std::vector<string>& columns, const std::vector<LineItems>& positions, CsvLine &csvLine) {
  47.         int i =0;
  48.         for (LineItems position : positions) {
  49.             switch(position){
  50.             case NAME:
  51.                 csvLine.name = columns[i];
  52.                 break;
  53.             case AGE:
  54.                 csvLine.age = atoi(columns[i].c_str());
  55.                 break;
  56.             }
  57.             i++;
  58.         }
  59.     }
  60. private:
  61.     qi::rule<It, CsvFile(), qi::locals<std::vector<LineItems>>, qi::blank_type> start;
  62.     qi::rule<It, std::vector<LineItems>(), qi::blank_type> header;
  63.     qi::rule<It, CsvLine(std::vector<LineItems>), qi::blank_type> line;
  64.     qi::rule<It, Column(), qi::blank_type> column;
  65.     qi::rule<It, std::string()> quoted;
  66.     qi::rule<It, qi::blank_type> empty;
  67.  
  68. };
  69.  
  70. int main() {
  71.     const std::string s = "Surname,Name,Age,\nJohn,Doe,32\nMark,Smith,43";
  72.  
  73.     auto f(begin(s)), l(end(s));
  74.     CsvGrammar<std::string::const_iterator> p;
  75.  
  76.     CsvFile parsed;
  77.     bool ok = qi::phrase_parse(f, l, p, qi::blank, parsed);
  78.  
  79.     if (ok) {
  80.         for (CsvLine line : parsed) {
  81.             std::cout << '[' << line.name << ']' << '[' << line.age << ']';
  82.             std::cout << std::endl;
  83.         }
  84.     } else {
  85.         std::cout << "Parse failed\n";
  86.     }
  87.  
  88.     if (f != l)
  89.         std::cout << "Remaining unparsed: '" << std::string(f, l) << "'\n";
  90. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement