Understand the vector <vector <double>> with boost :: spirit

My intention is to split the list of values ​​separated by commas into a nested vector. This list is two-dimensional. The main question:

Is it possible to analyze a vector of a vector with boost :: spirit?

Something like the table in the "Traction" section:

' ' 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. ' 

In the next step I would like to read in 4-dimensional data, but so far I am struggling with the second dimension. The data structure looks like this:

 struct table { std::vector<double> index; std::vector<double> index2; std::vector<std::vector<double> > base; }; 

The IMHO grammar is pretty simple:

 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 ; 

So far I have not had problems analyzing two vectors index and index2 . But the problem starts with base . I think in the crucial section I define vectorblock :

 vectorblock = *doublevector; 

I have tried several variations of this statement. Also, the %= operator did not change anything from this question. Although attribute propagation may be the right direction.

If I follow the example of accompanying documentation “with style” , the result will be the same:

 vectorblock = doublevector % qi::eps; 

Sample Redux list that use push_back() :

 vectorblock = doublevector[phoenix::push_back(qi::_val, qi::_1)] % qi::eps; 

trigger a stream of compilation errors, starting with:

error C2039: 'push_back': not a member of 'boost :: spirit :: unused_type'

Update: The problem was in the vectorblock . I forgot () after the attribute type. So, the definition should look like this:

 qi::rule<Iterator, std::vector<std::vector<double> >(), Skipper> vectorblock; 

Working example (updated):

 #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" "' RPM\n" "'\n" "0,5010,10000,15000,20000,25000\n" "'\n" "' Temp\n" "'\n" "-40.,0.,20.,40.\n" "'\n" "' Traction\n" "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; } 
+5
source share
1 answer

The answer is yes. It’s actually pretty trivial to understand vector<vector<double> >

Defining a rule requires a function type, not a type directly. This is simply explained here . A more detailed explanation is probably contained in the boost :: phoenix documentation

The result of the above program now shows the analyzed values ​​well:

 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, 
+3
source

All Articles