c++ - auto concatenation of parse results into vectors -


i've written rules parse floats 2 std::vector's of floats, in turn stored in struct:

data input:

# # object name01 #  v  -1.5701 33.8087 0.3592 v  -24.0119 0.0050 21.7439 # comment  vn 0.0000 0.5346 0.8451 vn 0.8331 0.5531 -0.0000 # comment 

struct:

struct objparsedata {     objparsedata() : verts(), norms() {}      std::vector<float> verts;     std::vector<float> norms; }; 

and relevant parsing code:

struct objgram : qi::grammar<std::string::const_iterator, objparsedata(), iso8859::space_type>     {         objgram() : objgram::base_type(start)         {             vertex  = 'v' >> qi::double_ >> qi::double_ >> qi::double_;             normal  = "vn" >> qi::double_ >> qi::double_ >> qi::double_;             comment = '#' >> qi::skip(qi::blank)[ *(qi::print) ];             vertexlist = *(vertex | comment);             normallist = *(normal | comment);             start = vertexlist >> normallist;         }          qi::rule<std::string::const_iterator, objparsedata(), iso8859::space_type> start;         qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertexlist;         qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> normallist;         qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex;         qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> normal;         qi::rule<std::string::const_iterator, iso8859::space_type> comment;     } objgrammar;       objparsedata resultdata;      std::string::const_iterator f = data.cbegin();     bool res = qi::phrase_parse( f, data.cend(), objgrammar, iso8859::space, resultdata ); 

and works. parses floats preceded 'v' verts vector of struct , floats preceded "vn" norms. great, don't know why works.

now if understand correctly, rule defined below puts results std::vector of floats.

qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex; 

so, looking @ parsing code shown above , knowing rule vertex parses std::vector of floats, apparently rule vertexlist (the 1 shown above) concatenates results vertex 1 std::vector of floats? seeing behaviour, think write 2 rules (vertex , vertexlist) one, unfortunately doesn't work:

vertex  = *('v' >> qi::double_ >> qi::double_ >> qi::double_) | comment; normal  = *("vn" >> qi::double_ >> qi::double_ >> qi::double_) | comment; comment = '#' >> qi::skip(qi::blank)[ *(qi::print) ]; start = vertex >> normal; 

the code compile , qi::phrase_parse return succesfull parse, std::vector's in struct aren't filled anymore.. missing here?

you missplaced grouping parentheses: expanding

    vertexlist = *(vertex | comment);     normallist = *(normal | comment); 

by eliminating subrules leads to

    vertex     = *(('v'  >> qi::double_ >> qi::double_ >> qi::double_) | comment);     normal     = *(("vn" >> qi::double_ >> qi::double_ >> qi::double_) | comment); 

or, i'd prefer:

full working sample (please make code samples sscce next time? https://meta.stackexchange.com/questions/22754/sscce-how-to-provide-examples-for-programming-questions):

#include <iterator> #include <fstream> #include <boost/fusion/adapted.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/karma.hpp> #include <boost/spirit/include/phoenix.hpp>  namespace qi    = boost::spirit::qi; namespace karma = boost::spirit::karma; namespace phx   = boost::phoenix;  struct objparsedata {     objparsedata() : verts(), norms() {}      std::vector<float> verts;     std::vector<float> norms; };  boost_fusion_adapt_struct(objparsedata, (std::vector<float>, verts)(std::vector<float>, norms))    template <typename it, typename skipper = qi::space_type>     struct parser : qi::grammar<it, objparsedata(), skipper> {     parser() : parser::base_type(start)     {         using namespace qi;           vertex     = 'v'  >> qi::double_ >> qi::double_ >> qi::double_;         normal     = "vn" >> qi::double_ >> qi::double_ >> qi::double_;         comment    = '#' >> qi::skip(qi::blank)[ *(qi::print) ]; #if 0         vertexlist = *(vertex | comment);         normallist = *(normal | comment);         start      = vertexlist >> normallist; #else         vertex     = *(comment | ('v'  >> qi::double_ >> qi::double_ >> qi::double_));         normal     = *(comment | ("vn" >> qi::double_ >> qi::double_ >> qi::double_));         start      = vertex >> normal;                                               #endif          boost_spirit_debug_node(start);     }    private:     qi::rule<std::string::const_iterator, objparsedata(), qi::space_type> start;     qi::rule<std::string::const_iterator, std::vector<float>(), qi::space_type> vertexlist;     qi::rule<std::string::const_iterator, std::vector<float>(), qi::space_type> normallist;     qi::rule<std::string::const_iterator, std::vector<float>(), qi::space_type> vertex;     qi::rule<std::string::const_iterator, std::vector<float>(), qi::space_type> normal;     qi::rule<std::string::const_iterator, qi::space_type> comment; };  bool doparse(const std::string& input) {     typedef std::string::const_iterator it;     auto f(begin(input)), l(end(input));      parser<it, qi::space_type> p;     objparsedata data;      try     {         bool ok = qi::phrase_parse(f,l,p,qi::space,data);         if (ok)            {             std::cout << "parse success\n";             std::cout << "data: " << karma::format_delimited(                     "v: " << karma::auto_ << karma::eol <<                     "n: " << karma::auto_ << karma::eol, ' ', data);         }         else      std::cerr << "parse failed: '" << std::string(f,l) << "'\n";          if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";         return ok;     } catch(const qi::expectation_failure<it>& e)     {         std::string frag(e.first, e.last);         std::cerr << e.what() << "'" << frag << "'\n";     }      return false; }  int main() {     std::ifstream ifs("input.txt", std::ios::binary);     ifs.unsetf(std::ios::skipws);     std::istreambuf_iterator<char> f(ifs), l;      bool ok = doparse({ f, l }); } 

output:

parse success data: v:  -1.57 33.809 0.359 -24.012 0.005 21.744   n:  0.0 0.535 0.845 0.833 0.553 0.0  

Comments