reuse parsed variable with boost karma
Asked Answered
C

1

3

I have a code base which is quite equivalent to the code below. I try to generate a text file with two times the content of a variable. I feel that the answer is in semantic actions and _a and _val but cannot manage to get through even with the documentation.

How will you do to have : "toto" in str and output : toto some stuff toto

i.e how to reuse a parsed variable in karma ?

struct data
 {
  std::string str;
 };

BOOST_FUSION_ADAPT_STRUCT(
                      data,
                      (std::string, str)
                      )

template <typename Iterator>
struct data: karma::grammar<Iterator, data() >
{
    data():data::base_type(start)
    {
        start = karma::string << karma::lit("some stuff") << karma::string; //Second string is in fact the first one 
    }
    karma::rule<Iterator, data()> start;
};

Solution (according to posts below :)

#include <iostream>
#include <string>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/spirit/include/support_iso8859_1.hpp>

namespace ast
{
    struct data
    {
        std::string str;
    };
}

BOOST_FUSION_ADAPT_STRUCT(
                          ast::data,
                          (std::string, str)
                          )

namespace karma = boost::spirit::karma;

namespace parser
{

    template <typename Iterator>
    struct data: karma::grammar<Iterator, ast::data() >
    {
        data():data::base_type(start)
        {
            start =
                karma::string[karma::_1 =  boost::phoenix::at_c<0>(karma::_val)] <<
                karma::lit("some stuff") <<
                karma::string[karma::_1 =  boost::phoenix::at_c<0>(karma::_val)]
                ;
        }
        karma::rule<Iterator, ast::data()> start;
    };
}

main()
{
    ast::data d;
    d.str = "toto";
    std::string generated;
    typedef std::back_insert_iterator<std::string> iterator_type;
    parser::data<iterator_type> d_p;
    iterator_type sink(generated);
    karma::generate(sink, d_p, d);
    std::cout << generated << std::endl;
}
Corrie answered 2/4, 2014 at 13:16 Comment(0)
D
1

This should do the trick:

start = karma::string[karma::_1 = karma::_val] 
    << karma::lit("some stuff") 
    << karma::string[karma::_1 = karma::_val]; 
Dieselelectric answered 2/4, 2014 at 13:31 Comment(4)
start = karma::duplicate[karma::string >> karma::lit("some stuff") >> karma::string]; also seems to work (but it may present more problems if "some stuff" is more complex).Bergstein
Good to see you here @cv_and_he. You're spot on. Saves me the typing xDUnderdeveloped
The first solution does not compile on my computer with boost 1.47 since it is complaining about operator= in self.hpp. However the first comment did the trick I wanted :)Corrie
Ok, this is because karma::string expects a std::string and you have an adapted struct, sorry I missed that. To make this work one could use boost::phoenix::at_c<0>(karma::_val).Dieselelectric

© 2022 - 2024 — McMap. All rights reserved.