1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ossrv_pub/boost_apis/boost/spirit/tree/common.hpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1504 @@
1.4 +/*=============================================================================
1.5 + Copyright (c) 2001-2003 Daniel Nuffer
1.6 + http://spirit.sourceforge.net/
1.7 +
1.8 + Use, modification and distribution is subject to the Boost Software
1.9 + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
1.10 + http://www.boost.org/LICENSE_1_0.txt)
1.11 +=============================================================================*/
1.12 +#ifndef BOOST_SPIRIT_TREE_COMMON_HPP
1.13 +#define BOOST_SPIRIT_TREE_COMMON_HPP
1.14 +
1.15 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.16 +#include <vector>
1.17 +#else
1.18 +#include <list>
1.19 +#endif
1.20 +
1.21 +#if defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
1.22 +#include <boost/pool/pool_alloc.hpp>
1.23 +#endif
1.24 +
1.25 +#include <algorithm>
1.26 +
1.27 +#include <boost/ref.hpp>
1.28 +#include <boost/call_traits.hpp>
1.29 +#include <boost/spirit/core.hpp>
1.30 +#include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
1.31 +
1.32 +#if defined(BOOST_SPIRIT_DEBUG) && \
1.33 + (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
1.34 +#include <iostream>
1.35 +#include <boost/spirit/debug/debug_node.hpp>
1.36 +#endif
1.37 +
1.38 +#include <boost/spirit/tree/common_fwd.hpp>
1.39 +
1.40 +namespace boost { namespace spirit {
1.41 +
1.42 +template <typename T>
1.43 +void swap(tree_node<T>& a, tree_node<T>& b);
1.44 +
1.45 +template <typename T, typename V>
1.46 +void swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b);
1.47 +
1.48 +namespace impl {
1.49 + template <typename T>
1.50 + inline void cp_swap(T& t1, T& t2);
1.51 +}
1.52 +
1.53 +template <typename T>
1.54 +struct tree_node
1.55 +{
1.56 + typedef T parse_node_t;
1.57 +
1.58 +#if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
1.59 + typedef std::allocator<tree_node<T> > allocator_type;
1.60 +#elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.61 + typedef boost::pool_allocator<tree_node<T> > allocator_type;
1.62 +#else
1.63 + typedef boost::fast_pool_allocator<tree_node<T> > allocator_type;
1.64 +#endif
1.65 +
1.66 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.67 + typedef std::vector<tree_node<T>, allocator_type> children_t;
1.68 +#else
1.69 + typedef std::list<tree_node<T>, allocator_type> children_t;
1.70 +#endif // BOOST_SPIRIT_USE_LIST_FOR_TREES
1.71 +
1.72 + typedef typename children_t::iterator tree_iterator;
1.73 + typedef typename children_t::const_iterator const_tree_iterator;
1.74 +
1.75 + T value;
1.76 + children_t children;
1.77 +
1.78 + tree_node()
1.79 + : value()
1.80 + , children()
1.81 + {}
1.82 +
1.83 + explicit tree_node(T const& v)
1.84 + : value(v)
1.85 + , children()
1.86 + {}
1.87 +
1.88 + tree_node(T const& v, children_t const& c)
1.89 + : value(v)
1.90 + , children(c)
1.91 + {}
1.92 +
1.93 + void swap(tree_node<T>& x)
1.94 + {
1.95 + impl::cp_swap(value, x.value);
1.96 + impl::cp_swap(children, x.children);
1.97 + }
1.98 +
1.99 +// Intel V5.0.1 has a problem without this explicit operator=
1.100 + tree_node &operator= (tree_node const &rhs)
1.101 + {
1.102 + tree_node(rhs).swap(*this);
1.103 + return *this;
1.104 + }
1.105 +};
1.106 +
1.107 +#if defined(BOOST_SPIRIT_DEBUG) && \
1.108 + (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
1.109 +template <typename T>
1.110 +inline std::ostream&
1.111 +operator<<(std::ostream& o, tree_node<T> const& n)
1.112 +{
1.113 + static int depth = 0;
1.114 + o << "\n";
1.115 + for (int i = 0; i <= depth; ++i)
1.116 + {
1.117 + o << "\t";
1.118 + }
1.119 + o << "(depth = " << depth++ << " value = " << n.value;
1.120 + int c = 0;
1.121 + for (typename tree_node<T>::children_t::const_iterator it = n.children.begin();
1.122 + it != n.children.end(); ++it)
1.123 + {
1.124 + o << " children[" << c++ << "] = " << *it;
1.125 + }
1.126 + o << ")";
1.127 + --depth;
1.128 + return o;
1.129 +}
1.130 +#endif
1.131 +
1.132 +//////////////////////////////////
1.133 +template <typename IteratorT, typename ValueT>
1.134 +struct node_iter_data
1.135 +{
1.136 + typedef IteratorT iterator_t;
1.137 + typedef IteratorT /*const*/ const_iterator_t;
1.138 +
1.139 + node_iter_data()
1.140 + : first(), last(), is_root_(false), parser_id_(), value_()
1.141 + {}
1.142 +
1.143 + node_iter_data(IteratorT const& _first, IteratorT const& _last)
1.144 + : first(_first), last(_last), is_root_(false), parser_id_(), value_()
1.145 + {}
1.146 +
1.147 + void swap(node_iter_data& x)
1.148 + {
1.149 + impl::cp_swap(first, x.first);
1.150 + impl::cp_swap(last, x.last);
1.151 + impl::cp_swap(parser_id_, x.parser_id_);
1.152 + impl::cp_swap(is_root_, x.is_root_);
1.153 + impl::cp_swap(value_, x.value_);
1.154 + }
1.155 +
1.156 + IteratorT begin()
1.157 + {
1.158 + return first;
1.159 + }
1.160 +
1.161 + IteratorT const& begin() const
1.162 + {
1.163 + return first;
1.164 + }
1.165 +
1.166 + IteratorT end()
1.167 + {
1.168 + return last;
1.169 + }
1.170 +
1.171 + IteratorT const& end() const
1.172 + {
1.173 + return last;
1.174 + }
1.175 +
1.176 + bool is_root() const
1.177 + {
1.178 + return is_root_;
1.179 + }
1.180 +
1.181 + void is_root(bool b)
1.182 + {
1.183 + is_root_ = b;
1.184 + }
1.185 +
1.186 + parser_id id() const
1.187 + {
1.188 + return parser_id_;
1.189 + }
1.190 +
1.191 + void id(parser_id r)
1.192 + {
1.193 + parser_id_ = r;
1.194 + }
1.195 +
1.196 + ValueT const& value() const
1.197 + {
1.198 + return value_;
1.199 + }
1.200 +
1.201 + void value(ValueT const& v)
1.202 + {
1.203 + value_ = v;
1.204 + }
1.205 +private:
1.206 + IteratorT first, last;
1.207 + bool is_root_;
1.208 + parser_id parser_id_;
1.209 + ValueT value_;
1.210 +
1.211 +public:
1.212 +};
1.213 +
1.214 +#if defined(BOOST_SPIRIT_DEBUG) && \
1.215 + (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
1.216 +// value is default nil_t, so provide an operator<< for nil_t
1.217 +inline std::ostream&
1.218 +operator<<(std::ostream& o, nil_t const&)
1.219 +{
1.220 + return o;
1.221 +}
1.222 +
1.223 +template <typename IteratorT, typename ValueT>
1.224 +inline std::ostream&
1.225 +operator<<(std::ostream& o, node_iter_data<IteratorT, ValueT> const& n)
1.226 +{
1.227 + o << "(id = " << n.id() << " text = \"";
1.228 + typedef typename node_iter_data<IteratorT, ValueT>::const_iterator_t
1.229 + iterator_t;
1.230 + for (iterator_t it = n.begin(); it != n.end(); ++it)
1.231 + impl::token_printer(o, *it);
1.232 + o << "\" is_root = " << n.is_root()
1.233 + << /*" value = " << n.value() << */")";
1.234 + return o;
1.235 +}
1.236 +#endif
1.237 +
1.238 +//////////////////////////////////
1.239 +template <typename IteratorT = char const*, typename ValueT = nil_t>
1.240 +struct node_val_data
1.241 +{
1.242 + typedef
1.243 + typename boost::detail::iterator_traits<IteratorT>::value_type
1.244 + value_type;
1.245 +
1.246 +#if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
1.247 + typedef std::allocator<value_type> allocator_type;
1.248 +#elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.249 + typedef boost::pool_allocator<value_type> allocator_type;
1.250 +#else
1.251 + typedef boost::fast_pool_allocator<value_type> allocator_type;
1.252 +#endif
1.253 +
1.254 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.255 + typedef std::vector<value_type, allocator_type> container_t;
1.256 +#else
1.257 + typedef std::list<value_type, allocator_type> container_t;
1.258 +#endif
1.259 +
1.260 + typedef typename container_t::iterator iterator_t;
1.261 + typedef typename container_t::const_iterator const_iterator_t;
1.262 +
1.263 + node_val_data()
1.264 + : text(), is_root_(false), parser_id_(), value_()
1.265 + {}
1.266 +
1.267 +#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
1.268 + node_val_data(IteratorT const& _first, IteratorT const& _last)
1.269 + : text(), is_root_(false), parser_id_(), value_()
1.270 + {
1.271 + std::copy(_first, _last, std::inserter(text, text.end()));
1.272 + }
1.273 +
1.274 + // This constructor is for building text out of iterators
1.275 + template <typename IteratorT2>
1.276 + node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
1.277 + : text(), is_root_(false), parser_id_(), value_()
1.278 + {
1.279 + std::copy(_first, _last, std::inserter(text, text.end()));
1.280 + }
1.281 +#else
1.282 + node_val_data(IteratorT const& _first, IteratorT const& _last)
1.283 + : text(_first, _last), is_root_(false), parser_id_(), value_()
1.284 + {}
1.285 +
1.286 + // This constructor is for building text out of iterators
1.287 + template <typename IteratorT2>
1.288 + node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
1.289 + : text(_first, _last), is_root_(false), parser_id_(), value_()
1.290 + {}
1.291 +#endif
1.292 +
1.293 + void swap(node_val_data& x)
1.294 + {
1.295 + impl::cp_swap(text, x.text);
1.296 + impl::cp_swap(is_root_, x.is_root_);
1.297 + impl::cp_swap(parser_id_, x.parser_id_);
1.298 + impl::cp_swap(value_, x.value_);
1.299 + }
1.300 +
1.301 + typename container_t::iterator begin()
1.302 + {
1.303 + return text.begin();
1.304 + }
1.305 +
1.306 + typename container_t::const_iterator begin() const
1.307 + {
1.308 + return text.begin();
1.309 + }
1.310 +
1.311 + typename container_t::iterator end()
1.312 + {
1.313 + return text.end();
1.314 + }
1.315 +
1.316 + typename container_t::const_iterator end() const
1.317 + {
1.318 + return text.end();
1.319 + }
1.320 +
1.321 + bool is_root() const
1.322 + {
1.323 + return is_root_;
1.324 + }
1.325 +
1.326 + void is_root(bool b)
1.327 + {
1.328 + is_root_ = b;
1.329 + }
1.330 +
1.331 + parser_id id() const
1.332 + {
1.333 + return parser_id_;
1.334 + }
1.335 +
1.336 + void id(parser_id r)
1.337 + {
1.338 + parser_id_ = r;
1.339 + }
1.340 +
1.341 + ValueT const& value() const
1.342 + {
1.343 + return value_;
1.344 + }
1.345 +
1.346 + void value(ValueT const& v)
1.347 + {
1.348 + value_ = v;
1.349 + }
1.350 +
1.351 +private:
1.352 + container_t text;
1.353 + bool is_root_;
1.354 + parser_id parser_id_;
1.355 + ValueT value_;
1.356 +};
1.357 +
1.358 +#if defined(BOOST_SPIRIT_DEBUG) && \
1.359 + (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
1.360 +template <typename IteratorT, typename ValueT>
1.361 +inline std::ostream&
1.362 +operator<<(std::ostream& o, node_val_data<IteratorT, ValueT> const& n)
1.363 +{
1.364 + o << "(id = " << n.id() << " text = \"";
1.365 + typedef typename node_val_data<IteratorT, ValueT>::const_iterator_t
1.366 + iterator_t;
1.367 + for (iterator_t it = n.begin(); it != n.end(); ++it)
1.368 + impl::token_printer(o, *it);
1.369 + o << "\" is_root = " << n.is_root()
1.370 + << " value = " << n.value() << ")";
1.371 + return o;
1.372 +}
1.373 +#endif
1.374 +
1.375 +template <typename T>
1.376 +inline void
1.377 +swap(tree_node<T>& a, tree_node<T>& b)
1.378 +{
1.379 + a.swap(b);
1.380 +}
1.381 +
1.382 +template <typename T, typename V>
1.383 +inline void
1.384 +swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b)
1.385 +{
1.386 + a.swap(b);
1.387 +}
1.388 +
1.389 +//////////////////////////////////
1.390 +template <typename ValueT>
1.391 +class node_iter_data_factory
1.392 +{
1.393 +public:
1.394 + // This inner class is so that node_iter_data_factory can simulate
1.395 + // a template template parameter
1.396 + template <typename IteratorT>
1.397 + class factory
1.398 + {
1.399 + public:
1.400 + typedef IteratorT iterator_t;
1.401 + typedef node_iter_data<iterator_t, ValueT> node_t;
1.402 +
1.403 + static node_t create_node(iterator_t const& first, iterator_t const& last,
1.404 + bool /*is_leaf_node*/)
1.405 + {
1.406 + return node_t(first, last);
1.407 + }
1.408 +
1.409 + static node_t empty_node()
1.410 + {
1.411 + return node_t();
1.412 + }
1.413 +
1.414 + // precondition: ContainerT contains a tree_node<node_t>. And all
1.415 + // iterators in the container point to the same sequence.
1.416 + template <typename ContainerT>
1.417 + static node_t group_nodes(ContainerT const& nodes)
1.418 + {
1.419 + return node_t(nodes.begin()->value.begin(),
1.420 + nodes.back().value.end());
1.421 + }
1.422 + };
1.423 +};
1.424 +
1.425 +//////////////////////////////////
1.426 +template <typename ValueT>
1.427 +class node_val_data_factory
1.428 +{
1.429 +public:
1.430 + // This inner class is so that node_val_data_factory can simulate
1.431 + // a template template parameter
1.432 + template <typename IteratorT>
1.433 + class factory
1.434 + {
1.435 + public:
1.436 + typedef IteratorT iterator_t;
1.437 + typedef node_val_data<iterator_t, ValueT> node_t;
1.438 +
1.439 + static node_t create_node(iterator_t const& first, iterator_t const& last,
1.440 + bool is_leaf_node)
1.441 + {
1.442 + if (is_leaf_node)
1.443 + return node_t(first, last);
1.444 + else
1.445 + return node_t();
1.446 + }
1.447 +
1.448 + static node_t empty_node()
1.449 + {
1.450 + return node_t();
1.451 + }
1.452 +
1.453 + template <typename ContainerT>
1.454 + static node_t group_nodes(ContainerT const& nodes)
1.455 + {
1.456 + typename node_t::container_t c;
1.457 + typename ContainerT::const_iterator i_end = nodes.end();
1.458 + // copy all the nodes text into a new one
1.459 + for (typename ContainerT::const_iterator i = nodes.begin();
1.460 + i != i_end; ++i)
1.461 + {
1.462 + // See docs: token_node_d or leaf_node_d cannot be used with a
1.463 + // rule inside the [].
1.464 + assert(i->children.size() == 0);
1.465 + c.insert(c.end(), i->value.begin(), i->value.end());
1.466 + }
1.467 + return node_t(c.begin(), c.end());
1.468 + }
1.469 + };
1.470 +};
1.471 +
1.472 +//////////////////////////////////
1.473 +template <typename ValueT>
1.474 +class node_all_val_data_factory
1.475 +{
1.476 +public:
1.477 + // This inner class is so that node_all_val_data_factory can simulate
1.478 + // a template template parameter
1.479 + template <typename IteratorT>
1.480 + class factory
1.481 + {
1.482 + public:
1.483 + typedef IteratorT iterator_t;
1.484 + typedef node_val_data<iterator_t, ValueT> node_t;
1.485 +
1.486 + static node_t create_node(iterator_t const& first, iterator_t const& last,
1.487 + bool /*is_leaf_node*/)
1.488 + {
1.489 + return node_t(first, last);
1.490 + }
1.491 +
1.492 + static node_t empty_node()
1.493 + {
1.494 + return node_t();
1.495 + }
1.496 +
1.497 + template <typename ContainerT>
1.498 + static node_t group_nodes(ContainerT const& nodes)
1.499 + {
1.500 + typename node_t::container_t c;
1.501 + typename ContainerT::const_iterator i_end = nodes.end();
1.502 + // copy all the nodes text into a new one
1.503 + for (typename ContainerT::const_iterator i = nodes.begin();
1.504 + i != i_end; ++i)
1.505 + {
1.506 + // See docs: token_node_d or leaf_node_d cannot be used with a
1.507 + // rule inside the [].
1.508 + assert(i->children.size() == 0);
1.509 + c.insert(c.end(), i->value.begin(), i->value.end());
1.510 + }
1.511 + return node_t(c.begin(), c.end());
1.512 + }
1.513 + };
1.514 +};
1.515 +
1.516 +namespace impl {
1.517 +
1.518 + ///////////////////////////////////////////////////////////////////////////
1.519 + // can't call unqualified swap from within classname::swap
1.520 + // as Koenig lookup rules will find only the classname::swap
1.521 + // member function not the global declaration, so use cp_swap
1.522 + // as a forwarding function (JM):
1.523 +#if __GNUC__ == 2
1.524 + using ::std::swap;
1.525 +#endif
1.526 + template <typename T>
1.527 + inline void cp_swap(T& t1, T& t2)
1.528 + {
1.529 + using std::swap;
1.530 + using boost::spirit::swap;
1.531 + using boost::swap;
1.532 + swap(t1, t2);
1.533 + }
1.534 +}
1.535 +
1.536 +//////////////////////////////////
1.537 +template <typename IteratorT, typename NodeFactoryT, typename T>
1.538 +class tree_match : public match<T>
1.539 +{
1.540 +public:
1.541 +
1.542 + typedef typename NodeFactoryT::template factory<IteratorT> node_factory_t;
1.543 + typedef typename node_factory_t::node_t parse_node_t;
1.544 + typedef tree_node<parse_node_t> node_t;
1.545 + typedef typename node_t::children_t container_t;
1.546 + typedef typename container_t::iterator tree_iterator;
1.547 + typedef typename container_t::const_iterator const_tree_iterator;
1.548 +
1.549 + typedef T attr_t;
1.550 + typedef typename boost::call_traits<T>::param_type param_type;
1.551 + typedef typename boost::call_traits<T>::reference reference;
1.552 + typedef typename boost::call_traits<T>::const_reference const_reference;
1.553 +
1.554 + tree_match()
1.555 + : match<T>(), trees()
1.556 + {}
1.557 +
1.558 + explicit
1.559 + tree_match(std::size_t length)
1.560 + : match<T>(length), trees()
1.561 + {}
1.562 +
1.563 + tree_match(std::size_t length, parse_node_t const& n)
1.564 + : match<T>(length), trees()
1.565 + {
1.566 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.567 + trees.reserve(10); // this is more or less an arbitrary number...
1.568 +#endif
1.569 + trees.push_back(node_t(n));
1.570 + }
1.571 +
1.572 + tree_match(std::size_t length, param_type val, parse_node_t const& n)
1.573 + : match<T>(length, val), trees()
1.574 + {
1.575 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.576 + trees.reserve(10); // this is more or less an arbitrary number...
1.577 +#endif
1.578 + trees.push_back(node_t(n));
1.579 + }
1.580 +
1.581 + // attention, these constructors will change the second parameter!
1.582 + tree_match(std::size_t length, container_t& c)
1.583 + : match<T>(length), trees()
1.584 + {
1.585 + impl::cp_swap(trees, c);
1.586 + }
1.587 +
1.588 + tree_match(std::size_t length, param_type val, container_t& c)
1.589 + : match<T>(length, val), trees()
1.590 + {
1.591 + impl::cp_swap(trees, c);
1.592 + }
1.593 +
1.594 + template <typename T2>
1.595 + tree_match(match<T2> const& other)
1.596 + : match<T>(other), trees()
1.597 + {}
1.598 +
1.599 + template <typename T2, typename T3, typename T4>
1.600 + tree_match(tree_match<T2, T3, T4> const& other)
1.601 + : match<T>(other), trees()
1.602 + { impl::cp_swap(trees, other.trees); }
1.603 +
1.604 + template <typename T2>
1.605 + tree_match&
1.606 + operator=(match<T2> const& other)
1.607 + {
1.608 + match<T>::operator=(other);
1.609 + return *this;
1.610 + }
1.611 +
1.612 + template <typename T2, typename T3, typename T4>
1.613 + tree_match&
1.614 + operator=(tree_match<T2, T3, T4> const& other)
1.615 + {
1.616 + match<T>::operator=(other);
1.617 + impl::cp_swap(trees, other.trees);
1.618 + return *this;
1.619 + }
1.620 +
1.621 + tree_match(tree_match const& x)
1.622 + : match<T>(x), trees()
1.623 + {
1.624 + // use auto_ptr like ownership for the trees data member
1.625 + impl::cp_swap(trees, x.trees);
1.626 + }
1.627 +
1.628 + tree_match& operator=(tree_match const& x)
1.629 + {
1.630 + tree_match tmp(x);
1.631 + this->swap(tmp);
1.632 + return *this;
1.633 + }
1.634 +
1.635 + void swap(tree_match& x)
1.636 + {
1.637 + match<T>::swap(x);
1.638 + impl::cp_swap(trees, x.trees);
1.639 + }
1.640 +
1.641 + mutable container_t trees;
1.642 +};
1.643 +
1.644 +#if defined(BOOST_SPIRIT_DEBUG) && \
1.645 + (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
1.646 +template <typename IteratorT, typename NodeFactoryT, typename T>
1.647 +inline std::ostream&
1.648 +operator<<(std::ostream& o, tree_match<IteratorT, NodeFactoryT, T> const& m)
1.649 +{
1.650 + typedef
1.651 + typename tree_match<IteratorT, NodeFactoryT, T>::container_t::iterator
1.652 + iterator;
1.653 +
1.654 + o << "(length = " << (int)m.length();
1.655 + int c = 0;
1.656 + for (iterator i = m.trees.begin(); i != m.trees.end(); ++i)
1.657 + {
1.658 + o << " trees[" << c++ << "] = " << *i;
1.659 + }
1.660 + o << "\n)";
1.661 + return o;
1.662 +}
1.663 +#endif
1.664 +
1.665 +//////////////////////////////////
1.666 +struct tree_policy
1.667 +{
1.668 + template <typename FunctorT, typename MatchT>
1.669 + static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/)
1.670 + {}
1.671 +
1.672 + template <typename MatchT, typename Iterator1T, typename Iterator2T>
1.673 + static void group_match(MatchT& /*m*/, parser_id const& /*id*/,
1.674 + Iterator1T const& /*first*/, Iterator2T const& /*last*/)
1.675 + {}
1.676 +
1.677 + template <typename MatchT>
1.678 + static void concat(MatchT& /*a*/, MatchT const& /*b*/)
1.679 + {}
1.680 +};
1.681 +
1.682 +//////////////////////////////////
1.683 +template <
1.684 + typename MatchPolicyT,
1.685 + typename IteratorT,
1.686 + typename NodeFactoryT,
1.687 + typename TreePolicyT
1.688 +>
1.689 +struct common_tree_match_policy : public match_policy
1.690 +{
1.691 + common_tree_match_policy()
1.692 + {
1.693 + }
1.694 +
1.695 + template <typename PolicyT>
1.696 + common_tree_match_policy(PolicyT const & policies)
1.697 + : match_policy(policies)
1.698 + {
1.699 + }
1.700 +
1.701 + template <typename T>
1.702 + struct result { typedef tree_match<IteratorT, NodeFactoryT, T> type; };
1.703 +
1.704 + typedef tree_match<IteratorT, NodeFactoryT> match_t;
1.705 + typedef IteratorT iterator_t;
1.706 + typedef TreePolicyT tree_policy_t;
1.707 + typedef NodeFactoryT factory_t;
1.708 +
1.709 + static const match_t no_match() { return match_t(); }
1.710 + static const match_t empty_match()
1.711 + { return match_t(0, tree_policy_t::empty_node()); }
1.712 +
1.713 + template <typename AttrT, typename Iterator1T, typename Iterator2T>
1.714 + static tree_match<IteratorT, NodeFactoryT, AttrT> create_match(
1.715 + std::size_t length,
1.716 + AttrT const& val,
1.717 + Iterator1T const& first,
1.718 + Iterator2T const& last)
1.719 + {
1.720 +#if defined(BOOST_SPIRIT_DEBUG) && \
1.721 + (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
1.722 +
1.723 + BOOST_SPIRIT_DEBUG_OUT << "\n>>> create_node(begin) <<<\n"
1.724 + "creating node text: \"";
1.725 + for (Iterator1T it = first; it != last; ++it)
1.726 + impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
1.727 + BOOST_SPIRIT_DEBUG_OUT << "\"\n";
1.728 + BOOST_SPIRIT_DEBUG_OUT << ">>> create_node(end) <<<\n\n";
1.729 +#endif
1.730 + return tree_match<IteratorT, NodeFactoryT, AttrT>(length, val,
1.731 + tree_policy_t::create_node(length, first, last, true));
1.732 + }
1.733 +
1.734 + template <typename Match1T, typename Match2T>
1.735 + static void concat_match(Match1T& a, Match2T const& b)
1.736 + {
1.737 +#if defined(BOOST_SPIRIT_DEBUG) && \
1.738 + (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
1.739 +
1.740 + BOOST_SPIRIT_DEBUG_OUT << "\n>>> concat_match(begin) <<<\n";
1.741 + BOOST_SPIRIT_DEBUG_OUT << "tree a:\n" << a << "\n";
1.742 + BOOST_SPIRIT_DEBUG_OUT << "tree b:\n" << b << "\n";
1.743 + BOOST_SPIRIT_DEBUG_OUT << ">>> concat_match(end) <<<\n\n";
1.744 +#endif
1.745 + BOOST_SPIRIT_ASSERT(a && b);
1.746 + if (a.length() == 0)
1.747 + {
1.748 + a = b;
1.749 + return;
1.750 + }
1.751 + else if (b.length() == 0
1.752 +#ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING
1.753 + && !b.trees.begin()->value.id().to_long()
1.754 +#endif
1.755 + )
1.756 + {
1.757 + return;
1.758 + }
1.759 + a.concat(b);
1.760 + tree_policy_t::concat(a, b);
1.761 + }
1.762 +
1.763 + template <typename MatchT, typename IteratorT2>
1.764 + void
1.765 + group_match(
1.766 + MatchT& m,
1.767 + parser_id const& id,
1.768 + IteratorT2 const& first,
1.769 + IteratorT2 const& last) const
1.770 + {
1.771 + if (!m) return;
1.772 +
1.773 +#if defined(BOOST_SPIRIT_DEBUG) && \
1.774 + (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_TREES)
1.775 +
1.776 + BOOST_SPIRIT_DEBUG_OUT << "\n>>> group_match(begin) <<<\n"
1.777 + "new node(" << id << ") \"";
1.778 + for (IteratorT2 it = first; it != last; ++it)
1.779 + impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
1.780 + BOOST_SPIRIT_DEBUG_OUT << "\"\n";
1.781 + BOOST_SPIRIT_DEBUG_OUT << "new child tree (before grouping):\n" << m << "\n";
1.782 +
1.783 + tree_policy_t::group_match(m, id, first, last);
1.784 +
1.785 + BOOST_SPIRIT_DEBUG_OUT << "new child tree (after grouping):\n" << m << "\n";
1.786 + BOOST_SPIRIT_DEBUG_OUT << ">>> group_match(end) <<<\n\n";
1.787 +#else
1.788 + tree_policy_t::group_match(m, id, first, last);
1.789 +#endif
1.790 + }
1.791 +};
1.792 +
1.793 +//////////////////////////////////
1.794 +template <typename MatchPolicyT, typename NodeFactoryT>
1.795 +struct common_tree_tree_policy
1.796 +{
1.797 + typedef typename MatchPolicyT::iterator_t iterator_t;
1.798 + typedef typename MatchPolicyT::match_t match_t;
1.799 + typedef typename NodeFactoryT::template factory<iterator_t> factory_t;
1.800 + typedef typename factory_t::node_t node_t;
1.801 +
1.802 + template <typename Iterator1T, typename Iterator2T>
1.803 + static node_t
1.804 + create_node(std::size_t /*length*/, Iterator1T const& first,
1.805 + Iterator2T const& last, bool leaf_node)
1.806 + {
1.807 + return factory_t::create_node(first, last, leaf_node);
1.808 + }
1.809 +
1.810 + static node_t
1.811 + empty_node()
1.812 + {
1.813 + return factory_t::empty_node();
1.814 + }
1.815 +
1.816 + template <typename FunctorT>
1.817 + static void apply_op_to_match(FunctorT const& op, match_t& m)
1.818 + {
1.819 + op(m);
1.820 + }
1.821 +};
1.822 +
1.823 +//////////////////////////////////
1.824 +// directives to modify how the parse tree is generated
1.825 +
1.826 +struct no_tree_gen_node_parser_gen;
1.827 +
1.828 +template <typename T>
1.829 +struct no_tree_gen_node_parser
1.830 +: public unary<T, parser<no_tree_gen_node_parser<T> > >
1.831 +{
1.832 + typedef no_tree_gen_node_parser<T> self_t;
1.833 + typedef no_tree_gen_node_parser_gen parser_generator_t;
1.834 + typedef unary_parser_category parser_category_t;
1.835 +// typedef no_tree_gen_node_parser<T> const &embed_t;
1.836 +
1.837 + no_tree_gen_node_parser(T const& a)
1.838 + : unary<T, parser<no_tree_gen_node_parser<T> > >(a) {}
1.839 +
1.840 + template <typename ScannerT>
1.841 + typename parser_result<self_t, ScannerT>::type
1.842 + parse(ScannerT const& scanner) const
1.843 + {
1.844 + typedef typename ScannerT::iteration_policy_t iteration_policy_t;
1.845 + typedef match_policy match_policy_t;
1.846 + typedef typename ScannerT::action_policy_t action_policy_t;
1.847 + typedef scanner_policies<
1.848 + iteration_policy_t,
1.849 + match_policy_t,
1.850 + action_policy_t
1.851 + > policies_t;
1.852 +
1.853 + return this->subject().parse(scanner.change_policies(policies_t(scanner)));
1.854 + }
1.855 +};
1.856 +
1.857 +//////////////////////////////////
1.858 +struct no_tree_gen_node_parser_gen
1.859 +{
1.860 + template <typename T>
1.861 + struct result {
1.862 +
1.863 + typedef no_tree_gen_node_parser<T> type;
1.864 + };
1.865 +
1.866 + template <typename T>
1.867 + static no_tree_gen_node_parser<T>
1.868 + generate(parser<T> const& s)
1.869 + {
1.870 + return no_tree_gen_node_parser<T>(s.derived());
1.871 + }
1.872 +
1.873 + template <typename T>
1.874 + no_tree_gen_node_parser<T>
1.875 + operator[](parser<T> const& s) const
1.876 + {
1.877 + return no_tree_gen_node_parser<T>(s.derived());
1.878 + }
1.879 +};
1.880 +
1.881 +//////////////////////////////////
1.882 +const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen();
1.883 +
1.884 +
1.885 +//////////////////////////////////
1.886 +namespace impl {
1.887 +
1.888 + template <typename MatchPolicyT>
1.889 + struct tree_policy_selector
1.890 + {
1.891 + typedef tree_policy type;
1.892 + };
1.893 +
1.894 +} // namespace impl
1.895 +
1.896 +//////////////////////////////////
1.897 +template <typename NodeParserT>
1.898 +struct node_parser_gen;
1.899 +
1.900 +template <typename T, typename NodeParserT>
1.901 +struct node_parser
1.902 +: public unary<T, parser<node_parser<T, NodeParserT> > >
1.903 +{
1.904 + typedef node_parser<T, NodeParserT> self_t;
1.905 + typedef node_parser_gen<NodeParserT> parser_generator_t;
1.906 + typedef unary_parser_category parser_category_t;
1.907 +// typedef node_parser<T, NodeParserT> const &embed_t;
1.908 +
1.909 + node_parser(T const& a)
1.910 + : unary<T, parser<node_parser<T, NodeParserT> > >(a) {}
1.911 +
1.912 + template <typename ScannerT>
1.913 + typename parser_result<self_t, ScannerT>::type
1.914 + parse(ScannerT const& scanner) const
1.915 + {
1.916 + typename parser_result<self_t, ScannerT>::type hit = this->subject().parse(scanner);
1.917 + if (hit)
1.918 + {
1.919 + impl::tree_policy_selector<typename ScannerT::match_policy_t>::type::apply_op_to_match(NodeParserT(), hit);
1.920 + }
1.921 + return hit;
1.922 + }
1.923 +};
1.924 +
1.925 +//////////////////////////////////
1.926 +template <typename NodeParserT>
1.927 +struct node_parser_gen
1.928 +{
1.929 + template <typename T>
1.930 + struct result {
1.931 +
1.932 + typedef node_parser<T, NodeParserT> type;
1.933 + };
1.934 +
1.935 + template <typename T>
1.936 + static node_parser<T, NodeParserT>
1.937 + generate(parser<T> const& s)
1.938 + {
1.939 + return node_parser<T, NodeParserT>(s.derived());
1.940 + }
1.941 +
1.942 + template <typename T>
1.943 + node_parser<T, NodeParserT>
1.944 + operator[](parser<T> const& s) const
1.945 + {
1.946 + return node_parser<T, NodeParserT>(s.derived());
1.947 + }
1.948 +};
1.949 +
1.950 +struct discard_node_op
1.951 +{
1.952 + template <typename MatchT>
1.953 + void operator()(MatchT& m) const
1.954 + {
1.955 + m.trees.clear();
1.956 + }
1.957 +};
1.958 +
1.959 +const node_parser_gen<discard_node_op> discard_node_d =
1.960 + node_parser_gen<discard_node_op>();
1.961 +
1.962 +struct leaf_node_op
1.963 +{
1.964 + template <typename MatchT>
1.965 + void operator()(MatchT& m) const
1.966 + {
1.967 + if (m.trees.size() == 1)
1.968 + {
1.969 + m.trees.begin()->children.clear();
1.970 + }
1.971 + else if (m.trees.size() > 1)
1.972 + {
1.973 + typedef typename MatchT::node_factory_t node_factory_t;
1.974 + m = MatchT(m.length(), node_factory_t::group_nodes(m.trees));
1.975 + }
1.976 + }
1.977 +};
1.978 +
1.979 +const node_parser_gen<leaf_node_op> leaf_node_d =
1.980 + node_parser_gen<leaf_node_op>();
1.981 +const node_parser_gen<leaf_node_op> token_node_d =
1.982 + node_parser_gen<leaf_node_op>();
1.983 +
1.984 +struct infix_node_op
1.985 +{
1.986 + template <typename MatchT>
1.987 + void operator()(MatchT& m) const
1.988 + {
1.989 + typedef typename MatchT::container_t container_t;
1.990 + typedef typename MatchT::container_t::iterator iter_t;
1.991 + typedef typename MatchT::container_t::value_type value_t;
1.992 +
1.993 + using std::swap;
1.994 + using boost::swap;
1.995 + using boost::spirit::swap;
1.996 +
1.997 + // copying the tree nodes is expensive, since it may copy a whole
1.998 + // tree. swapping them is cheap, so swap the nodes we want into
1.999 + // a new container of children.
1.1000 + container_t new_children;
1.1001 + std::size_t length = 0;
1.1002 + std::size_t tree_size = m.trees.size();
1.1003 +
1.1004 + // the infix_node_d[] make no sense for nodes with no subnodes
1.1005 + BOOST_SPIRIT_ASSERT(tree_size >= 1);
1.1006 +
1.1007 + bool keep = true;
1.1008 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.1009 + new_children.reserve((tree_size+1)/2);
1.1010 +#endif
1.1011 + iter_t i_end = m.trees.end();
1.1012 + for (iter_t i = m.trees.begin(); i != i_end; ++i)
1.1013 + {
1.1014 + if (keep) {
1.1015 + // adjust the length
1.1016 + length += std::distance((*i).value.begin(), (*i).value.end());
1.1017 +
1.1018 + // move the child node
1.1019 + new_children.push_back(value_t());
1.1020 + swap(new_children.back(), *i);
1.1021 + keep = false;
1.1022 + }
1.1023 + else {
1.1024 + // ignore this child node
1.1025 + keep = true;
1.1026 + }
1.1027 + }
1.1028 +
1.1029 + m = MatchT(length, new_children);
1.1030 + }
1.1031 +};
1.1032 +
1.1033 +const node_parser_gen<infix_node_op> infix_node_d =
1.1034 + node_parser_gen<infix_node_op>();
1.1035 +
1.1036 +struct discard_first_node_op
1.1037 +{
1.1038 + template <typename MatchT>
1.1039 + void operator()(MatchT& m) const
1.1040 + {
1.1041 + typedef typename MatchT::container_t container_t;
1.1042 + typedef typename MatchT::container_t::iterator iter_t;
1.1043 + typedef typename MatchT::container_t::value_type value_t;
1.1044 +
1.1045 + using std::swap;
1.1046 + using boost::swap;
1.1047 + using boost::spirit::swap;
1.1048 +
1.1049 + // copying the tree nodes is expensive, since it may copy a whole
1.1050 + // tree. swapping them is cheap, so swap the nodes we want into
1.1051 + // a new container of children, instead of saying
1.1052 + // m.trees.erase(m.trees.begin()) because, on a container_t that will
1.1053 + // cause all the nodes afterwards to be copied into the previous
1.1054 + // position.
1.1055 + container_t new_children;
1.1056 + std::size_t length = 0;
1.1057 + std::size_t tree_size = m.trees.size();
1.1058 +
1.1059 + // the discard_first_node_d[] make no sense for nodes with no subnodes
1.1060 + BOOST_SPIRIT_ASSERT(tree_size >= 1);
1.1061 +
1.1062 + if (tree_size > 1) {
1.1063 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.1064 + new_children.reserve(tree_size - 1);
1.1065 +#endif
1.1066 + iter_t i = m.trees.begin(), i_end = m.trees.end();
1.1067 + for (++i; i != i_end; ++i)
1.1068 + {
1.1069 + // adjust the length
1.1070 + length += std::distance((*i).value.begin(), (*i).value.end());
1.1071 +
1.1072 + // move the child node
1.1073 + new_children.push_back(value_t());
1.1074 + swap(new_children.back(), *i);
1.1075 + }
1.1076 + }
1.1077 + else {
1.1078 + // if there was a tree and now there isn't any, insert an empty node
1.1079 + iter_t i = m.trees.begin();
1.1080 +
1.1081 + // This isn't entirely correct, since the empty node will reference
1.1082 + // the end of the discarded node, but I currently don't see any way to
1.1083 + // get at the begin of the node following this subnode.
1.1084 + // This should be safe anyway because the it shouldn't get dereferenced
1.1085 + // under any circumstances.
1.1086 + typedef typename value_t::parse_node_t::iterator_t iterator_type;
1.1087 + iterator_type it = (*i).value.end();
1.1088 +
1.1089 + new_children.push_back(
1.1090 + value_t(typename value_t::parse_node_t(it, it)));
1.1091 + }
1.1092 +
1.1093 + m = MatchT(length, new_children);
1.1094 + }
1.1095 +};
1.1096 +
1.1097 +const node_parser_gen<discard_first_node_op> discard_first_node_d =
1.1098 + node_parser_gen<discard_first_node_op>();
1.1099 +
1.1100 +struct discard_last_node_op
1.1101 +{
1.1102 + template <typename MatchT>
1.1103 + void operator()(MatchT& m) const
1.1104 + {
1.1105 + typedef typename MatchT::container_t container_t;
1.1106 + typedef typename MatchT::container_t::iterator iter_t;
1.1107 + typedef typename MatchT::container_t::value_type value_t;
1.1108 +
1.1109 + using std::swap;
1.1110 + using boost::swap;
1.1111 + using boost::spirit::swap;
1.1112 +
1.1113 + // copying the tree nodes is expensive, since it may copy a whole
1.1114 + // tree. swapping them is cheap, so swap the nodes we want into
1.1115 + // a new container of children, instead of saying
1.1116 + // m.trees.erase(m.trees.begin()) because, on a container_t that will
1.1117 + // cause all the nodes afterwards to be copied into the previous
1.1118 + // position.
1.1119 + container_t new_children;
1.1120 + std::size_t length = 0;
1.1121 + std::size_t tree_size = m.trees.size();
1.1122 +
1.1123 + // the discard_last_node_d[] make no sense for nodes with no subnodes
1.1124 + BOOST_SPIRIT_ASSERT(tree_size >= 1);
1.1125 +
1.1126 + if (tree_size > 1) {
1.1127 + m.trees.pop_back();
1.1128 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.1129 + new_children.reserve(tree_size - 1);
1.1130 +#endif
1.1131 + iter_t i_end = m.trees.end();
1.1132 + for (iter_t i = m.trees.begin(); i != i_end; ++i)
1.1133 + {
1.1134 + // adjust the length
1.1135 + length += std::distance((*i).value.begin(), (*i).value.end());
1.1136 +
1.1137 + // move the child node
1.1138 + new_children.push_back(value_t());
1.1139 + swap(new_children.back(), *i);
1.1140 + }
1.1141 + }
1.1142 + else {
1.1143 + // if there was a tree and now there isn't any, insert an empty node
1.1144 + iter_t i = m.trees.begin();
1.1145 +
1.1146 + typedef typename value_t::parse_node_t::iterator_t iterator_type;
1.1147 + iterator_type it = (*i).value.begin();
1.1148 +
1.1149 + new_children.push_back(
1.1150 + value_t(typename value_t::parse_node_t(it, it)));
1.1151 + }
1.1152 +
1.1153 + m = MatchT(length, new_children);
1.1154 + }
1.1155 +};
1.1156 +
1.1157 +const node_parser_gen<discard_last_node_op> discard_last_node_d =
1.1158 + node_parser_gen<discard_last_node_op>();
1.1159 +
1.1160 +struct inner_node_op
1.1161 +{
1.1162 + template <typename MatchT>
1.1163 + void operator()(MatchT& m) const
1.1164 + {
1.1165 + typedef typename MatchT::container_t container_t;
1.1166 + typedef typename MatchT::container_t::iterator iter_t;
1.1167 + typedef typename MatchT::container_t::value_type value_t;
1.1168 +
1.1169 + using std::swap;
1.1170 + using boost::swap;
1.1171 + using boost::spirit::swap;
1.1172 +
1.1173 + // copying the tree nodes is expensive, since it may copy a whole
1.1174 + // tree. swapping them is cheap, so swap the nodes we want into
1.1175 + // a new container of children, instead of saying
1.1176 + // m.trees.erase(m.trees.begin()) because, on a container_t that will
1.1177 + // cause all the nodes afterwards to be copied into the previous
1.1178 + // position.
1.1179 + container_t new_children;
1.1180 + std::size_t length = 0;
1.1181 + std::size_t tree_size = m.trees.size();
1.1182 +
1.1183 + // the inner_node_d[] make no sense for nodes with less then 2 subnodes
1.1184 + BOOST_SPIRIT_ASSERT(tree_size >= 2);
1.1185 +
1.1186 + if (tree_size > 2) {
1.1187 + m.trees.pop_back(); // erase the last element
1.1188 +#if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
1.1189 + new_children.reserve(tree_size - 1);
1.1190 +#endif
1.1191 + iter_t i = m.trees.begin(); // skip over the first element
1.1192 + iter_t i_end = m.trees.end();
1.1193 + for (++i; i != i_end; ++i)
1.1194 + {
1.1195 + // adjust the length
1.1196 + length += std::distance((*i).value.begin(), (*i).value.end());
1.1197 +
1.1198 + // move the child node
1.1199 + new_children.push_back(value_t());
1.1200 + swap(new_children.back(), *i);
1.1201 + }
1.1202 + }
1.1203 + else {
1.1204 + // if there was a tree and now there isn't any, insert an empty node
1.1205 + iter_t i = m.trees.begin(); // skip over the first element
1.1206 +
1.1207 + typedef typename value_t::parse_node_t::iterator_t iterator_type;
1.1208 + iterator_type it = (*++i).value.begin();
1.1209 +
1.1210 + new_children.push_back(
1.1211 + value_t(typename value_t::parse_node_t(it, it)));
1.1212 + }
1.1213 +
1.1214 + m = MatchT(length, new_children);
1.1215 + }
1.1216 +};
1.1217 +
1.1218 +const node_parser_gen<inner_node_op> inner_node_d =
1.1219 + node_parser_gen<inner_node_op>();
1.1220 +
1.1221 +
1.1222 +//////////////////////////////////
1.1223 +// action_directive_parser and action_directive_parser_gen
1.1224 +// are meant to be used as a template to create directives that
1.1225 +// generate action classes. For example access_match and
1.1226 +// access_node. The ActionParserT template parameter must be
1.1227 +// a class that has an innter class called action that is templated
1.1228 +// on the parser type and the action type.
1.1229 +template <typename ActionParserT>
1.1230 +struct action_directive_parser_gen;
1.1231 +
1.1232 +template <typename T, typename ActionParserT>
1.1233 +struct action_directive_parser
1.1234 +: public unary<T, parser<action_directive_parser<T, ActionParserT> > >
1.1235 +{
1.1236 + typedef action_directive_parser<T, ActionParserT> self_t;
1.1237 + typedef action_directive_parser_gen<ActionParserT> parser_generator_t;
1.1238 + typedef unary_parser_category parser_category_t;
1.1239 +// typedef action_directive_parser<T, ActionParserT> const &embed_t;
1.1240 +
1.1241 + action_directive_parser(T const& a)
1.1242 + : unary<T, parser<action_directive_parser<T, ActionParserT> > >(a) {}
1.1243 +
1.1244 + template <typename ScannerT>
1.1245 + typename parser_result<self_t, ScannerT>::type
1.1246 + parse(ScannerT const& scanner) const
1.1247 + {
1.1248 + return this->subject().parse(scanner);
1.1249 + }
1.1250 +
1.1251 + template <typename ActionT>
1.1252 + typename ActionParserT::template action<action_directive_parser<T, ActionParserT>, ActionT>
1.1253 + operator[](ActionT const& actor) const
1.1254 + {
1.1255 + typedef typename
1.1256 + ActionParserT::template action<action_directive_parser, ActionT>
1.1257 + action_t;
1.1258 + return action_t(*this, actor);
1.1259 + }
1.1260 +};
1.1261 +
1.1262 +//////////////////////////////////
1.1263 +template <typename ActionParserT>
1.1264 +struct action_directive_parser_gen
1.1265 +{
1.1266 + template <typename T>
1.1267 + struct result {
1.1268 +
1.1269 + typedef action_directive_parser<T, ActionParserT> type;
1.1270 + };
1.1271 +
1.1272 + template <typename T>
1.1273 + static action_directive_parser<T, ActionParserT>
1.1274 + generate(parser<T> const& s)
1.1275 + {
1.1276 + return action_directive_parser<T, ActionParserT>(s.derived());
1.1277 + }
1.1278 +
1.1279 + template <typename T>
1.1280 + action_directive_parser<T, ActionParserT>
1.1281 + operator[](parser<T> const& s) const
1.1282 + {
1.1283 + return action_directive_parser<T, ActionParserT>(s.derived());
1.1284 + }
1.1285 +};
1.1286 +
1.1287 +//////////////////////////////////
1.1288 +// Calls the attached action passing it the match from the parser
1.1289 +// and the first and last iterators.
1.1290 +// The inner template class is used to simulate template-template parameters
1.1291 +// (declared in common_fwd.hpp).
1.1292 +template <typename ParserT, typename ActionT>
1.1293 +struct access_match_action::action
1.1294 +: public unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >
1.1295 +{
1.1296 + typedef action_parser_category parser_category;
1.1297 + typedef action<ParserT, ActionT> self_t;
1.1298 +
1.1299 + action( ParserT const& subject,
1.1300 + ActionT const& actor_);
1.1301 +
1.1302 + template <typename ScannerT>
1.1303 + typename parser_result<self_t, ScannerT>::type
1.1304 + parse(ScannerT const& scanner) const;
1.1305 +
1.1306 + ActionT const &predicate() const;
1.1307 +
1.1308 + private:
1.1309 + ActionT actor;
1.1310 +};
1.1311 +
1.1312 +//////////////////////////////////
1.1313 +template <typename ParserT, typename ActionT>
1.1314 +access_match_action::action<ParserT, ActionT>::action(
1.1315 + ParserT const& subject,
1.1316 + ActionT const& actor_)
1.1317 +: unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >(subject)
1.1318 +, actor(actor_)
1.1319 +{}
1.1320 +
1.1321 +//////////////////////////////////
1.1322 +template <typename ParserT, typename ActionT>
1.1323 +template <typename ScannerT>
1.1324 +typename parser_result<access_match_action::action<ParserT, ActionT>, ScannerT>::type
1.1325 +access_match_action::action<ParserT, ActionT>::
1.1326 +parse(ScannerT const& scan) const
1.1327 +{
1.1328 + typedef typename ScannerT::iterator_t iterator_t;
1.1329 + typedef typename parser_result<self_t, ScannerT>::type result_t;
1.1330 + if (!scan.at_end())
1.1331 + {
1.1332 + iterator_t save = scan.first;
1.1333 + result_t hit = this->subject().parse(scan);
1.1334 + actor(hit, save, scan.first);
1.1335 + return hit;
1.1336 + }
1.1337 + return scan.no_match();
1.1338 +}
1.1339 +
1.1340 +//////////////////////////////////
1.1341 +template <typename ParserT, typename ActionT>
1.1342 +ActionT const &access_match_action::action<ParserT, ActionT>::predicate() const
1.1343 +{
1.1344 + return actor;
1.1345 +}
1.1346 +
1.1347 +//////////////////////////////////
1.1348 +const action_directive_parser_gen<access_match_action> access_match_d
1.1349 + = action_directive_parser_gen<access_match_action>();
1.1350 +
1.1351 +
1.1352 +
1.1353 +//////////////////////////////////
1.1354 +// Calls the attached action passing it the node from the parser
1.1355 +// and the first and last iterators
1.1356 +// The inner template class is used to simulate template-template parameters
1.1357 +// (declared in common_fwd.hpp).
1.1358 +template <typename ParserT, typename ActionT>
1.1359 +struct access_node_action::action
1.1360 +: public unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >
1.1361 +{
1.1362 + typedef action_parser_category parser_category;
1.1363 + typedef action<ParserT, ActionT> self_t;
1.1364 +
1.1365 + action( ParserT const& subject,
1.1366 + ActionT const& actor_);
1.1367 +
1.1368 + template <typename ScannerT>
1.1369 + typename parser_result<self_t, ScannerT>::type
1.1370 + parse(ScannerT const& scanner) const;
1.1371 +
1.1372 + ActionT const &predicate() const;
1.1373 +
1.1374 + private:
1.1375 + ActionT actor;
1.1376 +};
1.1377 +
1.1378 +//////////////////////////////////
1.1379 +template <typename ParserT, typename ActionT>
1.1380 +access_node_action::action<ParserT, ActionT>::action(
1.1381 + ParserT const& subject,
1.1382 + ActionT const& actor_)
1.1383 +: unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >(subject)
1.1384 +, actor(actor_)
1.1385 +{}
1.1386 +
1.1387 +//////////////////////////////////
1.1388 +template <typename ParserT, typename ActionT>
1.1389 +template <typename ScannerT>
1.1390 +typename parser_result<access_node_action::action<ParserT, ActionT>, ScannerT>::type
1.1391 +access_node_action::action<ParserT, ActionT>::
1.1392 +parse(ScannerT const& scan) const
1.1393 +{
1.1394 + typedef typename ScannerT::iterator_t iterator_t;
1.1395 + typedef typename parser_result<self_t, ScannerT>::type result_t;
1.1396 + if (!scan.at_end())
1.1397 + {
1.1398 + iterator_t save = scan.first;
1.1399 + result_t hit = this->subject().parse(scan);
1.1400 + if (hit && hit.trees.size() > 0)
1.1401 + actor(*hit.trees.begin(), save, scan.first);
1.1402 + return hit;
1.1403 + }
1.1404 + return scan.no_match();
1.1405 +}
1.1406 +
1.1407 +//////////////////////////////////
1.1408 +template <typename ParserT, typename ActionT>
1.1409 +ActionT const &access_node_action::action<ParserT, ActionT>::predicate() const
1.1410 +{
1.1411 + return actor;
1.1412 +}
1.1413 +
1.1414 +//////////////////////////////////
1.1415 +const action_directive_parser_gen<access_node_action> access_node_d
1.1416 + = action_directive_parser_gen<access_node_action>();
1.1417 +
1.1418 +
1.1419 +
1.1420 +//////////////////////////////////
1.1421 +
1.1422 +///////////////////////////////////////////////////////////////////////////////
1.1423 +//
1.1424 +// tree_parse_info
1.1425 +//
1.1426 +// Results returned by the tree parse functions:
1.1427 +//
1.1428 +// stop: points to the final parse position (i.e parsing
1.1429 +// processed the input up to this point).
1.1430 +//
1.1431 +// match: true if parsing is successful. This may be full:
1.1432 +// the parser consumed all the input, or partial:
1.1433 +// the parser consumed only a portion of the input.
1.1434 +//
1.1435 +// full: true when we have a full match (i.e the parser
1.1436 +// consumed all the input.
1.1437 +//
1.1438 +// length: The number of characters consumed by the parser.
1.1439 +// This is valid only if we have a successful match
1.1440 +// (either partial or full). A negative value means
1.1441 +// that the match is unsucessful.
1.1442 +//
1.1443 +// trees: Contains the root node(s) of the tree.
1.1444 +//
1.1445 +///////////////////////////////////////////////////////////////////////////////
1.1446 +template <
1.1447 + typename IteratorT,
1.1448 + typename NodeFactoryT,
1.1449 + typename T
1.1450 +>
1.1451 +struct tree_parse_info
1.1452 +{
1.1453 + IteratorT stop;
1.1454 + bool match;
1.1455 + bool full;
1.1456 + std::size_t length;
1.1457 + typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees;
1.1458 +
1.1459 + tree_parse_info()
1.1460 + : stop()
1.1461 + , match(false)
1.1462 + , full(false)
1.1463 + , length(0)
1.1464 + , trees()
1.1465 + {}
1.1466 +
1.1467 + template <typename IteratorT2>
1.1468 + tree_parse_info(tree_parse_info<IteratorT2> const& pi)
1.1469 + : stop(pi.stop)
1.1470 + , match(pi.match)
1.1471 + , full(pi.full)
1.1472 + , length(pi.length)
1.1473 + , trees()
1.1474 + {
1.1475 + using std::swap;
1.1476 + using boost::swap;
1.1477 + using boost::spirit::swap;
1.1478 +
1.1479 + // use auto_ptr like ownership for the trees data member
1.1480 + swap(trees, pi.trees);
1.1481 + }
1.1482 +
1.1483 + tree_parse_info(
1.1484 + IteratorT stop_,
1.1485 + bool match_,
1.1486 + bool full_,
1.1487 + std::size_t length_,
1.1488 + typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees_)
1.1489 + : stop(stop_)
1.1490 + , match(match_)
1.1491 + , full(full_)
1.1492 + , length(length_)
1.1493 + , trees()
1.1494 + {
1.1495 + using std::swap;
1.1496 + using boost::swap;
1.1497 + using boost::spirit::swap;
1.1498 +
1.1499 + // use auto_ptr like ownership for the trees data member
1.1500 + swap(trees, trees_);
1.1501 + }
1.1502 +};
1.1503 +
1.1504 +}} // namespace boost::spirit
1.1505 +
1.1506 +#endif
1.1507 +