Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r61284 - in trunk: boost/spirit/home/karma/auxiliary boost/spirit/home/karma/nonterminal boost/spirit/home/karma/numeric boost/spirit/home/karma/string boost/spirit/home/qi/auxiliary boost/spirit/home/qi/nonterminal boost/spirit/home/support boost/spirit/repository/home/qi/nonterminal libs/spirit/doc/advanced libs/spirit/example/karma libs/spirit/example/qi libs/spirit/test/karma libs/spirit/test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-14 22:43:25


Author: hkaiser
Date: 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
New Revision: 61284
URL: http://svn.boost.org/trac/boost/changeset/61284

Log:
Spirit: refining the transform_attribute CP
Text files modified:
   trunk/boost/spirit/home/karma/auxiliary/attr_cast.hpp | 3
   trunk/boost/spirit/home/karma/nonterminal/rule.hpp | 20 +++
   trunk/boost/spirit/home/karma/numeric/bool_policies.hpp | 2
   trunk/boost/spirit/home/karma/string/symbols.hpp | 119 ++++++++++++++++++++++++-
   trunk/boost/spirit/home/qi/auxiliary/attr_cast.hpp | 3
   trunk/boost/spirit/home/qi/nonterminal/rule.hpp | 6
   trunk/boost/spirit/home/support/adapt_class_attributes.hpp | 8
   trunk/boost/spirit/home/support/attributes.hpp | 179 ++++++++++++++++++++++++++-------------
   trunk/boost/spirit/home/support/attributes_fwd.hpp | 9 +
   trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp | 6
   trunk/libs/spirit/doc/advanced/customization_points.qbk | 20 +++-
   trunk/libs/spirit/example/karma/reference.cpp | 2
   trunk/libs/spirit/example/qi/reference.cpp | 2
   trunk/libs/spirit/test/karma/attribute.cpp | 4
   trunk/libs/spirit/test/karma/symbols.cpp | 112 ++++++++++++++++++++++++
   trunk/libs/spirit/test/qi/attribute.cpp | 4
   16 files changed, 400 insertions(+), 99 deletions(-)

