c++ - making a vector of shared pointers from Spirit Qi -


this followup question a previous question.

i can parse vectors of strings grammar, cannot seem parse vector of shared pointers strings; i.e. std::vector<std::shared_ptr<std::string> >, , need bit of help.

my compiling header:

#define boost_spirit_use_phoenix_v3 1   #include <boost/spirit/include/qi_core.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <iostream> #include <string>   #include <boost/spirit/include/phoenix_stl.hpp>  #include <boost/phoenix/bind/bind_member_function.hpp> #include <boost/spirit/include/phoenix_fusion.hpp>    // solution lazy make shared comes forum, user sehe. // https://stackoverflow.com/questions/21516201/how-to-create-boost-phoenix-make-shared //    post found using google search terms `phoenix construct shared_ptr` // changed boost::shared_ptr std::shared_ptr namespace {     template <typename t>     struct make_shared_f     {         template <typename... a> struct result         { typedef std::shared_ptr<t> type; };          template <typename... a>         typename result<a...>::type operator()(a&&... a) const {             return std::make_shared<t>(std::forward<a>(a)...);         }     };      template <typename t>     using make_shared_ = boost::phoenix::function<make_shared_f<t> >; }     namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii;   template<typename iterator, typename skipper = ascii::space_type> struct systemparser : qi::grammar<iterator, std::vector<std::shared_ptr<std::string> >(), skipper> {       systemparser() : systemparser::base_type(variable_group_)     {         namespace phx = boost::phoenix;         using qi::_1;         using qi::_val;         using qi::eps;         using qi::lit;           var_counter = 0;          declarative_symbols.add("variable_group",0);          variable_group_ = "variable_group" > genericvargp_ > ';';         genericvargp_ = new_variable_ % ','; //         new_variable_ = unencountered_symbol_ [_val = make_shared_<std::string>() (_1)];         unencountered_symbol_ = valid_variable_name_ - ( encountered_variables | declarative_symbols );         valid_variable_name_ = +qi::alpha >> *(qi::alnum | qi::char_("[]_") );    //      debug(variable_group_); debug(unencountered_symbol_); debug(new_variable_); debug(genericvargp_); //      boost_spirit_debug_nodes((variable_group_) (valid_variable_name_) (unencountered_symbol_) (new_variable_) (genericvargp_))     }       // rule declarations.  these member variables parser.     qi::rule<iterator, std::vector<std::shared_ptr<std::string> >(), skipper > variable_group_;     qi::rule<iterator, std::vector<std::shared_ptr<std::string> >(), skipper > genericvargp_;     qi::rule<iterator, std::shared_ptr<std::string()> >  new_variable_;     qi::rule<iterator, std::string()> unencountered_symbol_;     qi::rule<iterator, std::string()> valid_variable_name_;       unsigned var_counter;     qi::symbols<char,int> encountered_variables;     qi::symbols<char,int> declarative_symbols; }; 

with driver code:

int main(int argc, char** argv) {      std::vector<std::shared_ptr<std::string> > v;     std::string str = "variable_group x, y, z; ";       std::string::const_iterator iter = str.begin();     std::string::const_iterator end = str.end();       systemparser<std::string::const_iterator> s;       bool s = phrase_parse(iter, end, s, boost::spirit::ascii::space, v);      if (s)     {         std::cout << "parse succeeded: " << v.size() << " variables\n";         (auto& s : v)             std::cout << " - '" << s << "'\n";     }     else         std::cout << "parse failed\n";      if (iter!=end)         std::cout << "remaining unparsed: '" << std::string(iter, end) << "'\n";       return 0; } 

the text parsed correctly, resulting vector of length 0, while should of length 3. somehow, std::shared_ptr<string> not pushed onto of vector resulting rule genericvargp_.

i've tried many things, including reading debug information test parse, , placement of %= signs rule definitions, should used rules there semantic action not assign _val unless mistaken. i've played night , day using phx::bind manually push onto of _val, got nowhere. i've further verified make_shared_ provided sehe in answer in fact lazy std::shared_ptr.

as aside, have struggled getting result of unencountered_symbol_ add encountered_variables enforce uniqueness of variable names...

the problem seems propagation of result of new_variable_ rule onto desired vector of shared pointers in genericvargp_ rule.

this declaration

qi::rule<iterator, std::shared_ptr<std::string()> > new_variable_; 

doesn't match desired type:

qi::rule<iterator, std::shared_ptr<std::string>() > new_variable_; 

sadly, in old spiritv2 attribute silently ignored , no attribute propagation done. explains why didn't error out on compile time.

live on coliru

#define boost_spirit_use_phoenix_v3 1 #define boost_spirit_debug 1  #include <boost/spirit/include/qi_core.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <iostream> #include <string>  #include <boost/spirit/include/phoenix_stl.hpp>  #include <boost/phoenix/bind/bind_member_function.hpp> #include <boost/spirit/include/phoenix_fusion.hpp>  // solution lazy make shared comes forum, user sehe. // https://stackoverflow.com/questions/21516201/how-to-create-boost-phoenix-make-shared //    post found using google search terms `phoenix construct shared_ptr` // changed boost::shared_ptr std::shared_ptr namespace {     template <typename t> struct make_shared_f {         template <typename... a> struct result { typedef std::shared_ptr<t> type; };          template <typename... a> typename result<a...>::type operator()(a &&... a) const {             return std::make_shared<t>(std::forward<a>(a)...);         }     };      template <typename t> using make_shared_ = boost::phoenix::function<make_shared_f<t> >; }  namespace qi    = boost::spirit::qi; namespace ascii = boost::spirit::ascii;  template <typename iterator, typename skipper = ascii::space_type> struct systemparser : qi::grammar<iterator, std::vector<std::shared_ptr<std::string> >(), skipper> {      systemparser() : systemparser::base_type(variable_group_) {         namespace phx = boost::phoenix;         using qi::_1;         using qi::_val;         using qi::eps;         using qi::lit;          var_counter = 0;          declarative_symbols.add("variable_group", 0);          variable_group_       = "variable_group" > genericvargp_ > ';';         genericvargp_         = new_variable_ % ',';                                                                                      //         new_variable_         = unencountered_symbol_ [_val = make_shared_<std::string>()(_1)];         unencountered_symbol_ = valid_variable_name_ - (encountered_variables | declarative_symbols);         valid_variable_name_  = +qi::alpha >> *(qi::alnum | qi::char_("[]_"));          boost_spirit_debug_nodes((variable_group_) (valid_variable_name_) (unencountered_symbol_) (new_variable_) (genericvargp_))     }      // rule declarations.  these member variables parser.     qi::rule<iterator, std::vector<std::shared_ptr<std::string> >(), skipper> variable_group_;     qi::rule<iterator, std::vector<std::shared_ptr<std::string> >(), skipper> genericvargp_;     qi::rule<iterator, std::shared_ptr<std::string>() > new_variable_;     qi::rule<iterator, std::string()> unencountered_symbol_;     qi::rule<iterator, std::string()> valid_variable_name_;      unsigned var_counter;     qi::symbols<char, qi::unused_type> encountered_variables;     qi::symbols<char, qi::unused_type> declarative_symbols; };  int main() {     std::vector<std::shared_ptr<std::string> > v;     std::string str = "variable_group x, y, z; ";      std::string::const_iterator iter = str.begin();     std::string::const_iterator end = str.end();      systemparser<std::string::const_iterator> s;      bool s = phrase_parse(iter, end, s, boost::spirit::ascii::space, v);      if (s)     {         std::cout << "parse succeeded: " << v.size() << " variables\n";         (auto& s : v)             std::cout << " - '" << *s << "'\n";     }     else         std::cout << "parse failed\n";      if (iter!=end)         std::cout << "remaining unparsed: '" << std::string(iter, end) << "'\n"; } 

prints

parse succeeded: 3 variables  - 'x'  - 'y'  - 'z' 

as lot of debug information


Comments

Popular posts from this blog

javascript - oscilloscope of speaker input stops rendering after a few seconds -

javascript - gulp-nodemon - nodejs restart after file change - Error: listen EADDRINUSE events.js:85 -

Fatal Python error: Py_Initialize: unable to load the file system codec. ImportError: No module named 'encodings' -