Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r69020 - in trunk/boost/spirit/home: qi/detail qi/directive support
From: joel_at_[hidden]
Date: 2011-02-18 21:13:04


Author: djowel
Date: 2011-02-18 21:13:03 EST (Fri, 18 Feb 2011)
New Revision: 69020
URL: http://svn.boost.org/trac/boost/changeset/69020

Log:
Allow attribute compatibility on alternatives
Text files modified:
   trunk/boost/spirit/home/qi/detail/alternative_function.hpp | 72 +++++++++++++++++++++++++++++++++++++--
   trunk/boost/spirit/home/qi/detail/assign_to.hpp | 62 ++++++++++++++++++++++++----------
   trunk/boost/spirit/home/qi/detail/construct.hpp | 56 +++++++++++++++---------------
   trunk/boost/spirit/home/qi/directive/as.hpp | 21 +++++++++--
   trunk/boost/spirit/home/support/attributes.hpp | 67 +++++++++++++++++++++++++------------
   5 files changed, 201 insertions(+), 77 deletions(-)

Modified: trunk/boost/spirit/home/qi/detail/alternative_function.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/alternative_function.hpp (original)
+++ trunk/boost/spirit/home/qi/detail/alternative_function.hpp 2011-02-18 21:13:03 EST (Fri, 18 Feb 2011)
@@ -20,6 +20,29 @@
 
 namespace boost { namespace spirit { namespace qi { namespace detail
 {
+ template <typename Variant, typename Expected>
+ struct find_substitute
+ {
+ // Get the typr from the variant that can be a substitute for Expected.
+ // If none is found, just return Expected
+
+ typedef Variant variant_type;
+ typedef typename variant_type::types types;
+ typedef typename mpl::end<types>::type end;
+
+ typedef typename
+ mpl::find_if<types, traits::is_substitute<mpl::_1, Expected> >::type
+ iter;
+
+ typedef typename
+ mpl::eval_if<
+ is_same<iter, end>,
+ mpl::identity<Expected>,
+ mpl::deref<iter>
+ >::type
+ type;
+ };
+
     template <typename Iterator, typename Context, typename Skipper,
         typename Attribute>
     struct alternative_function
@@ -40,10 +63,10 @@
         }
 
         template <typename Component>
- bool call(Component const& component, mpl::false_) const
+ bool call_optional_or_variant(Component const& component, mpl::true_) const
         {
- // if Attribute is a variant or optional, then create an
- // attribute for the Component with its expected type.
+ // if Attribute is an optional, then create an attribute for
+ // the Component with its expected type.
             typename traits::attribute_of<Component, Context, Iterator>::type val;
             if (component.parse(first, last, context, skipper, val))
             {
@@ -54,13 +77,52 @@
         }
 
         template <typename Component>
+ bool call_optional_or_variant(Component const& component, mpl::false_) const
+ {
+#ifndef BOOST_SPIRIT_ALTERNATIVES_ALLOW_ATTR_COMPAT
+ // if Attribute is a variant, then create an attribute for
+ // the Component with its expected type.
+ typename traits::attribute_of<Component, Context, Iterator>::type val;
+ if (component.parse(first, last, context, skipper, val))
+ {
+ traits::assign_to(val, attr);
+ return true;
+ }
+ return false;
+#else
+ // if Attribute is a variant, then search the variant types for a
+ // suitable substitute type.
+
+ typename
+ find_substitute<Attribute,
+ typename traits::attribute_of<Component, Context, Iterator>::type
+ >::type
+ val;
+
+ if (component.parse(first, last, context, skipper, val))
+ {
+ traits::assign_to(val, attr);
+ return true;
+ }
+ return false;
+#endif
+ }
+
+ template <typename Component>
+ bool call(Component const& component, mpl::false_) const
+ {
+ return call_optional_or_variant(
+ component, spirit::traits::not_is_variant<Attribute, qi::domain>());
+ }
+
+ template <typename Component>
         bool operator()(Component const& component) const
         {
             // return true if the parser succeeds
- return call(component,
+ return call(component,
                 mpl::and_<
                     spirit::traits::not_is_variant<Attribute, qi::domain>,
- spirit::traits::not_is_optional<Attribute, qi::domain>
+ spirit::traits::not_is_optional<Attribute, qi::domain>
>());
         }
 

Modified: trunk/boost/spirit/home/qi/detail/assign_to.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/assign_to.hpp (original)
+++ trunk/boost/spirit/home/qi/detail/assign_to.hpp 2011-02-18 21:13:03 EST (Fri, 18 Feb 2011)
@@ -18,6 +18,7 @@
 #include <boost/spirit/home/qi/detail/attributes.hpp>
 #include <boost/spirit/home/support/container.hpp>
 #include <boost/spirit/home/phoenix/core/actor.hpp>
+#include <boost/fusion/include/assign.hpp>
 #include <boost/ref.hpp>
 #include <boost/range/iterator_range.hpp>
 
@@ -31,7 +32,7 @@
     template <typename Attribute, typename Iterator, typename Enable>
     struct assign_to_attribute_from_iterators
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, Attribute& attr)
         {
             if (traits::is_empty(attr))
@@ -47,7 +48,7 @@
     struct assign_to_attribute_from_iterators<
         reference_wrapper<Attribute>, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last
           , reference_wrapper<Attribute> attr)
         {
@@ -64,7 +65,7 @@
     struct assign_to_attribute_from_iterators<
         iterator_range<Iterator>, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last
           , iterator_range<Iterator>& attr)
         {
@@ -93,7 +94,7 @@
     template <typename Attribute, typename T, typename Enable>
     struct assign_to_attribute_from_value
     {
- typedef typename traits::one_element_sequence<Attribute>::type
+ typedef typename traits::one_element_sequence<Attribute>::type
             is_one_element_sequence;
 
         typedef typename mpl::eval_if<
@@ -103,25 +104,25 @@
>::type type;
 
         template <typename T_>
- static void
+ static void
         call(T_ const& val, Attribute& attr, mpl::false_)
         {
             attr = static_cast<Attribute>(val);
         }
 
         // This handles the case where the attribute is a single element fusion
- // sequence. We silently assign to the only element and treat it as the
+ // sequence. We silently assign to the only element and treat it as the
         // attribute to parse the results into.
         template <typename T_>
- static void
+ static void
         call(T_ const& val, Attribute& attr, mpl::true_)
         {
- typedef typename fusion::result_of::value_at_c<Attribute, 0>::type
+ typedef typename fusion::result_of::value_at_c<Attribute, 0>::type
                 element_type;
             fusion::at_c<0>(attr) = static_cast<element_type>(val);
         }
 
- static void
+ static void
         call(T const& val, Attribute& attr)
         {
             call(val, attr, is_one_element_sequence());
@@ -131,7 +132,7 @@
     template <typename Attribute>
     struct assign_to_attribute_from_value<Attribute, Attribute>
     {
- static void
+ static void
         call(Attribute const& val, Attribute& attr)
         {
             attr = val;
@@ -141,7 +142,7 @@
     template <typename Attribute, typename T>
     struct assign_to_attribute_from_value<reference_wrapper<Attribute>, T>
     {
- static void
+ static void
         call(T const& val, reference_wrapper<Attribute> attr)
         {
             assign_to(val.get(), attr);
@@ -151,12 +152,37 @@
     template <typename Attribute>
     struct assign_to_attribute_from_value<boost::optional<Attribute>, unused_type>
     {
- static void
+ static void
         call(unused_type, boost::optional<Attribute> const&)
         {
         }
     };
 
+ namespace detail
+ {
+ template <typename A, typename B>
+ struct is_same_size_sequence
+ : mpl::bool_<fusion::result_of::size<A>::value
+ == fusion::result_of::size<B>::value>
+ {};
+ }
+
+ template <typename Attribute, typename T>
+ struct assign_to_attribute_from_value<Attribute, T,
+ mpl::and_<
+ fusion::traits::is_sequence<Attribute>,
+ fusion::traits::is_sequence<T>,
+ detail::is_same_size_sequence<Attribute, T>
+ >
+ >
+ {
+ static void
+ call(T const& val, Attribute& attr)
+ {
+ fusion::assign(val, attr);
+ }
+ };
+
     ///////////////////////////////////////////////////////////////////////////
     template <typename Attribute, typename T, typename Enable>
     struct assign_to_container_from_value
@@ -172,14 +198,14 @@
         template <typename T_>
         static void call(T_ const& val, Attribute& attr, mpl::true_, mpl::false_)
         {
- typedef typename traits::container_iterator<T_ const>::type
+ typedef typename traits::container_iterator<T_ const>::type
                 iterator_type;
             iterator_type end = traits::end(val);
             for (iterator_type i = traits::begin(val); i != end; traits::next(i))
                 traits::push_back(attr, traits::deref(i));
         }
 
- // T is a string
+ // T is a string
         template <typename Iterator>
         static void append_to_string(Attribute& attr, Iterator begin, Iterator end)
         {
@@ -223,7 +249,7 @@
     template <typename Attribute, typename T>
     struct assign_to_container_from_value<reference_wrapper<Attribute>, T>
     {
- static void
+ static void
         call(T const& val, reference_wrapper<Attribute> attr)
         {
             assign_to(val.get(), attr);
@@ -233,7 +259,7 @@
     template <typename Attribute>
     struct assign_to_container_from_value<boost::optional<Attribute>, unused_type>
     {
- static void
+ static void
         call(unused_type, boost::optional<Attribute> const&)
         {
         }
@@ -250,7 +276,7 @@
             assign_to_attribute_from_value<Attribute, T>::call(val, attr);
         }
 
- // overload for containers (but not for variants or optionals
+ // overload for containers (but not for variants or optionals
         // holding containers)
         template <typename T, typename Attribute>
         inline void
@@ -267,7 +293,7 @@
         typedef typename mpl::and_<
             traits::is_container<Attribute>
           , traits::not_is_variant<Attribute>
- , traits::not_is_optional<Attribute>
+ , traits::not_is_optional<Attribute>
>::type is_not_wrapped_container;
 
         detail::assign_to(val, attr, is_not_wrapped_container());

Modified: trunk/boost/spirit/home/qi/detail/construct.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/construct.hpp (original)
+++ trunk/boost/spirit/home/qi/detail/construct.hpp 2011-02-18 21:13:03 EST (Fri, 18 Feb 2011)
@@ -20,13 +20,13 @@
 namespace boost { namespace spirit { namespace traits
 {
     ///////////////////////////////////////////////////////////////////////////
- // We provide overloads for the assign_to_attribute_from_iterators
+ // We provide overloads for the assign_to_attribute_from_iterators
     // customization point for all built in types
     ///////////////////////////////////////////////////////////////////////////
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<char, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, char& attr)
         {
             attr = *first;
@@ -36,7 +36,7 @@
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<signed char, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, signed char& attr)
         {
             attr = *first;
@@ -46,7 +46,7 @@
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<unsigned char, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, unsigned char& attr)
         {
             attr = *first;
@@ -57,7 +57,7 @@
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<wchar_t, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, wchar_t& attr)
         {
             attr = *first;
@@ -69,7 +69,7 @@
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<unsigned short, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, unsigned short& attr)
         {
             attr = *first;
@@ -80,64 +80,64 @@
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<bool, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, bool& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, bool_, attr);
+ qi::parse(first_, last, bool_type(), attr);
         }
     };
 
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<short, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, short& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, short_, attr);
+ qi::parse(first_, last, short_type(), attr);
         }
     };
 
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<int, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, int& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, int_, attr);
+ qi::parse(first_, last, int_type(), attr);
         }
     };
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<unsigned int, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, unsigned int& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, uint_, attr);
+ qi::parse(first_, last, uint_type(), attr);
         }
     };
 
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<long, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, long& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, long_, attr);
+ qi::parse(first_, last, long_type(), attr);
         }
     };
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<unsigned long, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, unsigned long& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, ulong_, attr);
+ qi::parse(first_, last, ulong_type(), attr);
         }
     };
 
