
Hi! Though I appreciate simple examples in the docs it is indeed helpful to have examples with fully qualified names. I am having hard times figuring out which versions of "_1", "at_c", etc. are in use. the fusion/phoenix/proto/mpl chaos is hard to keep track of. In summary: using declaratives are nice for toy examples but drive you nuts, once you #include more files and have ADL destroying the idyll of simplicity. Below is a piece of code that nearly compiles. One line has a problem: A semantic action, namely a push_back fails under vc8 and the error message is far from being helpful. So could you please be so nice and give me some hint on how to fix this. (BTW, Joel: "iter+30" directives from the spirit2 examples are assert-catched by the VC8 debugging STL, so I changed that part a little bit to first check the distance and doing iterator arithmetics afterwards. See below.) best regards, Markus ---snip--- #define BOOST_SPIRIT_DEBUG_OUT std::cerr #define BOOST_SPIRIT_DEBUG #include "Enforce.h" #include <boost/tr1/functional.hpp> #include <boost/tr1/tuple.hpp> #include <boost/mpl/assert.hpp> #include <boost/mpl/at.hpp> #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.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_container.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/variant/recursive_variant.hpp> #include <boost/foreach.hpp> #include <boost/preprocessor/repetition.hpp> #include <boost/preprocessor/arithmetic/sub.hpp> #include <boost/preprocessor/punctuation/comma_if.hpp> #include <list> #include <string> #include <vector> #include <iostream> #include <iterator> using namespace boost::spirit; using namespace boost::spirit::qi; using namespace boost::spirit::ascii; using namespace boost::spirit::arg_names; using boost::phoenix::push_back; namespace fusion = boost::fusion; namespace phoenix = boost::phoenix; namespace { //////////////////////////////////////////////////////////////////////////////// // parser traits 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; \ } \ } // int PARSER_TRAITS(int, int_type); // unsigned int PARSER_TRAITS(unsigned int, uint_type); // double PARSER_TRAITS(double, double_type); }; //////////////////////////////////////////////////////////////////////////////// // parser template <typename Iterator, typename Tuple> struct tuple_grammar; template <typename Iterator, typename T1, typename T2> struct tuple_grammar<Iterator, std::tr1::tuple<T1, T2> > : grammar<Iterator, std::list<std::tr1::tuple<T1, T2> >(), space_type> { typename parser_traits::parser<T1>::type p1; typename parser_traits::parser<T2>::type p2; typedef typename std::tr1::tuple<T1, T2> tuple_t; tuple_grammar() : tuple_grammar::base_type(rule_tuple_list) { using phoenix::at_c; using boost::spirit::arg_names::_1; // using boost::spirit::container::push_back; using boost::phoenix::push_back; rule_tuple = '(' >> p1[at_c<0>(_val) = _1] >> ',' >> p2[at_c<1>(_val) = _1] >> ')' ; rule_tuple_list = // COMPILER FALS ON THIS SEMANTIC ACTION - WHY? *(rule_tuple[push_back(ref(_val), _1)]) ; } rule<Iterator, tuple_t(), space_type> rule_tuple; rule<Iterator, std::list<tuple_t>(), space_type> rule_tuple_list; }; //////////////////////////////////////////////////////////////////////////////// // string_to_list_of_tuples template <typename Tuple> struct string_to_list_of_tuples; template <typename T1, typename T2> struct string_to_list_of_tuples<std::tr1::tuple<T1, T2> > { typedef std::tr1::tuple<T1, T2> tuple_t; static std::list<tuple_t> apply(std::string const & s) { std::list<tuple_t> result; typedef tuple_grammar<std::string::const_iterator, tuple_t> tuple_grammar; tuple_grammar tg; std::string::const_iterator iter = s.begin(); std::string::const_iterator end = s.end(); bool r = phrase_parse(iter, end, tg, result, space); if (r && iter == end) { std::cout << "-------------------------\n"; std::cout << "Parsing succeeded\n"; std::cout << "-------------------------\n"; } else { std::size_t dist = std::distance(iter, end); std::string::const_iterator some = dist > 30 ? iter+30 : end; std::string context(iter, some); std::cout << "-------------------------\n"; std::cout << "Parsing failed\n"; std::cout << "stopped at: \"" << context << "...\"\n"; std::cout << "-------------------------\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; } }