Modified: trunk/boost/spirit/home/karma/auxiliary/attr_cast.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/auxiliary/attr_cast.hpp (original)
+++ trunk/boost/spirit/home/karma/auxiliary/attr_cast.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -76,7 +76,8 @@
           , Attribute const& attr) const
         {
             typedef traits::transform_attribute<
- Attribute const, transformed_attribute_type> transform;
+ Attribute const, transformed_attribute_type, domain>
+ transform;
 
             return compile<karma::domain>(subject).generate(
                 sink, ctx, d, transform::pre(attr));

Modified: trunk/boost/spirit/home/karma/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/rule.hpp (original)
+++ trunk/boost/spirit/home/karma/nonterminal/rule.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -247,12 +247,18 @@
                 // Create an attribute if none is supplied.
                 typedef traits::make_attribute<attr_type, Attribute>
                     make_attribute;
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, domain>
+ transform;
+
+ typename transform::type attr_ =
+ traits::pre_transform<domain, attr_type>(
+ make_attribute::call(attr));
 
                 // If you are seeing a compilation error here, you are probably
                 // trying to use a rule or a grammar which has inherited
                 // attributes, without passing values for them.
- context_type context(traits::pre_transform<attr_type>(
- make_attribute::call(attr)));
+ context_type context(attr_);
 
                 // If you are seeing a compilation error here stating that the
                 // third parameter can't be converted to a karma::reference
@@ -281,12 +287,18 @@
                 // Create an attribute if none is supplied.
                 typedef traits::make_attribute<attr_type, Attribute>
                     make_attribute;
+ typedef traits::transform_attribute<
+ typename make_attribute::type, attr_type, domain>
+ transform;
+
+ typename transform::type attr_ =
+ traits::pre_transform<domain, attr_type>(
+ make_attribute::call(attr));
 
                 // If you are seeing a compilation error here, you are probably
                 // trying to use a rule or a grammar which has inherited
                 // attributes, passing values of incompatible types for them.
- context_type context(traits::pre_transform<attr_type>(
- make_attribute::call(attr)), params, caller_context);
+ context_type context(attr_, params, caller_context);
 
                 // If you are seeing a compilation error here stating that the
                 // third parameter can't be converted to a karma::reference

Modified: trunk/boost/spirit/home/karma/numeric/bool_policies.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/bool_policies.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/bool_policies.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -28,7 +28,7 @@
     // // we want to spell the names of false as eurt (true backwards)
     // template <typename CharEncoding, typename Tag
     // , typename OutputIterator>
- // static bool generate_flase(OutputIterator& sink, bool)
+ // static bool generate_false(OutputIterator& sink, bool)
     // {
     // return string_inserter<CharEncoding, Tag>::call(sink, "eurt");
     // }

Modified: trunk/boost/spirit/home/karma/string/symbols.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/string/symbols.hpp (original)
+++ trunk/boost/spirit/home/karma/string/symbols.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -30,6 +30,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
 {
+ ///////////////////////////////////////////////////////////////////////////
     template <typename Attribute, typename T>
     struct symbols_lookup
       : mpl::if_<
@@ -40,6 +41,103 @@
     {};
 
     ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ ///////////////////////////////////////////////////////////////////////
+ template <typename CharEncoding, typename Tag>
+ struct generate_encoded
+ {
+ typedef typename
+ proto::terminal<tag::char_code<Tag, CharEncoding> >::type
+ encoding_type;
+
+ template <typename OutputIterator, typename Expr, typename Attribute>
+ static bool call(OutputIterator& sink, Expr const& expr
+ , Attribute const& attr)
+ {
+ encoding_type const encoding = encoding_type();
+ return karma::generate(sink, encoding[expr], attr);
+ }
+ };
+
+ template <>
+ struct generate_encoded<unused_type, unused_type>
+ {
+ template <typename OutputIterator, typename Expr, typename Attribute>
+ static bool call(OutputIterator& sink, Expr const& expr
+ , Attribute const& attr)
+ {
+ return karma::generate(sink, expr, attr);
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // extract first and second element of a fusion sequence
+ template <typename T>
+ struct first
+ {
+ typedef typename
+ mpl::eval_if<fusion::traits::is_sequence<T>
+ , fusion::result_of::value_at_c<T, 0>, mpl::identity<T>
+ >::type type;
+ typedef typename add_reference<
+ typename add_const<type>::type
+ >::type result_type;
+
+ template <typename T_>
+ static result_type
+ call(T_ const& t, mpl::true_)
+ {
+ return fusion::at_c<0>(t);
+ }
+
+ template <typename T_>
+ static result_type
+ call(T_ const& t, mpl::false_)
+ {
+ return t;
+ }
+
+ static result_type
+ call(T const& t)
+ {
+ return call(t, fusion::traits::is_sequence<T>());
+ }
+ };
+
+ template <typename T>
+ struct second
+ {
+ typedef typename
+ mpl::eval_if<fusion::traits::is_sequence<T>
+ , fusion::result_of::value_at_c<T, 1>, mpl::identity<unused_type>
+ >::type type;
+ typedef typename add_reference<
+ typename add_const<type>::type
+ >::type result_type;
+
+ template <typename T_>
+ static result_type
+ call(T_ const& t, mpl::true_)
+ {
+ return fusion::at_c<1>(t);
+ }
+
+ template <typename T_>
+ static result_type
+ call(T_ const& t, mpl::false_)
+ {
+ return unused;
+ }
+
+ static result_type
+ call(T const& t)
+ {
+ return call(t, fusion::traits::is_sequence<T>());
+ }
+ };
+ }
+
     template <
         typename Attribute = char, typename T = unused_type
       , typename Lookup = typename symbols_lookup<Attribute, T>::type
@@ -186,13 +284,15 @@
         bool generate(OutputIterator& sink, Context&, Delimiter const& d
           , Attr const& attr) const
         {
- typename Lookup::iterator it = lookup->find(attr);
+ typename Lookup::iterator it = lookup->find(
+ detail::first<Attr>::call(attr));
             if (it == lookup->end())
                 return false;
 
- return spirit::karma::detail::string_generate(
- sink, (*it).second, CharEncoding(), Tag()) &&
- spirit::karma::delimit_out(sink, d);
+ return karma::detail::generate_encoded<CharEncoding, Tag>::call(
+ sink, (*it).second
+ , detail::second<Attr>::call(attr)) &&
+ karma::delimit_out(sink, d);
         }
 
         template <typename Context>
@@ -425,13 +525,16 @@
         bool generate(OutputIterator& sink, Context&, Delimiter const& d
           , Attr const& attr) const
         {
- typename Lookup::iterator it = lookup->find(attr);
+ typename Lookup::iterator it = lookup->find(
+ detail::first<Attr>::call(attr));
             if (it == lookup->end())
                 return false;
 
- return spirit::karma::detail::string_generate(
- sink, attr, CharEncoding(), Tag()) &&
- spirit::karma::delimit_out(sink, d);
+ return karma::detail::generate_encoded<CharEncoding, Tag>::
+ call(sink
+ , detail::first<Attr>::call(attr)
+ , detail::second<Attr>::call(attr)) &&
+ karma::delimit_out(sink, d);
         }
 
         template <typename Context>

Modified: trunk/boost/spirit/home/qi/auxiliary/attr_cast.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/auxiliary/attr_cast.hpp (original)
+++ trunk/boost/spirit/home/qi/auxiliary/attr_cast.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -87,7 +87,8 @@
             // do down-stream transformation, provides attribute for embedded
             // parser
             typedef traits::transform_attribute<
- exposed_attribute_type, transformed_attribute_type> transform;
+ exposed_attribute_type, transformed_attribute_type, domain>
+ transform;
 
             typename transform::type attr_ = transform::pre(attr);
 

Modified: trunk/boost/spirit/home/qi/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/nonterminal/rule.hpp (original)
+++ trunk/boost/spirit/home/qi/nonterminal/rule.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -246,7 +246,8 @@
                 // do down-stream transformation, provides attribute for
                 // rhs parser
                 typedef traits::transform_attribute<
- typename make_attribute::type, attr_type> transform;
+ typename make_attribute::type, attr_type, domain>
+ transform;
 
                 typename make_attribute::type made_attr = make_attribute::call(attr);
                 typename transform::type attr_ = transform::pre(made_attr);
@@ -291,7 +292,8 @@
                 // do down-stream transformation, provides attribute for
                 // rhs parser
                 typedef traits::transform_attribute<
- typename make_attribute::type, attr_type> transform;
+ typename make_attribute::type, attr_type, domain>
+ transform;
 
                 typename make_attribute::type made_attr = make_attribute::call(attr);
                 typename transform::type attr_ = transform::pre(made_attr);

Modified: trunk/boost/spirit/home/support/adapt_class_attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/adapt_class_attributes.hpp (original)
+++ trunk/boost/spirit/home/support/adapt_class_attributes.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -74,9 +74,9 @@
     {};
 
     ///////////////////////////////////////////////////////////////////////////
- template <typename T, int N, typename Attribute>
+ template <typename T, int N, typename Attribute, typename Domain>
     struct transform_attribute<
- fusion::extension::class_member_proxy<T, N>, Attribute
+ fusion::extension::class_member_proxy<T, N>, Attribute, Domain
       , typename disable_if<
             is_reference<typename fusion::extension::class_member_proxy<T, N>::lvalue>
>::type>
@@ -100,9 +100,9 @@
         }
     };
 
- template <typename T, int N, typename Attribute>
+ template <typename T, int N, typename Attribute, typename Domain>
     struct transform_attribute<
- fusion::extension::class_member_proxy<T, N>, Attribute
+ fusion::extension::class_member_proxy<T, N>, Attribute, Domain
       , typename enable_if<
             is_reference<typename fusion::extension::class_member_proxy<T, N>::lvalue>
>::type>

Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp (original)
+++ trunk/boost/spirit/home/support/attributes.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -17,6 +17,8 @@
 #include <boost/spirit/home/support/attributes_fwd.hpp>
 #include <boost/spirit/home/support/detail/hold_any.hpp>
 #include <boost/spirit/home/support/detail/as_variant.hpp>
+#include <boost/spirit/home/qi/domain.hpp>
+#include <boost/spirit/home/karma/domain.hpp>
 #include <boost/optional/optional.hpp>
 #include <boost/fusion/include/transform.hpp>
 #include <boost/fusion/include/filter_if.hpp>
@@ -49,7 +51,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     ///////////////////////////////////////////////////////////////////////////
- // This file deals with attribute related functions and metafunctions
+ // This file deals with attribute related functions and meta-functions
     // including generalized attribute transformation utilities for Spirit
     // components.
     ///////////////////////////////////////////////////////////////////////////
@@ -100,7 +102,8 @@
     namespace detail
     {
         // A component is compatible to a given Attribute type if the
- // Attribute is the same as the expected type of the component
+ // 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
           : is_convertible<Attribute, Expected>
@@ -197,7 +200,7 @@
     ///////////////////////////////////////////////////////////////////////////
     // attribute_not_unused
     //
- // An mpl metafunction class that determines whether a component's
+ // An mpl meta-function class that determines whether a component's
     // attribute is not unused.
     ///////////////////////////////////////////////////////////////////////////
     template <typename Context, typename Iterator = unused_type>
@@ -552,32 +555,22 @@
         static void fail(Attribute&) {}
     };
 
- template <typename Exposed, typename Transformed, typename Enable/* = void*/>
- struct transform_attribute
- : default_transform_attribute<Exposed, Transformed> {};
-
+ // main specialization for Qi
     template <typename Exposed, typename Transformed>
- struct transform_attribute<Exposed, Transformed,
- typename enable_if<
- mpl::and_<
- mpl::not_<is_const<Exposed> >,
- mpl::not_<is_reference<Exposed> >,
- is_proxy<Transformed>
- >
- >::type>
- : proxy_transform_attribute<Exposed, Transformed> {};
-
- template <typename Exposed, typename Transformed>
- struct transform_attribute<Exposed const, Transformed>
- {
- typedef Transformed type;
- static Transformed pre(Exposed const& val) { return Transformed(val); }
- // Karma only, no post() and no fail() required
- };
+ struct transform_attribute<Exposed, Transformed, qi::domain>
+ : mpl::if_<
+ mpl::and_<
+ mpl::not_<is_const<Exposed> >
+ , mpl::not_<is_reference<Exposed> >
+ , is_proxy<Transformed> >
+ , proxy_transform_attribute<Exposed, Transformed>
+ , default_transform_attribute<Exposed, Transformed>
+ >::type
+ {};
 
     template <typename Exposed, typename Transformed>
- struct transform_attribute<optional<Exposed>, Transformed,
- typename disable_if<is_same<optional<Exposed>, Transformed> >::type>
+ struct transform_attribute<optional<Exposed>, Transformed, qi::domain
+ , typename disable_if<is_same<optional<Exposed>, Transformed> >::type>
     {
         typedef Transformed& type;
         static Transformed& pre(optional<Exposed>& val)
@@ -593,22 +586,14 @@
         }
     };
 
