Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r67472 - in trunk: boost/spirit/home/karma/detail boost/spirit/home/karma/directive boost/spirit/home/karma/operator boost/spirit/home/qi/directive boost/spirit/home/qi/operator boost/spirit/home/support boost/spirit/home/support/utree boost/spirit/home/support/utree/detail libs/spirit/test/karma libs/spirit/test/qi libs/spirit/test/support
From: hartmut.kaiser_at_[hidden]
Date: 2010-12-27 18:45:58


Author: hkaiser
Date: 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
New Revision: 67472
URL: http://svn.boost.org/trac/boost/changeset/67472

Log:
Spirit: utree modifications, mostly
Text files modified:
   trunk/boost/spirit/home/karma/detail/as.hpp | 16 +-
   trunk/boost/spirit/home/karma/directive/as.hpp | 6
   trunk/boost/spirit/home/karma/operator/sequence.hpp | 18 ++++
   trunk/boost/spirit/home/qi/directive/repeat.hpp | 3
   trunk/boost/spirit/home/qi/operator/kleene.hpp | 3
   trunk/boost/spirit/home/qi/operator/list.hpp | 3
   trunk/boost/spirit/home/qi/operator/plus.hpp | 3
   trunk/boost/spirit/home/qi/operator/sequence_base.hpp | 3
   trunk/boost/spirit/home/support/attributes_fwd.hpp | 12 ++
   trunk/boost/spirit/home/support/container.hpp | 24 +++++
   trunk/boost/spirit/home/support/utree/detail/utree_detail2.hpp | 41 +++------
   trunk/boost/spirit/home/support/utree/operators.hpp | 12 +-
   trunk/boost/spirit/home/support/utree/utree.hpp | 43 ++++++---
   trunk/boost/spirit/home/support/utree/utree_traits.hpp | 168 ++++++++++++++++++++++++++-------------
   trunk/libs/spirit/test/karma/utree.cpp | 49 ++++++----
   trunk/libs/spirit/test/qi/utree.cpp | 84 +++++++++++++++++--
   trunk/libs/spirit/test/support/utree_test.cpp | 4
   17 files changed, 337 insertions(+), 155 deletions(-)

Modified: trunk/boost/spirit/home/karma/detail/as.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/as.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/as.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -24,7 +24,7 @@
 
     // This is the default case: the plain attribute values
     template <typename T, typename Attribute, typename Enable/*= void*/>
