|
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