- template <typename Attribute>
- struct transform_attribute<Attribute const, Attribute>
- {
- typedef Attribute const& type;
- static Attribute const& pre(Attribute const& val) { return val; }
- // Karma only, no post() and no fail() required
- };
-
     // reference types need special handling
     template <typename Exposed, typename Transformed>
- struct transform_attribute<Exposed&, Transformed>
- : transform_attribute<Exposed, Transformed>
+ struct transform_attribute<Exposed&, Transformed, qi::domain>
+ : transform_attribute<Exposed, Transformed, qi::domain>
     {};
 
     template <typename Attribute>
- struct transform_attribute<Attribute&, Attribute>
+ struct transform_attribute<Attribute&, Attribute, qi::domain>
     {
         typedef Attribute& type;
         static Attribute& pre(Attribute& val) { return val; }
@@ -616,73 +601,142 @@
         static void fail(Attribute&) {}
     };
 
+ // unused_type needs some special handling as well
+ template <>
+ struct transform_attribute<unused_type, unused_type, qi::domain>
+ {
+ typedef unused_type type;
+ static unused_type pre(unused_type) { return unused; }
+ static void post(unused_type, unused_type) {}
+ static void fail(unused_type) {}
+ };
+
+ template <>
+ struct transform_attribute<unused_type const, unused_type, qi::domain>
+ : transform_attribute<unused_type, unused_type, qi::domain>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<unused_type, Attribute, qi::domain>
+ : transform_attribute<unused_type, unused_type, qi::domain>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<unused_type const, Attribute, qi::domain>
+ : transform_attribute<unused_type, unused_type, qi::domain>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<Attribute, unused_type, qi::domain>
+ : transform_attribute<unused_type, unused_type, qi::domain>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<Attribute const, unused_type, qi::domain>
+ : transform_attribute<unused_type, unused_type, qi::domain>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Exposed, typename Transformed>
+ struct transform_attribute<Exposed, Transformed, karma::domain>
+ {
+ typedef Transformed type;
+ static Transformed pre(Exposed& val) { return Transformed(val); }
+ // Karma only, no post() and no fail() required
+ };
+
+ template <typename Exposed, typename Transformed>
+ struct transform_attribute<Exposed const, Transformed, karma::domain>
+ {
+ typedef Transformed type;
+ static Transformed pre(Exposed const& val) { return Transformed(val); }
+ // Karma only, no post() and no fail() required
+ };
+
     template <typename Attribute>
