
[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; } }
participants (1)
-
Markus Werle