@@ -145,21 +145,21 @@
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<long_long_type, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, long_long_type& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, long_long, attr);
+ qi::parse(first_, last, long_long_type(), attr);
         }
     };
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<ulong_long_type, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, ulong_long_type& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, ulong_long, attr);
+ qi::parse(first_, last, ulong_long_type(), attr);
         }
     };
 #endif
@@ -167,33 +167,33 @@
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<float, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, float& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, float_, attr);
+ qi::parse(first_, last, float_type(), attr);
         }
     };
 
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<double, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, double& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, double_, attr);
+ qi::parse(first_, last, double_type(), attr);
         }
     };
 
     template <typename Iterator>
     struct assign_to_attribute_from_iterators<long double, Iterator>
     {
- static void
+ static void
         call(Iterator const& first, Iterator const& last, long double& attr)
         {
             Iterator first_ = first;
- qi::parse(first_, last, long_double, attr);
+ qi::parse(first_, last, long_double_type(), attr);
         }
     };
 

Modified: trunk/boost/spirit/home/qi/directive/as.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/directive/as.hpp (original)
+++ trunk/boost/spirit/home/qi/directive/as.hpp 2011-02-18 21:13:03 EST (Fri, 18 Feb 2011)
@@ -34,10 +34,10 @@
     struct as
       : stateful_tag_type<T, tag::as>
     {
- BOOST_SPIRIT_ASSERT_MSG(
- (traits::is_container<T>::type::value),
- error_type_must_be_a_container,
- (T));
+ //~ BOOST_SPIRIT_ASSERT_MSG(
+ //~ (traits::is_container<T>::type::value),
+ //~ error_type_must_be_a_container,
+ //~ (T));
     };
 }}}
 