- struct transform_attribute<Attribute const&, Attribute>
- : transform_attribute<Attribute const, Attribute>
+ struct transform_attribute<Attribute const, Attribute, karma::domain>
+ {
+ typedef Attribute const& type;
+ static Attribute const& pre(Attribute const& val) { return val; }
+ // Karma only, no post() and no fail() required
+ };
+
+ // reference types need special handling
+ template <typename Exposed, typename Transformed>
+ struct transform_attribute<Exposed&, Transformed, karma::domain>
+ : transform_attribute<Exposed, Transformed, karma::domain>
+ {};
+
+ template <typename Exposed, typename Transformed>
+ struct transform_attribute<Exposed const&, Transformed, karma::domain>
+ : transform_attribute<Exposed const, Transformed, karma::domain>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<Attribute const&, Attribute, karma::domain>
+ : transform_attribute<Attribute const, Attribute, karma::domain>
     {};
 
     // unused_type needs some special handling as well
     template <>
- struct transform_attribute<unused_type, unused_type>
+ struct transform_attribute<unused_type, unused_type, karma::domain>
     {
         typedef unused_type type;
         static unused_type pre(unused_type) { return unused; }
- static void post(unused_type, unused_type) {}
- static void fail(unused_type) {}
     };
 
     template <>
- struct transform_attribute<unused_type const, unused_type>
- : transform_attribute<unused_type, unused_type>
+ struct transform_attribute<unused_type const, unused_type, karma::domain>
+ : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     template <typename Attribute>
- struct transform_attribute<unused_type, Attribute>
- : transform_attribute<unused_type, unused_type>
+ struct transform_attribute<unused_type, Attribute, karma::domain>
+ : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     template <typename Attribute>
- struct transform_attribute<unused_type const, Attribute>
- : transform_attribute<unused_type, unused_type>
+ struct transform_attribute<unused_type const, Attribute, karma::domain>
+ : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     template <typename Attribute>
- struct transform_attribute<Attribute, unused_type>
- : transform_attribute<unused_type, unused_type>
+ struct transform_attribute<Attribute, unused_type, karma::domain>
+ : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     template <typename Attribute>
- struct transform_attribute<Attribute const, unused_type>
- : transform_attribute<unused_type, unused_type>
+ struct transform_attribute<Attribute const, unused_type, karma::domain>
+ : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     ///////////////////////////////////////////////////////////////////////////
- template <typename Transformed, typename Exposed>
- typename spirit::result_of::pre_transform<Exposed, Transformed>::type
+ template <typename Domain, typename Transformed, typename Exposed>
+ typename spirit::result_of::pre_transform<Exposed, Transformed, Domain>::type
     pre_transform(Exposed& attr BOOST_PROTO_DISABLE_IF_IS_CONST(Exposed))
     {
- return transform_attribute<Exposed, Transformed>::pre(attr);
+ return transform_attribute<Exposed, Transformed, Domain>::pre(attr);
     }
 
