|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r56386 - in trunk/boost/spirit: home/karma/nonterminal home/qi/nonterminal home/support repository/home/karma/nonterminal repository/home/qi/nonterminal
From: hartmut.kaiser_at_[hidden]
Date: 2009-09-26 12:23:12
Author: hkaiser
Date: 2009-09-26 12:23:11 EDT (Sat, 26 Sep 2009)
New Revision: 56386
URL: http://svn.boost.org/trac/boost/changeset/56386
Log:
Spirit: started to add attribute transformation capabilities
Text files modified:
trunk/boost/spirit/home/karma/nonterminal/rule.hpp | 11 +-
trunk/boost/spirit/home/qi/nonterminal/rule.hpp | 8 +
trunk/boost/spirit/home/support/attributes.hpp | 143 ++++++++++++++++++++++++++++++++++++---
trunk/boost/spirit/repository/home/karma/nonterminal/subrule.hpp | 12 +-
trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp | 12 +-
5 files changed, 155 insertions(+), 31 deletions(-)
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 2009-09-26 12:23:11 EDT (Sat, 26 Sep 2009)
@@ -221,8 +221,8 @@
if (f)
{
// Create an attribute if none is supplied.
- typedef traits::make_attribute<attr_type, Attribute>
- make_attribute;
+ typedef traits::make_transformed_attribute<
+ attr_type, Attribute const> make_attribute;
// If you are seeing a compilation error here, you are probably
// trying to use a rule or a grammar which has inherited
@@ -250,13 +250,14 @@
if (f)
{
// Create an attribute if none is supplied.
- typedef traits::make_attribute<attr_type, Attribute>
- make_attribute;
+ typedef traits::make_transformed_attribute<
+ attr_type, Attribute const> make_attribute;
// 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(make_attribute::call(attr), params, caller_context);
+ context_type context(make_attribute::call(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/qi/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/nonterminal/rule.hpp (original)
+++ trunk/boost/spirit/home/qi/nonterminal/rule.hpp 2009-09-26 12:23:11 EDT (Sat, 26 Sep 2009)
@@ -212,7 +212,9 @@
{
if (f)
{
- typedef traits::make_attribute<attr_type, Attribute> make_attribute;
+ // Create an attribute if none is supplied.
+ typedef traits::make_transformed_attribute<
+ attr_type, Attribute> make_attribute;
typename make_attribute::type attr_ = make_attribute::call(attr);
@@ -241,7 +243,9 @@
{
if (f)
{
- typedef traits::make_attribute<attr_type, Attribute> make_attribute;
+ // Create an attribute if none is supplied.
+ typedef traits::make_transformed_attribute<
+ attr_type, Attribute> make_attribute;
typename make_attribute::type attr_ = make_attribute::call(attr);
Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp (original)
+++ trunk/boost/spirit/home/support/attributes.hpp 2009-09-26 12:23:11 EDT (Sat, 26 Sep 2009)
@@ -303,16 +303,79 @@
};
///////////////////////////////////////////////////////////////////////////
+ // transform_attribute
+ //
+ // Sometimes the user needs to transform the attribute types for certain
+ // attributes. This template can be used as a customization point, where
+ // the user is able specify specific transformation rules for any attribute
+ // type.
+ template <typename Destination, typename Source>
+ struct transform_attribute
+ {
+ static Destination call(Source& val) { return Destination(val); }
+ };
+
+ template <typename Destination, typename Source>
+ struct transform_attribute<Destination, Source const>
+ {
+ static Destination call(Source const& val) { return Destination(val); }
+ };
+
+ // The default is not to do any transformation
+ template <typename Attribute>
+ struct transform_attribute<Attribute, Attribute>
+ {
+ static Attribute& call(Attribute& val) { return val; }
+ };
+
+ template <typename Attribute>
+ struct transform_attribute<Attribute, Attribute const>
+ {
+ static Attribute const& call(Attribute const& val) { return val; }
+ };
+
+ // unused_type needs some special handling
+ template <>
+ struct transform_attribute<unused_type, unused_type>
+ {
+ static unused_type call(unused_type) { return unused; }
+ };
+
+ template <>
+ struct transform_attribute<unused_type, unused_type const>
+ : transform_attribute<unused_type, unused_type>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<unused_type, Attribute>
+ : transform_attribute<unused_type, unused_type>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<unused_type, Attribute const>
+ : transform_attribute<unused_type, unused_type>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<Attribute, unused_type>
+ : transform_attribute<unused_type, unused_type>
+ {};
+
+ template <typename Attribute>
+ struct transform_attribute<Attribute, unused_type const>
+ : transform_attribute<unused_type, unused_type>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
// make_attribute
//
- // All parsers and generators have specific attribute or parameter types.
- // Spirit parsers are passed an attribute and Spirit generators
- // are passed a parameter; these are either references to the expected
- // type, or an unused_type -- to flag that we do not care about the
- // attribute/parameter. 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.
+ // All parsers and generators have specific attribute types.
+ // Spirit parsers and generators are passed an attribute; these are either
+ // references to the expected type, or an unused_type -- to flag that we do
+ // 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.
///////////////////////////////////////////////////////////////////////////
template <typename Attribute, typename ActualAttribute>
struct make_attribute
@@ -353,14 +416,12 @@
template <typename Attribute, typename ActualAttribute>
struct make_attribute<Attribute&, ActualAttribute>
: make_attribute<Attribute, ActualAttribute>
- {
- };
+ {};
template <typename Attribute, typename ActualAttribute>
struct make_attribute<Attribute const&, ActualAttribute>
: make_attribute<Attribute, ActualAttribute>
- {
- };
+ {};
template <typename ActualAttribute>
struct make_attribute<unused_type, ActualAttribute>
@@ -374,6 +435,64 @@
};
///////////////////////////////////////////////////////////////////////////
+ template <typename Attribute, typename ActualAttribute>
+ struct make_transformed_attribute
+ {
+ // We assume that as soon as the source and destination attribute types
+ // are not the same we need to create a new instance of the destination
+ // in order to do the conversion. In this case we can't just pass
+ // through the references anymore (as it's done in the template
+ // make_attribute above).
+ typedef typename remove_const<ActualAttribute>::type
+ non_const_actual_attribute;
+
+ typedef typename
+ mpl::if_<
+ is_same<non_const_actual_attribute, Attribute>
+ , ActualAttribute&
+ , Attribute>::type
+ attribute_type;
+
+ typedef typename
+ mpl::if_<
+ is_same<non_const_actual_attribute, unused_type>
+ , typename remove_const<Attribute>::type
+ , attribute_type>::type
+ type;
+
+ static Attribute call(unused_type)
+ {
+ // synthesize the attribute/parameter
+ return boost::get(value_initialized<Attribute>());
+ }
+
+ template <typename T>
+ static type call(T& value)
+ {
+ // create the proper attribute transformation
+ typedef transform_attribute<Attribute, ActualAttribute> transform;
+
+ // return either the transformed value or pass 'value' through
+ return transform::call(value);
+ }
+ };
+
+ template <typename Attribute, typename ActualAttribute>
+ struct make_transformed_attribute<Attribute&, ActualAttribute>
+ : make_attribute<Attribute, ActualAttribute>
+ {};
+
+ template <typename Attribute, typename ActualAttribute>
+ struct make_transformed_attribute<Attribute const&, ActualAttribute>
+ : make_attribute<Attribute, ActualAttribute>
+ {};
+
+ template <typename ActualAttribute>
+ struct make_transformed_attribute<unused_type, ActualAttribute>
+ : make_attribute<unused_type, ActualAttribute>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
// swap_impl
//
// Swap (with proper handling of unused_types)
Modified: trunk/boost/spirit/repository/home/karma/nonterminal/subrule.hpp
==============================================================================
--- trunk/boost/spirit/repository/home/karma/nonterminal/subrule.hpp (original)
+++ trunk/boost/spirit/repository/home/karma/nonterminal/subrule.hpp 2009-09-26 12:23:11 EDT (Sat, 26 Sep 2009)
@@ -200,8 +200,8 @@
context_type;
// Create an attribute if none is supplied.
- typedef traits::make_attribute<subrule_attr_type, Attribute>
- make_attribute;
+ typedef traits::make_transformed_attribute<
+ subrule_attr_type, Attribute const> make_attribute;
// If you are seeing a compilation error here, you are probably
// trying to use a subrule which has inherited attributes,
@@ -233,14 +233,14 @@
context_type;
// Create an attribute if none is supplied.
- typedef traits::make_attribute<subrule_attr_type, Attribute>
- make_attribute;
+ typedef traits::make_transformed_attribute<
+ subrule_attr_type, Attribute const> make_attribute;
// If you are seeing a compilation error here, you are probably
// trying to use a subrule which has inherited attributes,
// passing values of incompatible types for them.
- context_type context(*this, make_attribute::call(attr)
- , params, caller_context);
+ context_type context(*this, make_attribute::call(attr), params
+ , caller_context);
return def.binder(sink, context, delimiter);
}
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 2009-09-26 12:23:11 EDT (Sat, 26 Sep 2009)
@@ -196,9 +196,9 @@
context_type;
// prepare attribute
- typedef
- traits::make_attribute<subrule_attr_type, Attribute>
- make_attribute;
+ typedef traits::make_transformed_attribute<
+ subrule_attr_type, Attribute> make_attribute;
+
typename make_attribute::type attr_ = make_attribute::call(attr);
// If you are seeing a compilation error here, you are probably
@@ -233,9 +233,9 @@
context_type;
// prepare attribute
- typedef
- traits::make_attribute<subrule_attr_type, Attribute>
- make_attribute;
+ typedef traits::make_transformed_attribute<
+ subrule_attr_type, Attribute> make_attribute;
+
typename make_attribute::type attr_ = make_attribute::call(attr);
// If you are seeing a compilation error here, you are probably
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