@@ -101,6 +101,19 @@
             return false;
         }
 
+ template <typename Iterator, typename Context, typename Skipper>
+ bool parse(Iterator& first, Iterator const& last
+ , Context& context, Skipper const& skipper, T& attr) const
+ {
+ Iterator i = first;
+ if (subject.parse(i, last, context, skipper, attr))
+ {
+ first = i;
+ return true;
+ }
+ return false;
+ }
+
         template <typename Context>
         info what(Context& context) const
         {

Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp (original)
+++ trunk/boost/spirit/home/support/attributes.hpp 2011-02-18 21:13:03 EST (Fri, 18 Feb 2011)
@@ -27,6 +27,7 @@
 #include <boost/fusion/include/is_sequence.hpp>
 #include <boost/fusion/include/for_each.hpp>
 #include <boost/fusion/include/is_view.hpp>
+#include <boost/fusion/include/mpl.hpp>
 #include <boost/foreach.hpp>
 #include <boost/utility/value_init.hpp>
 #include <boost/type_traits/is_same.hpp>
@@ -39,6 +40,7 @@
 #include <boost/mpl/distance.hpp>
 #include <boost/mpl/or.hpp>
 #include <boost/mpl/has_xxx.hpp>
+#include <boost/mpl/equal.hpp>
 #include <boost/proto/proto_fwd.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/variant.hpp>
@@ -56,6 +58,25 @@
     // components.
     ///////////////////////////////////////////////////////////////////////////
 
+ // Find out if T is a substitute for Expected attribute
+ template <typename T, typename Expected, typename Enable = void>
+ struct is_substitute : is_same<T, Expected> {};
+
+ template <typename T, typename Expected>
+ struct is_substitute<optional<T>, optional<Expected> >
+ : is_substitute<T, Expected> {};
+
+ template <typename T, typename Expected>
+ struct is_substitute<T, Expected,
+ typename enable_if<
+ mpl::and_<
+ fusion::traits::is_sequence<T>,
+ fusion::traits::is_sequence<Expected>,
+ mpl::equal<T, Expected, is_substitute<mpl::_1, mpl::_2> >
+ >
+ >::type>
+ : mpl::true_ {};
+
     template <typename T, typename Enable/* = void*/>
     struct is_proxy : mpl::false_ {};
 
@@ -102,7 +123,7 @@
     namespace detail
     {
         // A component is compatible to a given Attribute type if the
- // Attribute is the same as the expected type of the component or if
+ // Attribute is the same as the expected type of the component or if
         // it is convertible to the expected type.
         template <typename Expected, typename Attribute>
         struct attribute_is_compatible
@@ -162,7 +183,7 @@
             mpl::eval_if<type, mpl::deref<iter>, mpl::identity<unused_type> >::type
         compatible_type;
 
- // return whether the given type is compatible with the Expected type
+ // return whether the given type is compatible with the Expected type
         static bool is_compatible(int which)
         {
             return which == distance::value;
@@ -437,38 +458,38 @@
 
     ///////////////////////////////////////////////////////////////////////////
     // sequence_attribute_transform
- //
+ //
     // This transform is invoked for every attribute in a sequence allowing
- // to modify the attribute type exposed by a component to the enclosing
+ // to modify the attribute type exposed by a component to the enclosing
     // sequence component. By default no transformation is performed.
- ///////////////////////////////////////////////////////////////////////////
- template <typename Attribute, typename Domain>
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename Domain>
     struct sequence_attribute_transform
       : mpl::identity<Attribute>
     {};
 
     ///////////////////////////////////////////////////////////////////////////
     // permutation_attribute_transform
- //
+ //
     // This transform is invoked for every attribute in a sequence allowing
- // to modify the attribute type exposed by a component to the enclosing
- // permutation component. By default a build_optional transformation is
+ // to modify the attribute type exposed by a component to the enclosing
+ // permutation component. By default a build_optional transformation is
     // performed.
- ///////////////////////////////////////////////////////////////////////////
- template <typename Attribute, typename Domain>
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename Domain>
     struct permutation_attribute_transform
       : traits::build_optional<Attribute>
     {};
 
     ///////////////////////////////////////////////////////////////////////////
     // sequential_or_attribute_transform
- //
+ //
     // This transform is invoked for every attribute in a sequential_or allowing
- // to modify the attribute type exposed by a component to the enclosing
- // sequential_or component. By default a build_optional transformation is
+ // to modify the attribute type exposed by a component to the enclosing
+ // sequential_or component. By default a build_optional transformation is
     // performed.
- ///////////////////////////////////////////////////////////////////////////
- template <typename Attribute, typename Domain>
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename Domain>
     struct sequential_or_attribute_transform
       : traits::build_optional<Attribute>
     {};
@@ -613,12 +634,12 @@
 
     ///////////////////////////////////////////////////////////////////////////
     // alternative_attribute_transform
- //
+ //
     // This transform is invoked for every attribute in an alternative allowing
- // to modify the attribute type exposed by a component to the enclosing
+ // to modify the attribute type exposed by a component to the enclosing
     // alternative component. By default no transformation is performed.
- ///////////////////////////////////////////////////////////////////////////
- template <typename Attribute, typename Domain>
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename Domain>
     struct alternative_attribute_transform
       : mpl::identity<Attribute>
     {};
@@ -709,7 +730,9 @@
     // not care about the attribute. For semantic actions, however, we need to
     // have a real value to pass to the semantic action. If the client did not
     // provide one, we will have to synthesize the value. This class takes care
- // of that.
+ // of that. *Note that this behavior has changed. From Boost 1.47, semantic
+ // actions always take in the passed attribute as-is if the PP constant:
+ // BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT is defined.
     ///////////////////////////////////////////////////////////////////////////
     template <typename Attribute, typename ActualAttribute>
     struct make_attribute
@@ -1012,7 +1035,7 @@
             {
                 bool first = true;
                 typename container_iterator<T_ const>::type iend = traits::end(val);
- for (typename container_iterator<T_ const>::type i = traits::begin(val);
+ for (typename container_iterator<T_ const>::type i = traits::begin(val);
                      !traits::compare(i, iend); traits::next(i))
                 {
                     if (!first)


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