- template <typename Transformed, typename Exposed>
- typename spirit::result_of::pre_transform<Exposed const, Transformed>::type
+ template <typename Domain, typename Transformed, typename Exposed>
+ typename spirit::result_of::pre_transform<Exposed const, Transformed, Domain>::type
     pre_transform(Exposed const& attr)
     {
- return transform_attribute<Exposed const, Transformed>::pre(attr);
+ return transform_attribute<Exposed const, Transformed, Domain>::pre(attr);
     }
 
     ///////////////////////////////////////////////////////////////////////////
     template <typename Exposed, typename Transformed>
     void post_transform(Exposed& dest, Transformed const& attr)
     {
- return transform_attribute<Exposed, Transformed>::post(dest, attr);
+ return transform_attribute<Exposed, Transformed, qi::domain>::post(dest, attr);
     }
 
     ///////////////////////////////////////////////////////////////////////////
     template <typename Exposed, typename Transformed>
     void fail_transform(Exposed& dest, Transformed const&)
     {
- return transform_attribute<Exposed, Transformed>::fail(dest);
+ return transform_attribute<Exposed, Transformed, qi::domain>::fail(dest);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -918,6 +972,7 @@
     {
     }
 
+ ///////////////////////////////////////////////////////////////////////////
     template <typename Out, typename T>
     void print_attribute(Out& out, T const& val);
 
@@ -997,9 +1052,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace result_of
 {
- template <typename Exposed, typename Transformed>
+ template <typename Exposed, typename Transformed, typename Domain>
     struct pre_transform
- : traits::transform_attribute<Exposed, Transformed>
+ : traits::transform_attribute<Exposed, Transformed, Domain>
     {};
 }}}
 

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-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -49,10 +49,12 @@
     // the user is able specify specific transformation rules for any attribute
     // type.
     ///////////////////////////////////////////////////////////////////////////
