Search code examples
c++boost-spirit-karma

Make reordered tuple from vector of tuple with use spirit::karma


#include <tuple>
#include <vector>
#include <string>
#include <iostream>
//-------------------------------------------------------------------------
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
//-------------------------------------------------------------------------
namespace ph = boost::phoenix;
namespace karma = boost::spirit::karma;
typedef std::back_insert_iterator<std::string> Sink;
typedef std::tuple<double,int> Data;
typedef std::vector<Data> Container;
struct Generator : karma::grammar<Sink,Container()>
{
  Generator(void) : Generator::base_type(start,"Generator")
  {
    start = data % karma::eol;
    //data = karma::delimit[???];
    return;
  }
  karma::rule<Sink,Container()> start;
  karma::rule<Sink,Data()> data;
};
//-------------------------------------------------------------------------
int main(int argc,char** argv)
{
  Generator generator;
  Container container;
  container.push_back(Data(3.1415,100500));
  container.push_back(Data(2.7183,9000));
  std::string result;
  Sink sink(result);
  bool b = boost::spirit::karma::generate(sink,generator,container);
  std::cerr << (b == true ? result : std::string("Error!")) << std::endl;
  return 0;
}

in rule data (as example) I need generate int before double and make with it arithmetical operation. How can I get access to elements of synthesized attribute (tuple) in semantic actions of data rule?


Solution

  • The quickest solution I can come up with at this instant is simply:

    data = delimit [ int_ [ _1 = at_c<1>(_val) ] << double_ [ _1 = at_c<0>(_val) ] ];
    

    So, a full sample would look like:

    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <boost/spirit/include/phoenix_operator.hpp>
    
    #include <boost/fusion/adapted.hpp>
    #include <boost/tuple/tuple.hpp>
    //-------------------------------------------------------------------------
    namespace ph = boost::phoenix;
    namespace karma = boost::spirit::karma;
    typedef std::back_insert_iterator<std::string> Sink;
    typedef boost::tuple<double,int> Data;
    typedef std::vector<Data> Container;
    struct Generator : karma::grammar<Sink,Container()>
    {
        Generator(void) : Generator::base_type(start,"Generator")
        {
            using namespace karma;
            using namespace ph;
            data = delimit [ int_ [ _1 = at_c<1>(_val) ] << double_ [ _1 = at_c<0>(_val) ] ];
            start = data % eol;
            return;
        }
        karma::rule<Sink,Container()> start;
        karma::rule<Sink,Data()> data;
    };
    //-------------------------------------------------------------------------
    int main(int argc,char** argv)
    {
        Generator generator;
        Container container;
        container.push_back(Data(3.1415,100500));
        container.push_back(Data(2.7183,9000));
        std::string result;
        Sink sink(result);
        bool b = boost::spirit::karma::generate(sink,generator,container);
        std::cerr << (b == true ? result : std::string("Error!")) << std::endl;
        return 0;
    }
    

    Output:

    100500 3.142
    9000 2.718