Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r69495 - in trunk: boost/spirit/home/karma/detail libs/spirit/test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2011-03-02 18:37:53


Author: hkaiser
Date: 2011-03-02 18:37:52 EST (Wed, 02 Mar 2011)
New Revision: 69495
URL: http://svn.boost.org/trac/boost/changeset/69495

Log:
Spirit: added handling of variants to the new attribute handling
Text files modified:
   trunk/boost/spirit/home/karma/detail/pass_container.hpp | 79 ++++++++++++++++++++++++++-------------
   trunk/libs/spirit/test/qi/pass_container.cpp | 34 +++++++++++++++++
   2 files changed, 86 insertions(+), 27 deletions(-)

Modified: trunk/boost/spirit/home/karma/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/pass_container.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/pass_container.hpp 2011-03-02 18:37:52 EST (Wed, 02 Mar 2011)
@@ -24,6 +24,7 @@
 #include <boost/preprocessor/cat.hpp>
 #include <boost/preprocessor/repetition/repeat.hpp>
 #include <boost/range/iterator_range.hpp>
+#include <boost/fusion/include/deduce_sequence.hpp>
 
 namespace boost { namespace spirit { namespace karma { namespace detail
 {
@@ -31,29 +32,30 @@
     // is an STL container and that its value_type is convertible
     // to the RHS.
 
+ template <typename LHS, typename RHSAttribute>
+ struct has_same_elements;
+
     template <typename RHS, typename LHSAttribute
       , bool IsContainer = traits::is_container<LHSAttribute>::value
       , bool IsSequence = fusion::traits::is_sequence<LHSAttribute>::value>
- struct has_same_elements : mpl::false_ {};
+ struct has_same_elements_base
+ : mpl::or_<
+ is_convertible<RHS, LHSAttribute>
+ , traits::is_hold_any<LHSAttribute>
+ > {};
 
     template <typename RHS, typename LHSAttribute>
- struct has_same_elements<RHS, LHSAttribute, true, false>
+ struct has_same_elements_base<RHS, LHSAttribute, true, false>
       : mpl::or_<
             is_convertible<RHS, typename LHSAttribute::value_type>
           , traits::is_hold_any<typename LHSAttribute::value_type>
> {};
 
- template <typename RHS, typename T>
- struct has_same_elements<RHS, boost::optional<T>, false, false>
- : has_same_elements<RHS, T> {};
-
- template <typename RHS, typename T>
- struct has_same_elements<RHS, boost::optional<T>, true, false>
- : has_same_elements<RHS, T> {};
-
- template <typename RHS, typename T>
- struct has_same_elements<RHS, boost::optional<T>, false, true>
- : has_same_elements<RHS, T> {};
+ template <typename T>
+ struct has_same_elements_base<T, T, false, false> : mpl::true_ {};
+
+ template <typename T>
+ struct has_same_elements_base<T, T, false, true> : mpl::true_ {};
 
 #define BOOST_SPIRIT_IS_CONVERTIBLE(z, N, data) \
         has_same_elements<RHS, BOOST_PP_CAT(T, N)>::value || \
@@ -62,27 +64,59 @@
     // Note: variants are treated as containers if one of the held types is a
     // container (see support/container.hpp).
     template <typename RHS, BOOST_VARIANT_ENUM_PARAMS(typename T)>
- struct has_same_elements<
+ struct has_same_elements_base<
             RHS, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, true, false>
       : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
           , BOOST_SPIRIT_IS_CONVERTIBLE, _) false> {};
 
 #undef BOOST_SPIRIT_IS_CONVERTIBLE
 
+ template <typename RHS, typename LHSAttribute>
+ struct not_has_same_elements
+ : mpl::not_<has_same_elements<
+ RHS, typename remove_reference<LHSAttribute>::type> >
+ {};
+
     // Specialization for fusion sequences, in this case we check whether the
     // lhs attribute is convertible to the types in the sequence.
- // We return false if the rhs attribute itself is a fusion sequence.
- template <typename RHS, typename LHSAttribute>
- struct has_same_elements<RHS, LHSAttribute, false, true>
+ //
+ // We return false if the rhs attribute itself is a fusion sequence, which
+ // is compatible with the LHS sequence (we want to pass through this
+ // attribute without it being split apart).
+ template <typename RHS, typename LHSAttribute
+ , bool IsSequence = fusion::traits::is_sequence<RHS>::value>
+ struct has_same_elements_fusion_sequences
     {
         typedef typename mpl::find_if<
- LHSAttribute, mpl::not_<is_convertible<RHS, mpl::_1> >
+ LHSAttribute, not_has_same_elements<RHS, mpl::_1>
>::type iter;
         typedef typename mpl::end<LHSAttribute>::type end;
 
         typedef typename is_same<iter, end>::type type;
     };
 
+ template <typename RHS, typename LHS>
+ struct has_same_elements_fusion_sequences<RHS, LHS, true>
+ {
+ typedef typename fusion::traits::deduce_sequence<RHS>::type rhs;
+ typedef typename fusion::traits::deduce_sequence<LHS>::type lhs;
+
+ typedef typename mpl::not_<is_same<rhs, lhs> >::type type;
+ };
+
+ template <typename RHS, typename LHSAttribute>
+ struct has_same_elements_base<RHS, LHSAttribute, false, true>
+ : has_same_elements_fusion_sequences<RHS, LHSAttribute>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename RHS, typename LHSAttribute>
+ struct has_same_elements : has_same_elements_base<RHS, LHSAttribute> {};
+
+ template <typename RHS, typename LHSAttribute>
+ struct has_same_elements<RHS, optional<LHSAttribute> >
+ : has_same_elements_base<RHS, LHSAttribute> {};
+
     ///////////////////////////////////////////////////////////////////////////
     // This function handles the case where the attribute (Attr) given
     // to the sequence is an STL container. This is a wrapper around F.
@@ -119,11 +153,6 @@
                 return false;
             }
 
-// // in non-strict mode increment iterator if the underlying
-// // generator failed
-// if (!Strict::value && !is_at_end())
-// traits::next(iter);
-
             // either no elements available any more or generation failed
             return true;
         }
@@ -147,10 +176,6 @@
             typedef typename traits::attribute_of<
                 Component, context_type>::type attribute_type;
 
-// typedef mpl::and_<
-// traits::is_container<attribute_type>
-// , is_convertible<Attr, attribute_type> > predicate;
-
             typedef mpl::and_<
                 traits::is_container<attribute_type>
               , traits::handles_container<Component, Attr, context_type>

Modified: trunk/libs/spirit/test/qi/pass_container.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/pass_container.cpp (original)
+++ trunk/libs/spirit/test/qi/pass_container.cpp 2011-03-02 18:37:52 EST (Wed, 02 Mar 2011)
@@ -286,6 +286,40 @@
             s == "abc1abc2");
     }
 