- struct attribute_as_xxx
+ struct attribute_as
     {
         typedef Attribute const& type;
 
@@ -41,10 +41,10 @@
 
     ///////////////////////////////////////////////////////////////////////////
     template <typename T, typename Attribute>
- inline typename spirit::result_of::attribute_as_xxx<T, Attribute>::type
+ inline typename spirit::result_of::attribute_as<T, Attribute>::type
     as(Attribute const& attr)
     {
- return attribute_as_xxx<T, Attribute>::call(attr);
+ return attribute_as<T, Attribute>::call(attr);
     }
 
     template <typename T>
@@ -57,7 +57,7 @@
     template <typename T, typename Attribute>
     inline bool valid_as(Attribute const& attr)
     {
- return attribute_as_xxx<T, Attribute>::is_valid(attr);
+ return attribute_as<T, Attribute>::is_valid(attr);
     }
 
     template <typename T>
@@ -71,18 +71,18 @@
 namespace boost { namespace spirit { namespace result_of
 {
     template <typename T, typename Attribute>
- struct attribute_as_xxx
- : traits::attribute_as_xxx<T, Attribute>
+ struct attribute_as
+ : traits::attribute_as<T, Attribute>
     {};
 
     template <typename T>
- struct attribute_as_xxx<T, unused_type>
+ struct attribute_as<T, unused_type>
     {
         typedef unused_type type;
     };
 
     template <typename T>
- struct attribute_as_xxx<T, unused_type const>
+ struct attribute_as<T, unused_type const>
     {
         typedef unused_type type;
     };

Modified: trunk/boost/spirit/home/karma/directive/as.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/as.hpp (original)
+++ trunk/boost/spirit/home/karma/directive/as.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -86,9 +86,9 @@
         {
             if (!traits::valid_as<T>(attr))
                 return false;
- else
- return subject.generate(sink, ctx, d, traits::as<T>(attr)) &&
- karma::delimit_out(sink, d); // always do post-delimiting
+
+ return subject.generate(sink, ctx, d, traits::as<T>(attr)) &&
+ karma::delimit_out(sink, d); // always do post-delimiting
         }
 
         template <typename Context>

Modified: trunk/boost/spirit/home/karma/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/sequence.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/sequence.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -149,6 +149,9 @@
             indirect_iterator(Iterator& iter)
               : iter_(&iter)
             {}
+ indirect_iterator(indirect_iterator const& iter)
+ : iter_(iter.iter_)
+ {}
 
         private:
             friend class boost::iterator_core_access;
@@ -178,6 +181,12 @@
             typedef indirect_iterator<Iterator> type;
         };
 
+ template <typename Iterator>
+ struct make_indirect_iterator<indirect_iterator<Iterator> >
+ {
+ typedef indirect_iterator<Iterator> type;
+ };
+
         template <>
         struct make_indirect_iterator<unused_type const*>
         {
@@ -361,6 +370,15 @@
     struct make_composite<proto::tag::shift_left, Elements, Modifiers>
       : detail::make_sequence<Elements, detail::get_stricttag<Modifiers>::value>
     {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Helper template allowing to get the required container type for a rule
+ // attribute, which is part of a sequence.
+ template <typename Iterator>
+ struct make_sequence_iterator_range
+ {
+ typedef iterator_range<detail::indirect_iterator<Iterator> > type;
+ };
 }}}
 
 namespace boost { namespace spirit { namespace traits

Modified: trunk/boost/spirit/home/qi/directive/repeat.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/directive/repeat.hpp (original)
+++ trunk/boost/spirit/home/qi/directive/repeat.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -218,6 +218,9 @@
             value_type val = value_type();
             typename LoopIter::type i = iter.start();
 
+ // ensure the attribute is actually a container type
+ traits::make_container(attr);
+
             // parse the minimum required
             Iterator save = first;
             if (!iter.got_min(i) &&

Modified: trunk/boost/spirit/home/qi/operator/kleene.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/kleene.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/kleene.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -68,6 +68,9 @@
                 value_type;
             value_type val = value_type();
 
+ // ensure the attribute is actually a container type
+ traits::make_container(attr);
+
             // Repeat while subject parses ok
             Iterator save = first;
             while (subject.parse(save, last, context, skipper, val) &&

Modified: trunk/boost/spirit/home/qi/operator/list.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/list.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/list.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -66,6 +66,9 @@
                 value_type;
             value_type val = value_type();
 
+ // ensure the attribute is actually a container type
+ traits::make_container(attr);
+
             Iterator save = first;
             if (!left.parse(save, last, context, skipper, val) ||
                 !traits::push_back(attr, val))

Modified: trunk/boost/spirit/home/qi/operator/plus.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/plus.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/plus.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -64,6 +64,9 @@
                 value_type;
             value_type val = value_type();
 
+ // ensure the attribute is actually a container type
+ traits::make_container(attr);
+
             Iterator save = first;
             if (!subject.parse(save, last, context, skipper, val) ||
                 !traits::push_back(attr, val))

Modified: trunk/boost/spirit/home/qi/operator/sequence_base.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/operator/sequence_base.hpp (original)
+++ trunk/boost/spirit/home/qi/operator/sequence_base.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -97,6 +97,9 @@
           , Context& context, Skipper const& skipper
           , Attribute& attr_, mpl::true_) const
         {
+ // ensure the attribute is actually a container type
+ traits::make_container(attr_);
+
             Iterator iter = first;
             // return false if *any* of the parsers fail
             if (fusion::any(elements

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-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -28,7 +28,7 @@
     struct extract_from;
 
     template <typename T, typename Attribute>
- struct attribute_as_xxx;
+ struct attribute_as;
 
     template <typename Exposed, typename Transformed, typename Domain>
     struct pre_transform;
@@ -128,10 +128,10 @@
     ///////////////////////////////////////////////////////////////////////////
     // Karma only
     template <typename T, typename Attribute, typename Enable = void>
- struct attribute_as_xxx;
+ struct attribute_as;
 
     template <typename T, typename Attribute>
- typename spirit::result_of::attribute_as_xxx<T, Attribute>::type
+ typename spirit::result_of::attribute_as<T, Attribute>::type
     as(Attribute const& attr);
     
     template <typename T, typename Attribute>
@@ -143,6 +143,9 @@
     template <typename T, typename Enable = void>
     struct variant_which;
 
+ template <typename T>
+ int which(T const& v);
+
     ///////////////////////////////////////////////////////////////////////////
     // Determine, whether T is a variant like type
     ///////////////////////////////////////////////////////////////////////////
@@ -180,6 +183,9 @@
     template <typename Container, typename Enable = void>
     struct is_empty_container;
 
+ template <typename Container, typename Enable = void>
+ struct make_container_attribute;
+
     ///////////////////////////////////////////////////////////////////////
     // Determine the iterator type of the given container type
     // Karma only

Modified: trunk/boost/spirit/home/support/container.hpp
==============================================================================
--- trunk/boost/spirit/home/support/container.hpp (original)
+++ trunk/boost/spirit/home/support/container.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -349,13 +349,33 @@
         return is_empty_container<Container>::call(c);
     }
 
- template <typename T>
- bool is_empty(unused_type)
+ inline bool is_empty(unused_type)
     {
         return true;
     }
 
     ///////////////////////////////////////////////////////////////////////////
+ // Ensure the attribute is actually a container type
+ template <typename Container, typename Enable/* = void*/>
+ struct make_container_attribute
+ {
+ static void call(Container& c)
+ {
+ // for static types this function does nothing
+ }
+ };
+
+ template <typename T>
+ void make_container(T& t)
+ {
+ make_container_attribute<T>::call(t);
+ }
+
+ inline void make_container(unused_type)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
     template <typename Container, typename Enable/* = void*/>
     struct begin_container
     {

Modified: trunk/boost/spirit/home/support/utree/detail/utree_detail2.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/detail/utree_detail2.hpp (original)
+++ trunk/boost/spirit/home/support/utree/detail/utree_detail2.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -459,8 +459,8 @@
                     boost::throw_exception(bad_type_exception());
                     break;
 
- case type::uninitialized_type:
- return f(utree::uninitialized);
+ case type::invalid_type:
+ return f(utree::invalid);
 
                 case type::nil_type:
                     return f(utree::nil);
@@ -522,8 +522,8 @@
                     boost::throw_exception(bad_type_exception());
                     break;
 
- case type::uninitialized_type:
- return visit_impl::apply(y, detail::bind(f, utree::uninitialized));
+ case type::invalid_type:
+ return visit_impl::apply(y, detail::bind(f, utree::invalid));
 
                 case type::nil_type:
                     return visit_impl::apply(y, detail::bind(f, utree::nil));
@@ -620,10 +620,10 @@
         return new stored_function<F>(*this);
     }
 
- inline utree::utree(utree::uninitialized_type)
+ inline utree::utree(utree::invalid_type)
     {
         s.initialize();
- set_type(type::uninitialized_type);
+ set_type(type::invalid_type);
     }
 
     inline utree::utree(utree::nil_type)
@@ -631,13 +631,7 @@
         s.initialize();
         set_type(type::nil_type);
     }
-
- inline utree::utree(utree::list_type)
- {
- s.initialize();
- ensure_list_type();
- }
-
+
     inline utree::utree(bool b_)
     {
         s.initialize();
@@ -730,7 +724,7 @@
     inline utree::utree(boost::iterator_range<Iter> r)
     {
         s.initialize();
- set_type(type::uninitialized_type);
+
         assign(r.begin(), r.end());
     }
 
@@ -786,13 +780,6 @@
         return *this;
     }
 
- inline utree& utree::operator=(list_type)
- {
- free();
- ensure_list_type();
- return *this;
- }
-
     inline utree& utree::operator=(bool b_)
     {
         free();
@@ -1028,6 +1015,8 @@
             return p->assign(first, last);
 
         clear();
+ set_type(type::list_type);
+
         while (first != last)
         {
             push_back(*first);
@@ -1040,9 +1029,9 @@
         if (get_type() == type::reference_type)
             return p->clear();
 
- // clear will always make this an uninitialized type
+ // clear will always make this an invalid type
         free();
- set_type(type::uninitialized_type);
+ set_type(type::invalid_type);
     }
 
     inline void utree::pop_front()
@@ -1175,7 +1164,7 @@
         if (t == type::list_type)
             return l.size == 0;
 
- return t == type::nil_type || t == type::uninitialized_type;
+ return t == type::nil_type || t == type::invalid_type;
     }
 
     inline std::size_t utree::size() const
@@ -1297,7 +1286,7 @@
     inline void utree::ensure_list_type()
     {
         type::info t = get_type();
- if (t == type::uninitialized_type || t == type::nil_type)
+ if (t == type::invalid_type)
         {
             set_type(type::list_type);
             l.default_construct();
@@ -1337,7 +1326,7 @@
             default:
                 boost::throw_exception(bad_type_exception());
                 break;
- case type::uninitialized_type:
+ case type::invalid_type:
             case type::nil_type:
                 break;
             case type::bool_type:

Modified: trunk/boost/spirit/home/support/utree/operators.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/operators.hpp (original)
+++ trunk/boost/spirit/home/support/utree/operators.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -51,7 +51,7 @@
     std::ostream& operator<<(std::ostream& out, utree const& x);
     std::istream& operator>>(std::istream& in, utree& x);
 
- std::ostream& operator<<(std::ostream& out, utree::uninitialized_type const& x);
+ std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x);
     std::ostream& operator<<(std::ostream& out, utree::nil_type const& x);
 
     // Logical operators
@@ -116,7 +116,7 @@
             return static_cast<Base const&>(a) == static_cast<Base const&>(b);
         }
 
- bool operator()(utree::uninitialized_type, utree::uninitialized_type) const
+ bool operator()(utree::invalid_type, utree::invalid_type) const
         {
             return true;
         }
@@ -172,7 +172,7 @@
             return static_cast<Base const&>(a) < static_cast<Base const&>(b);
         }
 
- bool operator()(utree::uninitialized_type, utree::uninitialized_type) const
+ bool operator()(utree::invalid_type, utree::invalid_type) const
         {
             boost::throw_exception(bad_type_exception());
             return false; // no less than comparison for nil
@@ -204,9 +204,9 @@
         std::ostream& out;
         utree_print(std::ostream& out) : out(out) {}
 
- void operator()(utree::uninitialized_type) const
+ void operator()(utree::invalid_type) const
         {
- out << "<uninitialized> ";
+ out << "<invalid> ";
         }
 
         void operator()(utree::nil_type) const
@@ -493,7 +493,7 @@
         return out;
     }
 
- inline std::ostream& operator<<(std::ostream& out, utree::uninitialized_type const& x)
+ inline std::ostream& operator<<(std::ostream& out, utree::invalid_type const& x)
     {
         return out;
     }

Modified: trunk/boost/spirit/home/support/utree/utree.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/utree.hpp (original)
+++ trunk/boost/spirit/home/support/utree/utree.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -62,7 +62,7 @@
     {
         enum info
         {
- uninitialized_type, // the utree has not been initialized (it's
+ invalid_type, // the utree has not been initialized (it's
                                 // default constructed)
             nil_type, // nil is the sentinel (empty) utree type.
             list_type, // A doubly linked list of utrees.
@@ -249,9 +249,9 @@
     class utree {
     public:
         ///////////////////////////////////////////////////////////////////////
- // The uninitialized type
- struct uninitialized_type {};
- static uninitialized_type const uninitialized;
+ // The invalid type
+ struct invalid_type {};
+ static invalid_type const invalid;
 
         ///////////////////////////////////////////////////////////////////////
         // The nil type
@@ -261,7 +261,7 @@
         ///////////////////////////////////////////////////////////////////////
         // The list type, this can be used to initialize an utree to hold an
         // empty list
- struct list_type {};
+ struct list_type;
         static list_type const list;
 
         //[utree_container_types
@@ -294,21 +294,16 @@
            are non-explicit on purpose, allowing to use an utree instance as
            the attribute to almost any Qi parser.
         */
- // This constructs an `uninitialized_type` node. When used in places
+ // This constructs an `invalid_type` node. When used in places
         // where a boost::optional is expected (i.e. as an attribute for the
         // optional component), this represents the 'empty' state.
- utree(uninitialized_type = uninitialized);
+ utree(invalid_type = invalid);
 
         // This initializes a `nil_type` node, which represents a valid,
- // 'initialized empty' utree (different from uninitialized_type!).
+ // 'initialized empty' utree (different from invalid_type!).
         utree(nil_type);
         reference operator=(nil_type);
 
- // This initializes a `list_type` node, which represents an empty
- // but valid utree list.
- utree(list_type);
- reference operator=(list_type);
-
         // This initializes a `boolean_type` node, which can hold 'true' or
         // 'false' only.
         utree(bool);
@@ -466,6 +461,7 @@
         reference operator[](size_type);
         const_reference operator[](size_type) const;
 
+ // This clears the utree instance and resets its type to 'invalid_type'
         void clear();
 
         void swap(utree&);
@@ -496,6 +492,9 @@
         utree eval(scope const&) const;
 
     //<-
+ protected:
+ void ensure_list_type();
+
     private:
         typedef utree_type type;
 
@@ -509,7 +508,6 @@
 
         type::info get_type() const;
         void set_type(type::info);
- void ensure_list_type();
         void free();
         void copy(const_reference);
 
@@ -529,11 +527,24 @@
     };
     //]
 
+ struct utree::list_type : utree
+ {
+ using utree::operator=;
+
+ list_type() : utree() { ensure_list_type(); }
+
+ template <typename T0>
+ list_type(T0 t0) : utree(t0) {}
+
+ template <typename T0, typename T1>
+ list_type(T0 t0, T1 t1) : utree(t0, t1) {}
+ };
+
     ///////////////////////////////////////////////////////////////////////////
     // predefined instances for singular types
- utree::uninitialized_type const utree::uninitialized = {};
+ utree::invalid_type const utree::invalid = {};
     utree::nil_type const utree::nil = {};
- utree::list_type const utree::list = {};
+ utree::list_type const utree::list = utree::list_type();
 
     ///////////////////////////////////////////////////////////////////////////
     //[utree_scope

Modified: trunk/boost/spirit/home/support/utree/utree_traits.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/utree_traits.hpp (original)
+++ trunk/boost/spirit/home/support/utree/utree_traits.hpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -41,6 +41,14 @@
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace traits
 {
+ // this specialization tells Spirit how to extract the type of the value
+ // stored in the given utree node
+ template <>
+ struct variant_which<utree>
+ {
+ static int call(utree const& u) { return u.which(); }
+ };
+
     ///////////////////////////////////////////////////////////////////////////
     // this specialization lets Spirit know that typed basic_strings
     // are strings
@@ -154,7 +162,7 @@
                 iterator_type;
 
             // make sure the attribute is a list, at least an empty one
- if (attr.which() != utree_type::list_type)
+ if (traits::which(attr) != utree_type::list_type)
                 attr = utree::list;
 
             iterator_type end = traits::end(val);
@@ -176,41 +184,62 @@
     {
         static void call(utree const& val, utree& attr)
         {
- if (val.which() != utree_type::list_type)
+ if (traits::which(val) != utree_type::list_type)
                 attr = val;
             else {
                 typedef utree::const_iterator iterator_type;
 
                 // make sure the attribute is a list, at least an empty one
- if (attr.which() != utree_type::list_type)
+ if (traits::which(attr) != utree_type::list_type)
                     attr = utree::list;
 
- iterator_type end = val.end();
- for (iterator_type i = val.begin(); i != end; ++i)
- attr.push_back(*i);
+ iterator_type end = traits::end(val);
+ for (iterator_type i = traits::begin(val); i != end; traits::next(i))
+ push_back(attr, traits::deref(i));
             }
         }
     };
 
     ///////////////////////////////////////////////////////////////////////////
     //
+ template <typename Attribute>
+ struct transform_attribute<utree::list_type, Attribute, qi::domain>
+ {
+ typedef Attribute type;
+
+ static Attribute pre(utree::list_type&) { return Attribute(); }
+
+ static void post(utree::list_type& attr, Attribute const& val)
+ {
+ push_back(attr, val);
+ }
+
+ static void fail(utree::list_type&) {}
+ };
+
+ template <typename Attribute>
+ struct transform_attribute<utree::list_type&, Attribute, qi::domain>
+ : transform_attribute<utree::list_type, Attribute, qi::domain>
+ {};
+
     template <>
- struct transform_attribute<utree, utree, qi::domain>
+ struct transform_attribute<utree, utree::list_type, qi::domain>
     {
- typedef utree& type;
+ typedef utree::list_type type;
 
- static utree& pre(utree& val) { return val; }
+ static utree::list_type pre(utree&) { return utree::list_type(); }
 
- // If the rhs' attribute is already a list, push it back into the
- // rule's attribute, otherwise wrap it into a list and push that back.
- // This ensures that the rule always exposes an utree list node.
- static void post(utree& attr, utree const& val)
+ static void post(utree& attr, utree::list_type const& val)
         {
- if (val.which() != utree_type::list_type) {
- utree ut (utree::list);
- ut.push_back(val);
- attr.swap(ut);
- }
+ typedef utree::list_type::const_iterator iterator_type;
+
+ // make sure the attribute is a list, at least an empty one
+ if (traits::which(attr) != utree_type::list_type)
+ attr = utree::list;
+
+ iterator_type end = traits::end(val);
+ for (iterator_type i = traits::begin(val); i != end; traits::next(i))
+ attr.push_back(traits::deref(i));
         }
 
         // fail() will be called by Qi rule's if the rhs failed parsing
@@ -218,8 +247,8 @@
     };
 
     template <>
- struct transform_attribute<utree&, utree, qi::domain>
- : transform_attribute<utree, utree, qi::domain>
+ struct transform_attribute<utree&, utree::list_type, qi::domain>
+ : transform_attribute<utree, utree::list_type, qi::domain>
     {};
 
     ///////////////////////////////////////////////////////////////////////////
@@ -286,8 +315,12 @@
             if (attr.empty())
                 attr.assign(first, last);
             else {
+ // make sure the attribute is a list, at least an empty one
+ if (traits::which(attr) != utree_type::list_type)
+ attr = utree::list;
+
                 for (Iterator i = first; i != last; ++i)
- push_back(attr, *i);
+ push_back(attr, traits::deref(i));
             }
         }
     };
@@ -307,7 +340,7 @@
         
             static bool is_valid(utree const& attr)
             {
- switch (attr.which())
+ switch (traits::which(attr))
                 {
                 case utree_type::reference_type:
                     return is_valid(attr.deref());
@@ -324,17 +357,17 @@
     }
     
     template <>
- struct attribute_as_xxx<std::string, utree>
+ struct attribute_as<std::string, utree>
       : detail::attribute_as_string_type
     {};
 
     template <>
- struct attribute_as_xxx<utf8_string_type, utree>
+ struct attribute_as<utf8_string_type, utree>
       : detail::attribute_as_string_type
     {};
 
     template <>
- struct attribute_as_xxx<utf8_string_range_type, utree>
+ struct attribute_as<utf8_string_range_type, utree>
       : detail::attribute_as_string_type
     {};
 
@@ -352,7 +385,7 @@
         
             static bool is_valid(utree const& attr)
             {
- switch (attr.which())
+ switch (traits::which(attr))
                 {
                 case utree_type::reference_type:
                     return is_valid(attr.deref());
@@ -368,12 +401,12 @@
     }
 
     template <>
- struct attribute_as_xxx<utf8_symbol_type, utree>
+ struct attribute_as<utf8_symbol_type, utree>
       : detail::attribute_as_symbol_type
     {};
 
     template <>
- struct attribute_as_xxx<utf8_symbol_range_type, utree>
+ struct attribute_as<utf8_symbol_range_type, utree>
       : detail::attribute_as_symbol_type
     {};
 
@@ -391,7 +424,7 @@
 
             static bool is_valid(utree const& attr)
             {
- switch (attr.which())
+ switch (traits::which(attr))
                 {
                 case utree_type::reference_type:
                     return is_valid(attr.deref());
@@ -407,12 +440,12 @@
     }
 
     template <>
- struct attribute_as_xxx<binary_string_type, utree>
+ struct attribute_as<binary_string_type, utree>
       : detail::attribute_as_binary_string_type
     {};
 
     template <>
- struct attribute_as_xxx<binary_range_type, utree>
+ struct attribute_as<binary_range_type, utree>
       : detail::attribute_as_binary_string_type
     {};
 
@@ -423,9 +456,9 @@
     {
         static bool call(utree& c, T const& val)
         {
- switch (c.which())
+ switch (traits::which(c))
             {
- case utree_type::uninitialized_type:
+ case utree_type::invalid_type:
                 case utree_type::nil_type:
                 case utree_type::list_type:
                     c.push_back(val);
@@ -445,6 +478,23 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+ // ensure the utree attribute is an empty list
+ template <>
+ struct make_container_attribute<utree>
+ {
+ static void call(utree& ut)
+ {
+ if (traits::which(ut) != utree_type::list_type)
+ ut = utree::list;
+ }
+ };
+
+ template <>
+ struct make_container_attribute<utree::list_type>
+ : make_container_attribute<utree>
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
     // an utree is a container on its own
     template <>
     struct build_std_vector<utree>
@@ -468,6 +518,14 @@
     // or a grammar exposes an utree as it's attribute
     namespace detail
     {
+ // checks if the attr is the explicit utree list type, utree::list_type
+ template <typename Attribute>
+ struct attribute_is_not_utree_list
+ : mpl::and_<
+ mpl::not_<is_same<utree::list_type, Attribute> >,
+ traits::is_container<Attribute> >
+ {};
+
         template <typename Attribute>
         struct attribute_is_not_utree
           : mpl::and_<
@@ -480,7 +538,7 @@
         typename Iterator, typename T1, typename T2, typename T3
       , typename T4>
     struct handles_container<qi::rule<Iterator, T1, T2, T3, T4>, utree>
- : detail::attribute_is_not_utree<typename attribute_of<
+ : detail::attribute_is_not_utree_list<typename attribute_of<
             qi::rule<Iterator, T1, T2, T3, T4>
>::type>
     {};
@@ -489,7 +547,7 @@
         typename Iterator, typename T1, typename T2, typename T3
       , typename T4>
     struct handles_container<qi::grammar<Iterator, T1, T2, T3, T4>, utree>
- : detail::attribute_is_not_utree<typename attribute_of<
+ : detail::attribute_is_not_utree_list<typename attribute_of<
             qi::grammar<Iterator, T1, T2, T3, T4>
>::type>
     {};
@@ -527,10 +585,10 @@
             return val;
         }
 
- // only 'uninitialized_type' utree nodes are not valid
+ // only 'invalid_type' utree nodes are not valid
         static bool is_valid(utree const& val)
         {
- return val.which() != utree_type::uninitialized_type;
+ return traits::which(val) != utree_type::invalid_type;
         }
     };
 
@@ -559,14 +617,6 @@
       : mpl::false_
     {};
 
- // this specialization tells Spirit how to extract the type of the value
- // stored in the given utree node
- template <>
- struct variant_which<utree>
- {
- static int call(utree const& u) { return u.which(); }
- };
-
     // The specializations below tell Spirit to verify whether an attribute
     // type is compatible with a given variant type
     template <>
@@ -596,14 +646,14 @@
     };
 
     template <>
- struct compute_compatible_component_variant<utree, utree::uninitialized_type>
+ struct compute_compatible_component_variant<utree, utree::invalid_type>
       : mpl::true_
     {
- typedef utree::uninitialized_type compatible_type;
+ typedef utree::invalid_type compatible_type;
 
         static bool is_compatible(int d)
         {
- return d == utree_type::uninitialized_type;
+ return d == utree_type::invalid_type;
         }
     };
 
@@ -741,7 +791,7 @@
 
         static bool is_compatible(int d)
         {
- return d >= utree_type::uninitialized_type &&
+ return d >= utree_type::invalid_type &&
                    d <= utree_type::reference_type;
         }
     };
@@ -755,7 +805,7 @@
 
         static bool is_compatible(int d)
         {
- return d >= utree_type::uninitialized_type &&
+ return d >= utree_type::invalid_type &&
                    d <= utree_type::reference_type;
         }
     };
@@ -783,7 +833,7 @@
         static type call(utree const& t)
         {
             utf8_symbol_range_type r = boost::get<utf8_symbol_range_type>(t);
- return std::string(r.begin(), r.end());
+ return std::string(traits::begin(r), traits::end(r));
         }
     };
 
@@ -804,7 +854,7 @@
         template <typename T>
         inline T get_or_deref(utree const& t)
         {
- if (t.which() == utree_type::list_type)
+ if (traits::which(t) == utree_type::list_type)
                 return boost::get<T>(t.front());
             return boost::get<T>(t);
         }
@@ -880,7 +930,7 @@
         static type call(utree const& t, Context&)
         {
             utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
- return std::basic_string<char, Traits, Alloc>(r.begin(), r.end());
+ return type(traits::begin(r), traits::end(r));
         }
     };
 
@@ -893,7 +943,7 @@
         static type call(utree const& t, Context&)
         {
             utf8_symbol_range_type r = detail::get_or_deref<utf8_symbol_range_type>(t);
- return std::string(r.begin(), r.end());
+ return std::string(traits::begin(r), traits::end(r));
         }
     };
 
@@ -906,7 +956,7 @@
         static type call(utree const& t, Context&)
         {
             utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
- return std::string(r.begin(), r.end());
+ return std::string(traits::begin(r), traits::end(r));
         }
     };
 
@@ -976,7 +1026,7 @@
         static type pre(utree const& t)
         {
             utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
- return std::basic_string<char, Traits, Alloc>(r.begin(), r.end());
+ return type(traits::begin(r), traits::end(r));
         }
     };
 
@@ -1004,7 +1054,7 @@
         static type pre(utree const& t)
         {
             utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
- return std::string(r.begin(), r.end());
+ return std::string(traits::begin(r), traits::end(r));
         }
     };
 
@@ -1016,10 +1066,11 @@
         static type pre(utree const& t)
         {
             utf8_symbol_range_type r = detail::get_or_deref<utf8_symbol_range_type>(t);
- return std::string(r.begin(), r.end());
+ return std::string(traits::begin(r), traits::end(r));
         }
     };
 
+ #if 0
     // If a rule takes an utree attribute and that utree instance holds nothing
     // more than a list, we dereference this to simplify attribute handling
     // down the stream, i.e. ( ( 1 2 3 ) ) --> ( 1 2 3 ).
@@ -1039,6 +1090,7 @@
     struct transform_attribute<utree const&, utree, karma::domain>
       : transform_attribute<utree const, utree, karma::domain>
     {};
+ #endif
 }}}
 
 #endif

