|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r61322 - in trunk/boost/spirit/home: karma karma/binary karma/char karma/detail karma/numeric karma/operator karma/stream karma/string qi/detail support
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-16 14:12:26
Author: hkaiser
Date: 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
New Revision: 61322
URL: http://svn.boost.org/trac/boost/changeset/61322
Log:
Spirit: refined attribute extraction customization point (Karma), enabled single element sequences everzwhere a single value is expected (Qi, Karma)
Text files modified:
trunk/boost/spirit/home/karma/binary/binary.hpp | 3
trunk/boost/spirit/home/karma/char/char_generator.hpp | 2
trunk/boost/spirit/home/karma/detail/extract_from.hpp | 95 ++++++++++++++++++++++++++++-----------
trunk/boost/spirit/home/karma/numeric/bool.hpp | 7 +-
trunk/boost/spirit/home/karma/numeric/int.hpp | 7 +-
trunk/boost/spirit/home/karma/numeric/real.hpp | 7 +-
trunk/boost/spirit/home/karma/numeric/uint.hpp | 7 +-
trunk/boost/spirit/home/karma/operator/alternative.hpp | 1
trunk/boost/spirit/home/karma/phoenix_attributes.hpp | 4
trunk/boost/spirit/home/karma/stream/stream.hpp | 11 +++-
trunk/boost/spirit/home/karma/string/lit.hpp | 12 +++-
trunk/boost/spirit/home/qi/detail/assign_to.hpp | 38 ++++++++++++++-
trunk/boost/spirit/home/support/attributes_fwd.hpp | 4
13 files changed, 141 insertions(+), 57 deletions(-)
Modified: trunk/boost/spirit/home/karma/binary/binary.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/binary/binary.hpp (original)
+++ trunk/boost/spirit/home/karma/binary/binary.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -199,7 +199,8 @@
#pragma warning(push)
#pragma warning(disable: 4244)
#endif
- p = traits::extract_from(attr, context);
+ typedef typename karma::detail::integer<bits>::type attribute_type;
+ p = traits::extract_from<attribute_type>(attr, context);
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
Modified: trunk/boost/spirit/home/karma/char/char_generator.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/char/char_generator.hpp (original)
+++ trunk/boost/spirit/home/karma/char/char_generator.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -75,7 +75,7 @@
return false;
Attr ch = Attr();
- if (!this->derived().test(traits::extract_from(attr, context), ch, context))
+ if (!this->derived().test(traits::extract_from<Attr>(attr, context), ch, context))
return false;
return karma::detail::generate_to(sink, ch, char_encoding(), tag()) &&
Modified: trunk/boost/spirit/home/karma/detail/extract_from.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/extract_from.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/extract_from.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -27,89 +27,130 @@
// optimization will easily strip these away.
///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ ///////////////////////////////////////////////////////////////////////
+ // extract first and second element of a fusion sequence
+ template <typename T>
+ struct add_const_ref
+ : add_reference<typename add_const<T>::type>
+ {};
+
+ template <typename T, int N>
+ struct value_at_c
+ : add_const_ref<typename fusion::result_of::value_at_c<T, N>::type>
+ {};
+ }
+
+ // forward declaration only
+ template <typename Exposed, typename Attribute, typename Context>
+ typename spirit::result_of::extract_from<Exposed, Attribute>::type
+ extract_from(Attribute const& attr, Context& ctx);
+
// This is the default case: the plain attribute values
- template <typename Attribute, typename Enable/* = void*/>
+ template <typename Attribute, typename Exposed, typename Enable/*= void*/>
struct extract_from_attribute
{
- typedef Attribute const& type;
+ typedef typename traits::one_element_sequence<Attribute>::type
+ is_one_element_sequence;
+
+ typedef typename mpl::eval_if<
+ is_one_element_sequence
+ , detail::value_at_c<Attribute, 0>
+ , mpl::identity<Attribute const&>
+ >::type type;
template <typename Context>
- static type call(Attribute const& attr, Context&)
+ static type call(Attribute const& attr, Context&, mpl::false_)
{
return attr;
}
+
+ // This handles the case where the attribute is a single element fusion
+ // sequence. We silently extract the only element and treat it as the
+ // attribute to generate output from.
+ template <typename Context>
+ static type call(Attribute const& attr, Context& ctx, mpl::true_)
+ {
+ return extract_from<Exposed>(fusion::at_c<0>(attr), ctx);
+ }
+
+ template <typename Context>
+ static type call(Attribute const& attr, Context& ctx)
+ {
+ return call(attr, ctx, is_one_element_sequence());
+ }
};
// This handles optional attributes.
- template <typename Attribute>
- struct extract_from_attribute<optional<Attribute> >
+ template <typename Attribute, typename Exposed>
+ struct extract_from_attribute<optional<Attribute>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
- static type call(optional<Attribute> const& attr, Context&)
+ static type call(optional<Attribute> const& attr, Context& ctx)
{
- return boost::get<Attribute>(attr);
+ return extract_from<Exposed>(boost::get<Attribute>(attr), ctx);
}
};
- template <typename Attribute>
- struct extract_from_attribute<optional<Attribute const> >
+ template <typename Attribute, typename Exposed>
+ struct extract_from_attribute<optional<Attribute const>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
- static type call(optional<Attribute const> const& attr, Context&)
+ static type call(optional<Attribute const> const& attr, Context& ctx)
{
- return boost::get<Attribute const>(attr);
+ return extract_from<Exposed>(boost::get<Attribute const>(attr), ctx);
}
};
// This handles attributes wrapped inside a boost::ref().
- template <typename Attribute>
- struct extract_from_attribute<reference_wrapper<Attribute> >
+ template <typename Attribute, typename Exposed>
+ struct extract_from_attribute<reference_wrapper<Attribute>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
- static type call(reference_wrapper<Attribute> const& attr, Context&)
+ static type call(reference_wrapper<Attribute> const& attr, Context& ctx)
{
- return attr.get();
+ return extract_from<Exposed>(attr.get(), ctx);
}
};
///////////////////////////////////////////////////////////////////////////
- template <typename Attribute, typename Context>
- typename spirit::result_of::extract_from<Attribute>::type
- extract_from(Attribute const& attr, Context& context)
+ template <typename Exposed, typename Attribute, typename Context>
+ typename spirit::result_of::extract_from<Exposed, Attribute>::type
+ extract_from(Attribute const& attr, Context& ctx)
{
- return extract_from_attribute<Attribute>::call(attr, context);
+ return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
}
- template <typename Context>
+ template <typename Exposed, typename Context>
unused_type extract_from(unused_type, Context&)
{
return unused;
}
-
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace result_of
{
- template <typename Attribute>
+ template <typename Exposed, typename Attribute>
struct extract_from
- : traits::extract_from_attribute<Attribute>
+ : traits::extract_from_attribute<Attribute, Exposed>
{};
- template <>
- struct extract_from<unused_type>
+ template <typename Exposed>
+ struct extract_from<Exposed, unused_type>
{
typedef unused_type type;
};
- template <>
- struct extract_from<unused_type const>
+ template <typename Exposed>
+ struct extract_from<Exposed, unused_type const>
{
typedef unused_type type;
};
Modified: trunk/boost/spirit/home/karma/numeric/bool.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/bool.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/bool.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -144,7 +144,7 @@
return false; // fail if it's an uninitialized optional
return bool_inserter<T, Policies, CharEncoding, Tag>::call(
- sink, traits::extract_from(attr, context), p_) &&
+ sink, traits::extract_from<T>(attr, context), p_) &&
delimit_out(sink, d); // always do post-delimiting
}
@@ -184,7 +184,7 @@
public:
typedef typename Policies::properties properties;
- template <typename Context, typename Unused>
+ template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
@@ -201,8 +201,9 @@
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
+ typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
- bool(n_) != bool(traits::extract_from(attr, context)))
+ bool(n_) != bool(traits::extract_from<attribute_type>(attr, context)))
{
return false;
}
Modified: trunk/boost/spirit/home/karma/numeric/int.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/int.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/int.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -216,7 +216,7 @@
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
- return insert_int(sink, traits::extract_from(attr, context)) &&
+ return insert_int(sink, traits::extract_from<T>(attr, context)) &&
delimit_out(sink, d); // always do post-delimiting
}
@@ -263,7 +263,7 @@
}
public:
- template <typename Context, typename Unused>
+ template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
@@ -287,8 +287,9 @@
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
+ typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
- n_ != traits::extract_from(attr, context))
+ n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
Modified: trunk/boost/spirit/home/karma/numeric/real.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/real.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/real.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -175,7 +175,7 @@
return false; // fail if it's an uninitialized optional
typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
- return inserter_type::call(sink, traits::extract_from(attr, context), p_) &&
+ return inserter_type::call(sink, traits::extract_from<T>(attr, context), p_) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
@@ -214,7 +214,7 @@
{
typedef typename Policies::properties properties;
- template <typename Context, typename Unused>
+ template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
@@ -231,8 +231,9 @@
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
+ typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
- n_ != traits::extract_from(attr, context))
+ n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
Modified: trunk/boost/spirit/home/karma/numeric/uint.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/uint.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/uint.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -250,7 +250,7 @@
return false; // fail if it's an uninitialized optional
return uint_inserter<Radix, CharEncoding, Tag>::
- call(sink, traits::extract_from(attr, context)) &&
+ call(sink, traits::extract_from<T>(attr, context)) &&
delimit_out(sink, d); // always do post-delimiting
}
@@ -286,7 +286,7 @@
: primitive_generator<literal_uint_generator<T, CharEncoding, Tag, Radix
, no_attribute> >
{
- template <typename Context, typename Unused>
+ template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
@@ -310,8 +310,9 @@
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
+ typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
- n_ != traits::extract_from(attr, context))
+ n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
Modified: trunk/boost/spirit/home/karma/operator/alternative.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/alternative.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/alternative.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -12,7 +12,6 @@
#endif
#include <boost/spirit/home/karma/detail/alternative_function.hpp>
-#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
Modified: trunk/boost/spirit/home/karma/phoenix_attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/phoenix_attributes.hpp (original)
+++ trunk/boost/spirit/home/karma/phoenix_attributes.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -94,8 +94,8 @@
// Handle Phoenix actors as attributes, just invoke the function object
// and deal with the result as the attribute.
///////////////////////////////////////////////////////////////////////////
- template <typename Eval>
- struct extract_from_attribute<phoenix::actor<Eval> >
+ template <typename Eval, typename Exposed>
+ struct extract_from_attribute<phoenix::actor<Eval>, Exposed>
{
typedef typename boost::result_of<phoenix::actor<Eval>()>::type type;
Modified: trunk/boost/spirit/home/karma/stream/stream.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/stream/stream.hpp (original)
+++ trunk/boost/spirit/home/karma/stream/stream.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -110,7 +110,7 @@
struct any_stream_generator
: primitive_generator<any_stream_generator<Char, CharEncoding, Tag> >
{
- template <typename Context, typename Unused>
+ template <typename Context, typename Unused = unused_type>
struct attribute
{
typedef spirit::hold_any type;
@@ -132,8 +132,10 @@
return false;
// use existing operator<<()
+ typedef typename attribute<Context>::type attribute_type;
+
boost::iostreams::stream<sink_device> ostr(sink);
- ostr << traits::extract_from(attr, context) << std::flush;
+ ostr << traits::extract_from<attribute_type>(attr, context) << std::flush;
if (ostr.good())
return karma::delimit_out(sink, d); // always do post-delimiting
@@ -163,9 +165,12 @@
return false;
// use existing operator<<()
+ typedef typename attribute<Context>::type attribute_type;
+
boost::iostreams::stream<sink_device> ostr(sink);
ostr.imbue(sink.get_ostream().getloc());
- ostr << traits::extract_from(attr, context) << std::flush;
+ ostr << traits::extract_from<attribute_type>(attr, context)
+ << std::flush;
if (ostr.good())
return karma::delimit_out(sink, d); // always do post-delimiting
Modified: trunk/boost/spirit/home/karma/string/lit.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/string/lit.hpp (original)
+++ trunk/boost/spirit/home/karma/string/lit.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -78,7 +78,7 @@
typedef typename CharEncoding::char_type char_type;
typedef CharEncoding char_encoding;
- template <typename Context, typename Unused>
+ template <typename Context, typename Unused = unused_type>
struct attribute
{
typedef std::basic_string<char_type> type;
@@ -94,9 +94,11 @@
if (!traits::has_optional_value(attr))
return false;
+ typedef typename attribute<Context>::type attribute_type;
return
karma::detail::string_generate(sink
- , traits::extract_from(attr, context), char_encoding(), Tag()) &&
+ , traits::extract_from<attribute_type>(attr, context)
+ , char_encoding(), Tag()) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
@@ -134,7 +136,7 @@
char_type;
typedef std::basic_string<char_type> string_type;
- template <typename Context, typename Unused>
+ template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, string_type>
{};
@@ -156,9 +158,11 @@
return false;
// fail if attribute isn't matched by immediate literal
+ typedef typename attribute<Context>::type attribute_type;
+
using spirit::traits::get_c_string;
if (!detail::string_compare(
- get_c_string(traits::extract_from(attr, context))
+ get_c_string(traits::extract_from<attribute_type>(attr, context))
, get_c_string(str_), char_encoding(), Tag()))
{
return false;
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 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -15,7 +15,7 @@
#include <boost/spirit/home/qi/detail/construct.hpp>
#include <boost/spirit/home/support/unused.hpp>
-#include <boost/spirit/home/support/attributes_fwd.hpp>
+#include <boost/spirit/home/support/attributes.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/phoenix/core/actor.hpp>
#include <boost/ref.hpp>
@@ -87,14 +87,45 @@
}
///////////////////////////////////////////////////////////////////////////
+ template <typename T, typename Attribute>
+ void assign_to(T const& val, Attribute& attr);
+
template <typename Attribute, typename T, typename Enable>
struct assign_to_attribute_from_value
{
+ typedef typename traits::one_element_sequence<Attribute>::type
+ is_one_element_sequence;
+
+ typedef typename mpl::eval_if<
+ is_one_element_sequence
+ , fusion::result_of::at_c<Attribute, 0>
+ , mpl::identity<Attribute&>
+ >::type type;
+
+ template <typename T_>
static void
- call(T const& val, Attribute& attr)
+ 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
+ // attribute to parse the results into.
+ template <typename T_>
+ static void
+ call(T_ const& val, Attribute& attr, mpl::true_)
+ {
+ 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
+ call(T const& val, Attribute& attr)
+ {
+ call(val, attr, is_one_element_sequence());
+ }
};
template <typename Attribute, typename T>
@@ -103,7 +134,7 @@
static void
call(T const& val, reference_wrapper<Attribute> attr)
{
- attr = static_cast<Attribute>(val.get());
+ assign_to(val.get(), attr);
}
};
@@ -128,7 +159,6 @@
assign_to(T const&, unused_type)
{
}
-
}}}
#endif
Modified: trunk/boost/spirit/home/support/attributes_fwd.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes_fwd.hpp (original)
+++ trunk/boost/spirit/home/support/attributes_fwd.hpp 2010-04-16 14:12:24 EDT (Fri, 16 Apr 2010)
@@ -63,7 +63,7 @@
///////////////////////////////////////////////////////////////////////////
// Karma only
- template <typename Attribute, typename Enable = void>
+ template <typename Attribute, typename Exposed, typename Enable = void>
struct extract_from_attribute;
///////////////////////////////////////////////////////////////////////////
@@ -116,7 +116,7 @@
namespace boost { namespace spirit { namespace result_of
{
// forward declaration only
- template <typename Attribute>
+ template <typename Exposed, typename Attribute>
struct extract_from;
template <typename Exposed, typename Transformed, typename Domain>
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