Boost logo

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