Boost logo

Boost Users :

From: Markus Werle (numerical.simulation_at_[hidden])
Date: 2008-08-25 10:32:08


> [gmane anti-top-poster-complaint-header]

Hi!

[OK, Joel, it's not as trivial as I thought. Show me the way, master]

Below is my first toy implementation of string_to_list_of_tuples for
tr1::tuple. Unfortunately this code only parses the text, but does not store
the data. Any idea how to add the correct semantic actions in a pure and
elegant way?

Markus

---snip---
#define BOOST_SPIRIT_DEBUG_OUT std::cerr
#define BOOST_SPIRIT_DEBUG

// #include "Enforce.h"

#include <iostream>
#include <iterator>

#include <boost/tr1/tuple.hpp>

#include <boost/mpl/assert.hpp>
#include <boost/mpl/at.hpp>

#include <boost/spirit/include/classic_spirit.hpp>

#include <list>
#include <string>

namespace sp = boost::spirit::classic;
namespace fusion = boost::fusion;
namespace mpl = boost::mpl;

namespace
{

struct parser_traits
{
    template <typename T, int Dummy = 0> struct parser;

#define PARSER_TRAITS(TYPE, PARSER_T) \
    template <int Dummy> struct parser<TYPE, Dummy> \
    { \
        typedef PARSER_T type; \
                                                             \
        static inline \
        PARSER_T p() \
        { \
            PARSER_T result; \
            return result; \
        } \
    }

    PARSER_TRAITS(int, sp::int_parser<int>);
    PARSER_TRAITS(unsigned int, sp::uint_parser<unsigned>);

    typedef sp::real_parser
    <double, sp::ureal_parser_policies<double> > real_parser_t;

    PARSER_TRAITS(float, real_parser_t);
    PARSER_TRAITS(double, real_parser_t);

    template <int Dummy> struct parser<std::string, Dummy>
    {
        typedef sp::contiguous
        <sp::confix_parser
         <sp::strlit<const char*>,
          sp::kleene_star
          <sp::anychar_parser>,
          sp::strlit<const char*>,
          sp::unary_parser_category,
          sp::non_nested,
          sp::non_lexeme> > parser_t;

                                                 
        static inline
        parser_t p()
        {
            using namespace phoenix;
            
            parser_t result = sp::lexeme_d[sp::confix_p("\"" ,
(*sp::anychar_p) , "\"")];
            return result;
        }
                                                             
        static inline
        sp::strlit<char const *> comma()
        {
            sp::strlit<char const *> str_p(",");
            return str_p;
        }
    };
};

template <typename Tuple, long I>
struct
rule_generator_helper
{
    typedef typename std::tr1::tuple_element<I, Tuple>::type element_type;
    typedef typename parser_traits::parser<element_type> pt_type;

    typedef typename rule_generator_helper<Tuple, (I-1)>::type element_1_t;

    typedef typename
    sp::sequence<sp::sequence<element_1_t, sp::chlit<char> >, typename
pt_type::type> type;

    static
    type
    apply()
    {
        return
            rule_generator_helper<Tuple, (I-1)>::apply()
>> sp::ch_p(',')
>> pt_type::p()
            ;
    }
};

template <typename Tuple>
struct
rule_generator_helper<Tuple, 0L>
{
    typedef typename std::tr1::tuple_element<0, Tuple>::type element_type;
    typedef typename parser_traits::parser<element_type> pt_type;

    typedef typename pt_type::type type;

    static
    type
    apply()
    {
        return pt_type::p();
    }
};

template <typename Tuple>
struct
rule_generator
{
    typedef std::tr1::tuple_size<Tuple> tuple_size;
    
    BOOST_MPL_ASSERT_RELATION(tuple_size::value, >, 0);

    typedef
    rule_generator_helper<Tuple, (tuple_size::value - 1)> helper_t;

    static
    inline
    typename helper_t::type
    apply()
    {
        return helper_t::apply();
    }
};

template <typename Tuple>
struct
string_to_list_of_tuples
{
    static
    std::list<Tuple>
    apply(std::string const & s)
    {
        std::list<Tuple> result;

        typedef sp::rule<sp::phrase_scanner_t> rule_t;

        rule_t rule_tuple_rep =
            '(' >> rule_generator<Tuple>::apply() >> ')';

        rule_t rule_tuple_list =
            *(rule_tuple_rep)
>> sp::end_p // for trailing whitespace
            ;

        BOOST_SPIRIT_DEBUG_RULE(rule_tuple_rep);
        BOOST_SPIRIT_DEBUG_RULE(rule_tuple_list);

        sp::parse_info<> info;

        try
        {
            info = sp::parse(s.c_str(), rule_tuple_list, sp::space_p);
        }
        catch (std::exception const & e)
        {
            std::cerr << e.what() << std::endl;
        }
        
// ENFORCE(info.full)
// ("Failed to generate a list of tuples from ")
// ("string representation\n'")
// (s)("'\n");
        
        return result;
    }
};

} // namespace

int main()
{
    try
    {
        {
            typedef std::tr1::tuple<int, int> tuple_t;
            std::list<tuple_t> test =
                string_to_list_of_tuples<tuple_t>::apply(" ( 1, 2 ) ( 3, 4)
(5,6)");
            std::copy(test.begin(), test.end(),
                      std::ostream_iterator<tuple_t>(std::cout, "\n"));
        }

        {
            typedef std::tr1::tuple<unsigned int, int, double> tuple_t;
            std::list<tuple_t> test =
                string_to_list_of_tuples<tuple_t>::apply
                (" ( 1, -2 , 5.123) ( 3, 4,7.9)(5,6,8.6789)");
            std::copy(test.begin(), test.end(),
                      std::ostream_iterator<tuple_t>(std::cout, "\n"));
        }
    }
    catch (std::exception const & e)
    {
        std::cerr << e.what() << std::endl;
    }
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net