- template <typename Exposed, typename Transformed, typename Enable = void>
+ template <typename Exposed, typename Transformed, typename Domain
+ , typename Enable = void>
     struct transform_attribute;
 
     ///////////////////////////////////////////////////////////////////////////
+ // Qi only
     template <typename Attribute, typename Iterator, typename Enable = void>
     struct assign_to_attribute_from_iterators;
 
@@ -60,6 +62,7 @@
     struct assign_to_attribute_from_value;
 
     ///////////////////////////////////////////////////////////////////////////
+ // Karma only
     template <typename Attribute, typename Enable = void>
     struct extract_from_attribute;
 
@@ -82,6 +85,7 @@
     struct is_container;
 
     ///////////////////////////////////////////////////////////////////////////
+ // Qi only
     template <typename Container, typename T, typename Enable = void>
     struct push_back_container;
 
@@ -90,6 +94,7 @@
 
     ///////////////////////////////////////////////////////////////////////
     // Determine the iterator type of the given container type
+ // Karma only
     ///////////////////////////////////////////////////////////////////////
     template <typename Container, typename Enable = void>
     struct begin_container;
@@ -114,7 +119,7 @@
     template <typename Attribute>
     struct extract_from;
 
- template <typename Exposed, typename Transformed>
+ template <typename Exposed, typename Transformed, typename Domain>
     struct pre_transform;
 
     template <typename T>

Modified: trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp
==============================================================================
--- trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp (original)
+++ trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -202,7 +202,8 @@
             // do down-stream transformation, provides attribute for
             // rhs parser
             typedef traits::transform_attribute<
- typename make_attribute::type, subrule_attr_type> transform;
+ typename make_attribute::type, subrule_attr_type, domain>
+ transform;
 
             typename make_attribute::type made_attr = make_attribute::call(attr);
             typename transform::type attr_ = transform::pre(made_attr);
@@ -255,7 +256,8 @@
             // do down-stream transformation, provides attribute for
             // rhs parser
             typedef traits::transform_attribute<
- typename make_attribute::type, subrule_attr_type> transform;
+ typename make_attribute::type, subrule_attr_type, domain>
+ transform;
 
             typename make_attribute::type made_attr = make_attribute::call(attr);
             typename transform::type attr_ = transform::pre(made_attr);

Modified: trunk/libs/spirit/doc/advanced/customization_points.qbk
==============================================================================
--- trunk/libs/spirit/doc/advanced/customization_points.qbk (original)
+++ trunk/libs/spirit/doc/advanced/customization_points.qbk 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -217,6 +217,10 @@
 provided attribute to the attribute type expected by the right hand side
 component (for `rule`) or the embedded component (for `attr_cast`).
 
+[note The interface of this customization point has been changed with Boost
+ V1.44. We added the `Domain` template parameter to allow for more fine
+ grained specializations for __qi__ and __karma__.]
+
 [heading Module Headers]
 
     #include <boost/spirit/home/support/attributes.hpp>
@@ -236,7 +240,7 @@
 
 [heading Synopsis]
 
- template <typename Exposed, typename Transformed, typename Enable>
+ template <typename Exposed, typename Transformed, typename Domain, typename Enable>
     struct transform_attribute
     {
         typedef <unspecified> type;
@@ -253,6 +257,9 @@
                              which needs to be transformed.] [none]]
     [[`Transformed`] [The attribute type expected by the component
                              to be provided as the result of the transformation.] [none]]
+ [[`Domain`] [The domain of the sub library the template is
+ instantiated in. Typically this is either `qi::domain`
+ or `karma::domain`.] [none]]
     [[`Enable`] [Helper template parameter usable to selectively
                              enable or disable certain specializations
                              of `transform_attribute` utilizing SFINAE (i.e.
@@ -267,6 +274,9 @@
     [[`Transformed`] [The type, `Transformed` is the type of the attribute
                            as passed along to the right hand side of the `rule`
                            (embedded component of `attr_cast`).]]
+ [[`Domain`] [The domain of the sub library the template is
+ instantiated in. Typically this is either `qi::domain`
+ or `karma::domain`.]]
     [[`exposed`] [An instance of type `Exposed`.]]
     [[`transformed`] [An instance of type `Transformed`.]]
 ]
@@ -275,7 +285,7 @@
 
 [table
     [[Expression] [Semantics]]
- [[`transform_attribute<Exposed, Transformed>::type`]
+ [[`transform_attribute<Exposed, Transformed, Domain>::type`]
                         [Evaluates to the type to be used as the result of the
                          transformation (to be passed to the right hand side of
                          the `rule` or to the embedded component of the
@@ -284,7 +294,7 @@
                          `Transformed&` instead avoiding superfluous object
                          creation.]]
     [[
-``type transform_attribute<Exposed, Transformed>::pre(exposed)``]
+``type transform_attribute<Exposed, Transformed, Domain>::pre(exposed)``]
                         [Do `pre`-transformation before invoking the right hand
                          side component for `rule` (or the embedded component
                          for `attr_cast`). This takes the attribute supplied as by
@@ -293,7 +303,7 @@
                          as exposed by the metafunction `type`). This function
                          will be called in /Qi/ and for /Karma/.]]
     [[
-``void transform_attribute<Exposed, Transformed>::post(exposed, transformed)``]
+``void transform_attribute<Exposed, Transformed, Domain>::post(exposed, transformed)``]
                         [Do `post`-transformation after the invocation of the
                          right hand side component for `rule` (or the embedded
                          component for `attr_cast`). This takes the original
@@ -303,7 +313,7 @@
                          into the supplied attribute instance. This function
                          will be called in /Qi/ only.]]
     [[
-``void transform_attribute<Exposed, Transformed>::fail(exposed)``]
+``void transform_attribute<Exposed, Transformed, Domain>::fail(exposed)``]
                         [Handling failing parse operations of the
                          right hand side component for `rule` (or the embedded
                          component for `attr_cast`). This function

Modified: trunk/libs/spirit/example/karma/reference.cpp
==============================================================================
--- trunk/libs/spirit/example/karma/reference.cpp (original)
+++ trunk/libs/spirit/example/karma/reference.cpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -183,7 +183,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
- struct transform_attribute<int_data const, int>
+ struct transform_attribute<int_data const, int, karma::domain>
     {
         typedef int type;
         static int pre(int_data const& d) { return d.i; }

Modified: trunk/libs/spirit/example/qi/reference.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/reference.cpp (original)
+++ trunk/libs/spirit/example/qi/reference.cpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -281,7 +281,7 @@
     // in this case we just expose the embedded 'int' as the attribute instance
     // to use, allowing to leave the function 'post()' empty
     template <>
- struct transform_attribute<int_data, int>
+ struct transform_attribute<int_data, int, qi::domain>
     {
         typedef int& type;
         static int& pre(int_data& d) { return d.i; }

Modified: trunk/libs/spirit/test/karma/attribute.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/attribute.cpp (original)
+++ trunk/libs/spirit/test/karma/attribute.cpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -49,7 +49,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
- struct transform_attribute<test_int_data1 const, int>
+ struct transform_attribute<test_int_data1 const, int, karma::domain>
     {
         typedef int type;
         static int pre(test_int_data1 const& d) { return d.i; }
@@ -68,7 +68,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
- struct transform_attribute<test_int_data2 const, int>
+ struct transform_attribute<test_int_data2 const, int, karma::domain>
     {
         typedef int const& type;
         static int const& pre(test_int_data2 const& d) { return d.i; }

Modified: trunk/libs/spirit/test/karma/symbols.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/symbols.cpp (original)
+++ trunk/libs/spirit/test/karma/symbols.cpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -12,9 +12,12 @@
 #include <boost/spirit/include/karma_operator.hpp>
 #include <boost/spirit/include/karma_directive.hpp>
 #include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
 
 #include "test.hpp"
 
+namespace fusion = boost::fusion;
+
 int main()
 {
     using spirit_test::test;
@@ -65,6 +68,113 @@
         BOOST_TEST((!test("", sym, 'h')));
     }
 
+ { // advanced
+ using boost::spirit::karma::rule;
+ using boost::spirit::karma::lit;
+
+ typedef spirit_test::output_iterator<char>::type output_iterator_type;
+
+ symbols<char, rule<output_iterator_type> > sym;
+
+ rule<output_iterator_type> r1 = lit("Joel");
+ rule<output_iterator_type> r2 = lit("Hartmut");
+ rule<output_iterator_type> r3 = lit("Tom");
+ rule<output_iterator_type> r4 = lit("Kim");
+
+ sym.add
+ ('j', r1.alias())
+ ('h', r2.alias())
+ ('t', r3.alias())
+ ('k', r4.alias())
+ ;
+
+ boost::mpl::true_ f =
+ boost::mpl::bool_<boost::spirit::traits::is_generator<
+ symbols<char, rule<output_iterator_type> > >::value>();
+
+ // silence stupid compiler warnings
+ // i.e. MSVC warning C4189: 'f' : local variable is initialized but not referenced
+ BOOST_TEST((f.value));
+
+ BOOST_TEST((test("Joel", sym, 'j')));
+ BOOST_TEST((test("Hartmut", sym, 'h')));
+ BOOST_TEST((test("Tom", sym, 't')));
+ BOOST_TEST((test("Kim", sym, 'k')));
+ BOOST_TEST((!test("", sym, 'x')));
+
+ // test copy
+ symbols<char, rule<output_iterator_type> > sym2;
+ sym2 = sym;
+ BOOST_TEST((test("Joel", sym2, 'j')));
+ BOOST_TEST((test("Hartmut", sym2, 'h')));
+ BOOST_TEST((test("Tom", sym2, 't')));
+ BOOST_TEST((test("Kim", sym2, 'k')));
+ BOOST_TEST((!test("", sym2, 'x')));
+
+ // make sure it plays well with other generators
+ BOOST_TEST((test("Joelyo", sym << "yo", 'j')));
+
+ sym.remove
+ ('j')
+ ('h')
+ ;
+
+ BOOST_TEST((!test("", sym, 'j')));
+ BOOST_TEST((!test("", sym, 'h')));
+ }
+
+ { // more advanced
+ using boost::spirit::karma::rule;
+ using boost::spirit::karma::lit;
+ using boost::spirit::karma::string;
+
+ typedef spirit_test::output_iterator<char>::type output_iterator_type;
+
+ symbols<char, rule<output_iterator_type, std::string()> > sym;
+ rule<output_iterator_type, std::string()> r1 = string;
+
+ sym.add
+ ('j', r1.alias())
+ ('h', r1.alias())
+ ('t', r1.alias())
+ ('k', r1.alias())
+ ;
+
+ boost::mpl::true_ f =
+ boost::mpl::bool_<boost::spirit::traits::is_generator<
+ symbols<char, std::string> >::value>();
+
+ // silence stupid compiler warnings
+ // i.e. MSVC warning C4189: 'f' : local variable is initialized but not referenced
+ BOOST_TEST((f.value));
+
+ BOOST_TEST((test("Joel", sym, fusion::make_vector('j', "Joel"))));
+ BOOST_TEST((test("Hartmut", sym, fusion::make_vector('h', "Hartmut"))));
+ BOOST_TEST((test("Tom", sym, fusion::make_vector('t', "Tom"))));
+ BOOST_TEST((test("Kim", sym, fusion::make_vector('k', "Kim"))));
+ BOOST_TEST((!test("", sym, 'x')));
+
+ // test copy
+ symbols<char, rule<output_iterator_type, std::string()> > sym2;
+ sym2 = sym;
+ BOOST_TEST((test("Joel", sym2, fusion::make_vector('j', "Joel"))));
+ BOOST_TEST((test("Hartmut", sym2, fusion::make_vector('h', "Hartmut"))));
+ BOOST_TEST((test("Tom", sym2, fusion::make_vector('t', "Tom"))));
+ BOOST_TEST((test("Kim", sym2, fusion::make_vector('k', "Kim"))));
+ BOOST_TEST((!test("", sym2, 'x')));
+
+ // make sure it plays well with other generators
+ BOOST_TEST((test("Joelyo", sym << "yo", fusion::make_vector('j', "Joel"))));
+
+ sym.remove
+ ('j')
+ ('h')
+ ;
+
+ BOOST_TEST((!test("", sym, 'j')));
+ BOOST_TEST((!test("", sym, 'h')));
+ }
+
     { // basics
         symbols<std::string> sym;
 
@@ -110,7 +220,7 @@
         BOOST_TEST((!test("", sym, "Hartmut")));
     }
 
- { // no-case handling
+ { // lower/upper handling
         using namespace boost::spirit::ascii;
         using boost::spirit::karma::lower;
         using boost::spirit::karma::upper;

Modified: trunk/libs/spirit/test/qi/attribute.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/attribute.cpp (original)
+++ trunk/libs/spirit/test/qi/attribute.cpp 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -54,7 +54,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
- struct transform_attribute<test_int_data1, int>
+ struct transform_attribute<test_int_data1, int, qi::domain>
     {
         typedef int type;
         static int pre(test_int_data1& d) { return d.i; }
@@ -74,7 +74,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
- struct transform_attribute<test_int_data2, int>
+ struct transform_attribute<test_int_data2, int, qi::domain>
     {
         typedef int& type;
         static int& pre(test_int_data2& d) { return d.i; }


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