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
Post a Comment