+ {
+ using boost::spirit::qi::alpha;
+ using boost::spirit::qi::digit;
+
+ std::vector<char> v1;
+ BOOST_TEST(test_attr("ab1cd2", *(alpha >> alpha | +digit), v1) &&
+ compare(v1, "ab1cd2"));
+ v1.clear();
+ BOOST_TEST(test_attr("ab1cd2", *(alpha >> alpha | digit), v1) &&
+ compare(v1, "ab1cd2"));
+
+ std::string s1;
+ BOOST_TEST(test_attr("ab1cd2", *(alpha >> alpha | +digit), s1) &&
+ s1 == "ab1cd2");
+ s1.clear();
+ BOOST_TEST(test_attr("ab1cd2", *(alpha >> alpha | digit), s1) &&
+ s1 == "ab1cd2");
+
+ std::vector<std::vector<char> > v2;
+ BOOST_TEST(test_attr("ab1cd123", *(alpha >> alpha | +digit), v2) &&
+ v2.size() == 4 &&
+ compare(v2[0], "ab") &&
+ compare(v2[1], "1") &&
+ compare(v2[2], "cd") &&
+ compare(v2[3], "123"));
+
+ std::vector<std::string> v3;
+ BOOST_TEST(test_attr("ab1cd123", *(alpha >> alpha | +digit), v3) &&
+ v3.size() == 4 &&
+ v3[0] == "ab" &&
+ v3[1] == "1" &&
+ v3[2] == "cd" &&
+ v3[3] == "123");
+ }
     return boost::report_errors();
 }
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk