|
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