Modified: trunk/libs/spirit/test/karma/utree.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/utree.cpp (original)
+++ trunk/libs/spirit/test/karma/utree.cpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -144,39 +144,49 @@
 
     // lists
     {
- // ( "a" "b" )
- rule<output_iterator, utree()> r1 = char_ % ',';
+ rule<output_iterator, utree()> r1, r1ref;
+ rule<output_iterator, utf8_string_range_type()> r1str;
+ rule<output_iterator, utree::const_range()> r1list;
+
+ r1 = double_ | int_ | r1str | r1list | r1ref;
+
+ r1ref = r1;
+
+ r1str = string;
+
+ r1list = '(' << -(r1 % ',') << ')';
+
+ // ( "abc" "def" )
         utree ut;
- ut.push_back('a');
- ut.push_back('b');
- BOOST_TEST(test("a,b", char_ % ',', ut));
- BOOST_TEST(test("a,b", r1, ut));
+ ut.push_back("abc");
+ ut.push_back("def");
+ BOOST_TEST(test("abc,def", string % ',', ut));
+ BOOST_TEST(test("(abc,def)", r1, ut));
 
- // ( ( "a" "b" ) )
+ // ( ( "abc" "def" ) )
         utree ut1;
         ut1.push_back(ut);
- BOOST_TEST(test("a,b", r1, ut1));
+ BOOST_TEST(test("((abc,def))", r1, ut1));
 
 // rule<output_iterator, std::vector<char>()> r2 = char_ % ',';
-// BOOST_TEST(test("a,b", r2, ut));
-// BOOST_TEST(test("a,b", r2, ut1));
+// BOOST_TEST(test("abc,def", r2, ut));
+// BOOST_TEST(test("abc,def", r2, ut1));
 
- // ( ( "a" "b" ) ( "a" "b" ) )
+ // ( ( "abc" "def" ) ( "abc" "def" ) )
         ut1.push_back(ut);
- BOOST_TEST(test("a,b a,b", r1 << ' ' << r1, ut1));
+ BOOST_TEST(test("(abc,def) (abc,def)", r1 << ' ' << r1, ut1));
 
         // ( 123 456 )
- rule<output_iterator, utree()> r3 = int_ % ',';
         ut.clear();
         ut.push_back(123);
         ut.push_back(456);
         BOOST_TEST(test("123,456", int_ % ',', ut));
- BOOST_TEST(test("123,456", r3, ut));
+ BOOST_TEST(test("(123,456)", r1, ut));
 
         // ( ( 123 456 ) )
         ut1.clear();
         ut1.push_back(ut);
- BOOST_TEST(test("123,456", r3, ut1));
+ BOOST_TEST(test("((123,456))", r1, ut1));
 
 // rule<output_iterator, std::vector<int>()> r4 = int_ % ',';
 // BOOST_TEST(test("123,456", r4, ut));
@@ -184,20 +194,19 @@
 
         // ( ( 123 456 ) ( 123 456 ) )
         ut1.push_back(ut);
- BOOST_TEST(test("123,456 123,456", r3 << ' ' << r3, ut1));
+ BOOST_TEST(test("(123,456) (123,456)", r1 << ' ' << r1, ut1));
 
         // ( 1.23 4.56 )
- rule<output_iterator, utree()> r5 = double_ % ',';
         ut.clear();
         ut.push_back(1.23);
         ut.push_back(4.56);
         BOOST_TEST(test("1.23,4.56", double_ % ',', ut));
- BOOST_TEST(test("1.23,4.56", r5, ut));
+ BOOST_TEST(test("(1.23,4.56)", r1, ut));
 
         // ( ( 1.23 4.56 ) )
         ut1.clear();
         ut1.push_back(ut);
- BOOST_TEST(test("1.23,4.56", r5, ut1));
+ BOOST_TEST(test("((1.23,4.56))", r1, ut1));
 
 // rule<output_iterator, std::vector<double>()> r6 = double_ % ',';
 // BOOST_TEST(test("1.23,4.56", r6, ut));
@@ -205,7 +214,7 @@
 
         // ( ( 1.23 4.56 ) ( 1.23 4.56 ) )
         ut1.push_back(ut);
- BOOST_TEST(test("1.23,4.56 1.23,4.56", r5 <<' ' << r5, ut1));
+ BOOST_TEST(test("(1.23,4.56) (1.23,4.56)", r1 <<' ' << r1, ut1));
     }
 
     // alternatives

