|
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