c++ - How do I capture the original input into the synthesized output from a spirit grammar? -


i'm working on boost::spirit::qi::grammar , copy portion of original text synthesized output structure of grammar (more specifically, portion matched 1 of components of rule). grammar used sub-grammar more complicated grammar, don't have access original input.

i'm guessing can done through semantic actions or grammar context, can't find example without access original parse().

here's have far:

#include <iostream> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <boost/fusion/include/adapt_struct.hpp>  namespace qi = boost::spirit::qi;  struct {     std::string header;     std::vector<int> ints;     std::string inttext; };  boost_fusion_adapt_struct(     a,     (std::string, header)     (std::vector<int>, ints)     //(std::string, inttext) )  template <typename iterator> struct parser : qi::grammar< iterator, a() > {     parser() : parser::base_type(start)     {         header %= qi::lexeme[ +qi::alpha ];         ints %= qi::lexeme[ qi::int_ % qi::char_(",_") ]; // <---- capture original text matches inttext         start %= header >> ' ' >> ints;     }      qi::rule<iterator, std::string()> header;     qi::rule<iterator, std::vector<int>() > ints;     qi::rule<iterator, a()> start; };  int main() {     output;     std::string input("out 1,2_3");     auto iter = input.begin();     parser<decltype(iter)> p;     bool r = qi::parse(iter, input.end(), p, output);     if( !r || iter != input.end() )     {         std::cout << "did not parse";     }     else     {         // output.inttext "1,2_3"         std::cout << output.header << ": " << output.inttext << " -> [ ";         for( auto & i: output.ints )             std::cout << << ' ';         std::cout << ']' << std::endl;     } } 

something similar asked without using semantic actions:

#include <iostream> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/spirit/repository/include/qi_iter_pos.hpp>  namespace qi = boost::spirit::qi; using boost::spirit::repository::qi::iter_pos;  struct ints_type {    std::vector<int> data;    std::string::const_iterator begin;    std::string::const_iterator end;    };  struct {     std::string header;     ints_type ints; };  boost_fusion_adapt_struct(     ints_type,     (std::string::const_iterator, begin)     (std::vector<int>, data)     (std::string::const_iterator, end) )  boost_fusion_adapt_struct(      a,      (std::string, header)      (ints_type, ints) )  template <typename iterator> struct parser : qi::grammar< iterator, a() > {     parser() : parser::base_type(start)     {         header %= qi::lexeme[ +qi::alpha ];         ints %= qi::lexeme[ iter_pos >> qi::int_ % qi::char_(",_") >> iter_pos ]; // <---- capture original text matches inttext         start %= header >> ' ' >> ints;     }      qi::rule<iterator, std::string()> header;     qi::rule<iterator, ints_type() > ints;     qi::rule<iterator, a()> start; };  int main() {     output;     std::string input("out 1,2_3");     auto iter = input.begin();     parser<decltype(iter)> p;     bool r = qi::parse(iter, input.end(), p, output);     if( !r || iter != input.end() )     {         std::cout << "did not parse";     }     else     {         // output.inttext "1,2_3"         std::cout << output.header << ": " << std::string(output.ints.begin,output.ints.end) << " -> [ ";         for( auto & i: output.ints.data )             std::cout << << ' ';         std::cout << ']' << std::endl;     } } 

using semantic actions:

#include <iostream> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/spirit/repository/include/qi_iter_pos.hpp>  namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; using boost::spirit::repository::qi::iter_pos;  struct ints_type {    std::vector<int> data;    std::string inttext;  };  struct {     std::string header;     ints_type ints;  };  boost_fusion_adapt_struct(     ints_type,     (std::vector<int>, data)     (std::string, inttext) )  boost_fusion_adapt_struct(      a,      (std::string, header)      (ints_type, ints) )  template <typename iterator> struct parser : qi::grammar< iterator, a() > {     parser() : parser::base_type(start)     {         header %= qi::lexeme[ +qi::alpha ];         ints = qi::lexeme[                   (iter_pos >> qi::int_ % qi::char_(",_") >> iter_pos)                      [phx::at_c<0>(qi::_val)=qi::_2,                       phx::at_c<1>(qi::_val)=phx::construct<std::string>(qi::_1,qi::_3)]                 ];          start %= header >> ' ' >> ints;     }      qi::rule<iterator, std::string()> header;     qi::rule<iterator, ints_type() > ints;     qi::rule<iterator, a()> start; };  int main() {     output;     std::string input("out 1,2_3");     auto iter = input.begin();     parser<decltype(iter)> p;     bool r = qi::parse(iter, input.end(), p, output);     if( !r || iter != input.end() )     {         std::cout << "did not parse";     }     else     {         // output.inttext "1,2_3"         std::cout << output.header << ": " << output.ints.inttext << " -> [ ";         for( auto & i: output.ints.data )             std::cout << << ' ';         std::cout << ']' << std::endl;     } } 

Comments

Popular posts from this blog

sublimetext3 - what keyboard shortcut is to comment/uncomment for this script tag in sublime -

java - No use of nillable="0" in SOAP Webservice -

ubuntu - Laravel 5.2 quickstart guide gives Not Found Error -