Modified: trunk/libs/spirit/test/qi/utree.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/utree.cpp (original)
+++ trunk/libs/spirit/test/qi/utree.cpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -8,8 +8,8 @@
 #include <boost/config/warning_disable.hpp>
 #include <boost/detail/lightweight_test.hpp>
 
-#include <boost/spirit/include/support_utree.hpp>
 #include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/support_utree.hpp>
 #include <boost/mpl/print.hpp>
 
 #include <sstream>
@@ -45,6 +45,7 @@
     using boost::spirit::qi::int_;
     using boost::spirit::qi::double_;
     using boost::spirit::qi::space;
+ using boost::spirit::qi::space_type;
     using boost::spirit::qi::rule;
     using boost::spirit::qi::as;
     using boost::spirit::qi::lexeme;
@@ -77,9 +78,17 @@
     // single character parsers
     {
         utree ut;
- rule<char const*, utree()> r = char_("abc");
 
- BOOST_TEST(test_attr("a", r, ut) &&
+ // this rule returns a utree string
+ rule<char const*, utree()> r1 = char_("abc");
+
+ // this rule forces a utree list to be returned
+ rule<char const*, utree::list_type()> r2 = char_("abc");
+
+ BOOST_TEST(test_attr("a", r1, ut) &&
+ ut.which() == utree_type::string_type && check(ut, "\"a\""));
+ ut.clear();
+ BOOST_TEST(test_attr("a", r2, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( \"a\" )"));
     }
 
@@ -96,7 +105,6 @@
         ut.clear();
         BOOST_TEST(test_attr("1.23 4.56", double_ >> double_, ut, space) &&
             ut.which() == utree_type::list_type && check(ut, "( 1.23 4.56 )"));
-
         ut.clear();
         BOOST_TEST(test_attr("1.2ab", double_ >> *char_, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( 1.2 \"a\" \"b\" )"));
@@ -104,7 +112,9 @@
         BOOST_TEST(test_attr("ab1.2", *~digit >> double_, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( \"a\" \"b\" 1.2 )"));
 
- rule<char const*, utree()> r1 = double_;
+ // forces a utree list
+ rule<char const*, utree::list_type()> r1 = double_;
+
         ut.clear();
         BOOST_TEST(test_attr("1.2ab", r1 >> *char_, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( ( 1.2 ) \"a\" \"b\" )"));
@@ -112,7 +122,8 @@
         BOOST_TEST(test_attr("ab1.2", *~digit >> r1, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( \"a\" \"b\" ( 1.2 ) )"));
         ut.clear();
-
+
+ // implicitly a utree list, because of sequence attribute rules
         rule<char const*, utree()> r2 = int_ >> char_("!") >> double_;
         
         BOOST_TEST(test_attr("17!3.14", r2, ut) &&
@@ -123,12 +134,15 @@
 
         BOOST_TEST(test_attr("0.5foo5", r3, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( 0.5 \"foo\" 5 )"));
-
         ut.clear();
     }
 
     // kleene star
     {
+ typedef real_parser<double, strict_real_policies<double> >
+ strict_double_type;
+ strict_double_type const strict_double = strict_double_type();
+
         utree ut;
         BOOST_TEST(test_attr("xy", *char_, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( \"x\" \"y\" )"));
@@ -138,6 +152,37 @@
         ut.clear();
         BOOST_TEST(test_attr("1.23 4.56", *double_, ut, space) &&
             ut.which() == utree_type::list_type && check(ut, "( 1.23 4.56 )"));
+ ut.clear();
+
+ rule<char const*, utree(), space_type> r1 =
+ strict_double | int_ | ~char_("()") | ('(' >> *r1 >> ')');
+
+ BOOST_TEST(test_attr("(x y)", r1, ut, space) &&
+ ut.which() == utree_type::list_type && check(ut, "( \"x\" \"y\" )"));
+ ut.clear();
+ BOOST_TEST(test_attr("(((123)) 456)", r1, ut, space) &&
+ ut.which() == utree_type::list_type && check(ut, "( ( ( 123 ) ) 456 )"));
+ ut.clear();
+ BOOST_TEST(test_attr("((1.23 4.56))", r1, ut, space) &&
+ ut.which() == utree_type::list_type && check(ut, "( ( 1.23 4.56 ) )"));
+ ut.clear();
+ BOOST_TEST(test_attr("x", r1, ut, space) &&
+ ut.which() == utree_type::string_type && check(ut, "\"x\""));
+ ut.clear();
+ BOOST_TEST(test_attr("123", r1, ut, space) &&
+ ut.which() == utree_type::int_type && check(ut, "123"));
+ ut.clear();
+ BOOST_TEST(test_attr("123.456", r1, ut, space) &&
+ ut.which() == utree_type::double_type && check(ut, "123.456"));
+ ut.clear();
+ BOOST_TEST(test_attr("()", r1, ut, space) &&
+ ut.which() == utree_type::list_type &&
+ check(ut, "( )"));
+ ut.clear();
+ BOOST_TEST(test_attr("((()))", r1, ut, space) &&
+ ut.which() == utree_type::list_type &&
+ check(ut, "( ( ( ) ) )"));
+ ut.clear();
     }
 
     // lists
@@ -197,9 +242,17 @@
         rule<char const*, utree()> r2 = strict_double | int_;
         ut.clear();
         BOOST_TEST(test_attr("10", r2, ut) &&
- ut.which() == utree_type::list_type && check(ut, "( 10 )"));
+ ut.which() == utree_type::int_type && check(ut, "10"));
         ut.clear();
         BOOST_TEST(test_attr("10.2", r2, ut) &&
+ ut.which() == utree_type::double_type && check(ut, "10.2"));
+
+ rule<char const*, utree::list_type()> r3 = strict_double | int_;
+ ut.clear();
+ BOOST_TEST(test_attr("10", r3, ut) &&
+ ut.which() == utree_type::list_type && check(ut, "( 10 )"));
+ ut.clear();
+ BOOST_TEST(test_attr("10.2", r3, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( 10.2 )"));
     }
 
@@ -210,8 +263,8 @@
             ut.which() == utree_type::string_type && check(ut, "\"x\""));
         ut.clear();
         BOOST_TEST(test_attr("", -char_, ut) &&
- ut.which() == utree_type::uninitialized_type &&
- check(ut, "<uninitialized>"));
+ ut.which() == utree_type::invalid_type &&
+ check(ut, "<invalid>"));
     }
 
     // as_string
@@ -328,10 +381,19 @@
 
         rule<char const*, utree()> r2 = int_ % ',';
         BOOST_TEST(test_attr("1 2,3", int_ >> ' ' >> r2, ut) &&
- ut.which() == utree_type::list_type && check(ut, "( 1 ( 2 3 ) )"));
+ ut.which() == utree_type::list_type && check(ut, "( 1 2 3 )"));
         ut.clear();
 
         BOOST_TEST(test_attr("1,2 2,3", r2 >> ' ' >> r2, ut) &&
+ ut.which() == utree_type::list_type && check(ut, "( 1 2 2 3 )"));
+ ut.clear();
+
+ rule<char const*, utree::list_type()> r3 = int_ % ',';
+ BOOST_TEST(test_attr("1 2,3", int_ >> ' ' >> r3, ut) &&
+ ut.which() == utree_type::list_type && check(ut, "( 1 ( 2 3 ) )"));
+ ut.clear();
+
+ BOOST_TEST(test_attr("1,2 2,3", r3 >> ' ' >> r3, ut) &&
             ut.which() == utree_type::list_type && check(ut, "( ( 1 2 ) ( 2 3 ) )"));
         ut.clear();
     }

Modified: trunk/libs/spirit/test/support/utree_test.cpp
==============================================================================
--- trunk/libs/spirit/test/support/utree_test.cpp (original)
+++ trunk/libs/spirit/test/support/utree_test.cpp 2010-12-27 18:45:44 EST (Mon, 27 Dec 2010)
@@ -200,7 +200,7 @@
         a = 100.00;
         BOOST_TEST(a < b);
 
- b = a = utree(utree::uninitialized);
+ b = a = utree(utree::invalid);
         BOOST_TEST(a == b);
         a.push_back(1);
         a.push_back("two");
@@ -215,7 +215,7 @@
     }
 
     {
- utree a(utree::nil);
+ utree a(utree::list);
         a.push_back(1);
         a.push_back(2);
         a.push_back(3);


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