annotate DEPENDENCIES/generic/include/boost/spirit/home/classic/tree/common.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 /*=============================================================================
Chris@16 2 Copyright (c) 2001-2003 Daniel Nuffer
Chris@16 3 Copyright (c) 2001-2007 Hartmut Kaiser
Chris@16 4 Revised 2007, Copyright (c) Tobias Schwinger
Chris@16 5 http://spirit.sourceforge.net/
Chris@16 6
Chris@16 7 Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 =============================================================================*/
Chris@16 10 #ifndef BOOST_SPIRIT_TREE_COMMON_HPP
Chris@16 11 #define BOOST_SPIRIT_TREE_COMMON_HPP
Chris@16 12
Chris@16 13 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 14 #include <vector>
Chris@16 15 #else
Chris@16 16 #include <list>
Chris@16 17 #endif
Chris@16 18
Chris@16 19 #if defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
Chris@16 20 #include <boost/pool/pool_alloc.hpp>
Chris@16 21 #endif
Chris@16 22
Chris@16 23 #include <algorithm>
Chris@16 24
Chris@16 25 #include <boost/ref.hpp>
Chris@16 26 #include <boost/call_traits.hpp>
Chris@16 27 #include <boost/spirit/home/classic/namespace.hpp>
Chris@16 28 #include <boost/spirit/home/classic/core.hpp>
Chris@16 29 #include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
Chris@16 30 #include <boost/assert.hpp>
Chris@16 31
Chris@16 32 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 33 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 34 #include <iostream>
Chris@16 35 #include <boost/spirit/home/classic/debug/debug_node.hpp>
Chris@16 36 #endif
Chris@16 37
Chris@16 38 #include <boost/spirit/home/classic/tree/common_fwd.hpp>
Chris@16 39
Chris@16 40 namespace boost { namespace spirit {
Chris@16 41
Chris@16 42 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
Chris@16 43
Chris@16 44 template <typename T>
Chris@16 45 void swap(tree_node<T>& a, tree_node<T>& b);
Chris@16 46
Chris@16 47 template <typename T, typename V>
Chris@16 48 void swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b);
Chris@16 49
Chris@16 50 namespace impl {
Chris@16 51 template <typename T>
Chris@16 52 inline void cp_swap(T& t1, T& t2);
Chris@16 53 }
Chris@16 54
Chris@16 55 template <typename T>
Chris@16 56 struct tree_node
Chris@16 57 {
Chris@16 58 typedef T parse_node_t;
Chris@16 59
Chris@16 60 #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
Chris@16 61 typedef std::allocator<tree_node<T> > allocator_type;
Chris@16 62 #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 63 typedef boost::pool_allocator<tree_node<T> > allocator_type;
Chris@16 64 #else
Chris@16 65 typedef boost::fast_pool_allocator<tree_node<T> > allocator_type;
Chris@16 66 #endif
Chris@16 67
Chris@16 68 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 69 typedef std::vector<tree_node<T>, allocator_type> children_t;
Chris@16 70 #else
Chris@16 71 typedef std::list<tree_node<T>, allocator_type> children_t;
Chris@16 72 #endif // BOOST_SPIRIT_USE_LIST_FOR_TREES
Chris@16 73
Chris@16 74 typedef typename children_t::iterator tree_iterator;
Chris@16 75 typedef typename children_t::const_iterator const_tree_iterator;
Chris@16 76
Chris@16 77 T value;
Chris@16 78 children_t children;
Chris@16 79
Chris@16 80 tree_node()
Chris@16 81 : value()
Chris@16 82 , children()
Chris@16 83 {}
Chris@16 84
Chris@16 85 explicit tree_node(T const& v)
Chris@16 86 : value(v)
Chris@16 87 , children()
Chris@16 88 {}
Chris@16 89
Chris@16 90 tree_node(T const& v, children_t const& c)
Chris@16 91 : value(v)
Chris@16 92 , children(c)
Chris@16 93 {}
Chris@16 94
Chris@16 95 void swap(tree_node<T>& x)
Chris@16 96 {
Chris@16 97 impl::cp_swap(value, x.value);
Chris@16 98 impl::cp_swap(children, x.children);
Chris@16 99 }
Chris@16 100
Chris@16 101 // Intel V5.0.1 has a problem without this explicit operator=
Chris@16 102 tree_node &operator= (tree_node const &rhs)
Chris@16 103 {
Chris@16 104 tree_node(rhs).swap(*this);
Chris@16 105 return *this;
Chris@16 106 }
Chris@16 107 };
Chris@16 108
Chris@16 109 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 110 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 111 template <typename T>
Chris@16 112 inline std::ostream&
Chris@16 113 operator<<(std::ostream& o, tree_node<T> const& n)
Chris@16 114 {
Chris@16 115 static int depth = 0;
Chris@16 116 o << "\n";
Chris@16 117 for (int i = 0; i <= depth; ++i)
Chris@16 118 {
Chris@16 119 o << "\t";
Chris@16 120 }
Chris@16 121 o << "(depth = " << depth++ << " value = " << n.value;
Chris@16 122 int c = 0;
Chris@16 123 for (typename tree_node<T>::children_t::const_iterator it = n.children.begin();
Chris@16 124 it != n.children.end(); ++it)
Chris@16 125 {
Chris@16 126 o << " children[" << c++ << "] = " << *it;
Chris@16 127 }
Chris@16 128 o << ")";
Chris@16 129 --depth;
Chris@16 130 return o;
Chris@16 131 }
Chris@16 132 #endif
Chris@16 133
Chris@16 134 //////////////////////////////////
Chris@16 135 template <typename IteratorT, typename ValueT>
Chris@16 136 struct node_iter_data
Chris@16 137 {
Chris@16 138 typedef IteratorT iterator_t;
Chris@16 139 typedef IteratorT /*const*/ const_iterator_t;
Chris@16 140
Chris@16 141 node_iter_data()
Chris@16 142 : first(), last(), is_root_(false), parser_id_(), value_()
Chris@16 143 {}
Chris@16 144
Chris@16 145 node_iter_data(IteratorT const& _first, IteratorT const& _last)
Chris@16 146 : first(_first), last(_last), is_root_(false), parser_id_(), value_()
Chris@16 147 {}
Chris@16 148
Chris@16 149 void swap(node_iter_data& x)
Chris@16 150 {
Chris@16 151 impl::cp_swap(first, x.first);
Chris@16 152 impl::cp_swap(last, x.last);
Chris@16 153 impl::cp_swap(parser_id_, x.parser_id_);
Chris@16 154 impl::cp_swap(is_root_, x.is_root_);
Chris@16 155 impl::cp_swap(value_, x.value_);
Chris@16 156 }
Chris@16 157
Chris@16 158 IteratorT begin()
Chris@16 159 {
Chris@16 160 return first;
Chris@16 161 }
Chris@16 162
Chris@16 163 IteratorT const& begin() const
Chris@16 164 {
Chris@16 165 return first;
Chris@16 166 }
Chris@16 167
Chris@16 168 IteratorT end()
Chris@16 169 {
Chris@16 170 return last;
Chris@16 171 }
Chris@16 172
Chris@16 173 IteratorT const& end() const
Chris@16 174 {
Chris@16 175 return last;
Chris@16 176 }
Chris@16 177
Chris@16 178 bool is_root() const
Chris@16 179 {
Chris@16 180 return is_root_;
Chris@16 181 }
Chris@16 182
Chris@16 183 void is_root(bool b)
Chris@16 184 {
Chris@16 185 is_root_ = b;
Chris@16 186 }
Chris@16 187
Chris@16 188 parser_id id() const
Chris@16 189 {
Chris@16 190 return parser_id_;
Chris@16 191 }
Chris@16 192
Chris@16 193 void id(parser_id r)
Chris@16 194 {
Chris@16 195 parser_id_ = r;
Chris@16 196 }
Chris@16 197
Chris@16 198 ValueT const& value() const
Chris@16 199 {
Chris@16 200 return value_;
Chris@16 201 }
Chris@16 202
Chris@16 203 void value(ValueT const& v)
Chris@16 204 {
Chris@16 205 value_ = v;
Chris@16 206 }
Chris@16 207 private:
Chris@16 208 IteratorT first, last;
Chris@16 209 bool is_root_;
Chris@16 210 parser_id parser_id_;
Chris@16 211 ValueT value_;
Chris@16 212
Chris@16 213 public:
Chris@16 214 };
Chris@16 215
Chris@16 216 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 217 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 218 // value is default nil_t, so provide an operator<< for nil_t
Chris@16 219 inline std::ostream&
Chris@16 220 operator<<(std::ostream& o, nil_t const&)
Chris@16 221 {
Chris@16 222 return o;
Chris@16 223 }
Chris@16 224
Chris@16 225 template <typename IteratorT, typename ValueT>
Chris@16 226 inline std::ostream&
Chris@16 227 operator<<(std::ostream& o, node_iter_data<IteratorT, ValueT> const& n)
Chris@16 228 {
Chris@16 229 o << "(id = " << n.id() << " text = \"";
Chris@16 230 typedef typename node_iter_data<IteratorT, ValueT>::const_iterator_t
Chris@16 231 iterator_t;
Chris@16 232 for (iterator_t it = n.begin(); it != n.end(); ++it)
Chris@16 233 impl::token_printer(o, *it);
Chris@16 234 o << "\" is_root = " << n.is_root()
Chris@16 235 << /*" value = " << n.value() << */")";
Chris@16 236 return o;
Chris@16 237 }
Chris@16 238 #endif
Chris@16 239
Chris@16 240 //////////////////////////////////
Chris@16 241 template <typename IteratorT = char const*, typename ValueT = nil_t>
Chris@16 242 struct node_val_data
Chris@16 243 {
Chris@16 244 typedef
Chris@16 245 typename boost::detail::iterator_traits<IteratorT>::value_type
Chris@16 246 value_type;
Chris@16 247
Chris@16 248 #if !defined(BOOST_SPIRIT_USE_BOOST_ALLOCATOR_FOR_TREES)
Chris@16 249 typedef std::allocator<value_type> allocator_type;
Chris@16 250 #elif !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 251 typedef boost::pool_allocator<value_type> allocator_type;
Chris@16 252 #else
Chris@16 253 typedef boost::fast_pool_allocator<value_type> allocator_type;
Chris@16 254 #endif
Chris@16 255
Chris@16 256 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 257 typedef std::vector<value_type, allocator_type> container_t;
Chris@16 258 #else
Chris@16 259 typedef std::list<value_type, allocator_type> container_t;
Chris@16 260 #endif
Chris@16 261
Chris@16 262 typedef typename container_t::iterator iterator_t;
Chris@16 263 typedef typename container_t::const_iterator const_iterator_t;
Chris@16 264
Chris@16 265 node_val_data()
Chris@16 266 : text(), is_root_(false), parser_id_(), value_()
Chris@16 267 {}
Chris@16 268
Chris@16 269 #if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
Chris@16 270 node_val_data(IteratorT const& _first, IteratorT const& _last)
Chris@16 271 : text(), is_root_(false), parser_id_(), value_()
Chris@16 272 {
Chris@16 273 std::copy(_first, _last, std::inserter(text, text.end()));
Chris@16 274 }
Chris@16 275
Chris@16 276 // This constructor is for building text out of iterators
Chris@16 277 template <typename IteratorT2>
Chris@16 278 node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
Chris@16 279 : text(), is_root_(false), parser_id_(), value_()
Chris@16 280 {
Chris@16 281 std::copy(_first, _last, std::inserter(text, text.end()));
Chris@16 282 }
Chris@16 283 #else
Chris@16 284 node_val_data(IteratorT const& _first, IteratorT const& _last)
Chris@16 285 : text(_first, _last), is_root_(false), parser_id_(), value_()
Chris@16 286 {}
Chris@16 287
Chris@16 288 // This constructor is for building text out of iterators
Chris@16 289 template <typename IteratorT2>
Chris@16 290 node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
Chris@16 291 : text(_first, _last), is_root_(false), parser_id_(), value_()
Chris@16 292 {}
Chris@16 293 #endif
Chris@16 294
Chris@16 295 void swap(node_val_data& x)
Chris@16 296 {
Chris@16 297 impl::cp_swap(text, x.text);
Chris@16 298 impl::cp_swap(is_root_, x.is_root_);
Chris@16 299 impl::cp_swap(parser_id_, x.parser_id_);
Chris@16 300 impl::cp_swap(value_, x.value_);
Chris@16 301 }
Chris@16 302
Chris@16 303 typename container_t::iterator begin()
Chris@16 304 {
Chris@16 305 return text.begin();
Chris@16 306 }
Chris@16 307
Chris@16 308 typename container_t::const_iterator begin() const
Chris@16 309 {
Chris@16 310 return text.begin();
Chris@16 311 }
Chris@16 312
Chris@16 313 typename container_t::iterator end()
Chris@16 314 {
Chris@16 315 return text.end();
Chris@16 316 }
Chris@16 317
Chris@16 318 typename container_t::const_iterator end() const
Chris@16 319 {
Chris@16 320 return text.end();
Chris@16 321 }
Chris@16 322
Chris@16 323 bool is_root() const
Chris@16 324 {
Chris@16 325 return is_root_;
Chris@16 326 }
Chris@16 327
Chris@16 328 void is_root(bool b)
Chris@16 329 {
Chris@16 330 is_root_ = b;
Chris@16 331 }
Chris@16 332
Chris@16 333 parser_id id() const
Chris@16 334 {
Chris@16 335 return parser_id_;
Chris@16 336 }
Chris@16 337
Chris@16 338 void id(parser_id r)
Chris@16 339 {
Chris@16 340 parser_id_ = r;
Chris@16 341 }
Chris@16 342
Chris@16 343 ValueT const& value() const
Chris@16 344 {
Chris@16 345 return value_;
Chris@16 346 }
Chris@16 347
Chris@16 348 void value(ValueT const& v)
Chris@16 349 {
Chris@16 350 value_ = v;
Chris@16 351 }
Chris@16 352
Chris@16 353 private:
Chris@16 354 container_t text;
Chris@16 355 bool is_root_;
Chris@16 356 parser_id parser_id_;
Chris@16 357 ValueT value_;
Chris@16 358 };
Chris@16 359
Chris@16 360 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 361 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 362 template <typename IteratorT, typename ValueT>
Chris@16 363 inline std::ostream&
Chris@16 364 operator<<(std::ostream& o, node_val_data<IteratorT, ValueT> const& n)
Chris@16 365 {
Chris@16 366 o << "(id = " << n.id() << " text = \"";
Chris@16 367 typedef typename node_val_data<IteratorT, ValueT>::const_iterator_t
Chris@16 368 iterator_t;
Chris@16 369 for (iterator_t it = n.begin(); it != n.end(); ++it)
Chris@16 370 impl::token_printer(o, *it);
Chris@16 371 o << "\" is_root = " << n.is_root()
Chris@16 372 << " value = " << n.value() << ")";
Chris@16 373 return o;
Chris@16 374 }
Chris@16 375 #endif
Chris@16 376
Chris@16 377 template <typename T>
Chris@16 378 inline void
Chris@16 379 swap(tree_node<T>& a, tree_node<T>& b)
Chris@16 380 {
Chris@16 381 a.swap(b);
Chris@16 382 }
Chris@16 383
Chris@16 384 template <typename T, typename V>
Chris@16 385 inline void
Chris@16 386 swap(node_iter_data<T, V>& a, node_iter_data<T, V>& b)
Chris@16 387 {
Chris@16 388 a.swap(b);
Chris@16 389 }
Chris@16 390
Chris@16 391 //////////////////////////////////
Chris@16 392 template <typename ValueT>
Chris@16 393 class node_iter_data_factory
Chris@16 394 {
Chris@16 395 public:
Chris@16 396 // This inner class is so that node_iter_data_factory can simulate
Chris@16 397 // a template template parameter
Chris@16 398 template <typename IteratorT>
Chris@16 399 class factory
Chris@16 400 {
Chris@16 401 public:
Chris@16 402 typedef IteratorT iterator_t;
Chris@16 403 typedef node_iter_data<iterator_t, ValueT> node_t;
Chris@16 404
Chris@16 405 static node_t create_node(iterator_t const& first, iterator_t const& last,
Chris@16 406 bool /*is_leaf_node*/)
Chris@16 407 {
Chris@16 408 return node_t(first, last);
Chris@16 409 }
Chris@16 410
Chris@16 411 static node_t empty_node()
Chris@16 412 {
Chris@16 413 return node_t();
Chris@16 414 }
Chris@16 415
Chris@16 416 // precondition: ContainerT contains a tree_node<node_t>. And all
Chris@16 417 // iterators in the container point to the same sequence.
Chris@16 418 template <typename ContainerT>
Chris@16 419 static node_t group_nodes(ContainerT const& nodes)
Chris@16 420 {
Chris@16 421 return node_t(nodes.begin()->value.begin(),
Chris@16 422 nodes.back().value.end());
Chris@16 423 }
Chris@16 424 };
Chris@16 425 };
Chris@16 426
Chris@16 427 //////////////////////////////////
Chris@16 428 template <typename ValueT>
Chris@16 429 class node_val_data_factory
Chris@16 430 {
Chris@16 431 public:
Chris@16 432 // This inner class is so that node_val_data_factory can simulate
Chris@16 433 // a template template parameter
Chris@16 434 template <typename IteratorT>
Chris@16 435 class factory
Chris@16 436 {
Chris@16 437 public:
Chris@16 438 typedef IteratorT iterator_t;
Chris@16 439 typedef node_val_data<iterator_t, ValueT> node_t;
Chris@16 440
Chris@16 441 static node_t create_node(iterator_t const& first, iterator_t const& last,
Chris@16 442 bool is_leaf_node)
Chris@16 443 {
Chris@16 444 if (is_leaf_node)
Chris@16 445 return node_t(first, last);
Chris@16 446 else
Chris@16 447 return node_t();
Chris@16 448 }
Chris@16 449
Chris@16 450 static node_t empty_node()
Chris@16 451 {
Chris@16 452 return node_t();
Chris@16 453 }
Chris@16 454
Chris@16 455 template <typename ContainerT>
Chris@16 456 static node_t group_nodes(ContainerT const& nodes)
Chris@16 457 {
Chris@16 458 typename node_t::container_t c;
Chris@16 459 typename ContainerT::const_iterator i_end = nodes.end();
Chris@16 460 // copy all the nodes text into a new one
Chris@16 461 for (typename ContainerT::const_iterator i = nodes.begin();
Chris@16 462 i != i_end; ++i)
Chris@16 463 {
Chris@16 464 // See docs: reduced_node_d cannot be used with a
Chris@16 465 // rule inside the [].
Chris@16 466 BOOST_ASSERT(i->children.size() == 0);
Chris@16 467 c.insert(c.end(), i->value.begin(), i->value.end());
Chris@16 468 }
Chris@16 469 return node_t(c.begin(), c.end());
Chris@16 470 }
Chris@16 471 };
Chris@16 472 };
Chris@16 473
Chris@16 474 //////////////////////////////////
Chris@16 475 template <typename ValueT>
Chris@16 476 class node_all_val_data_factory
Chris@16 477 {
Chris@16 478 public:
Chris@16 479 // This inner class is so that node_all_val_data_factory can simulate
Chris@16 480 // a template template parameter
Chris@16 481 template <typename IteratorT>
Chris@16 482 class factory
Chris@16 483 {
Chris@16 484 public:
Chris@16 485 typedef IteratorT iterator_t;
Chris@16 486 typedef node_val_data<iterator_t, ValueT> node_t;
Chris@16 487
Chris@16 488 static node_t create_node(iterator_t const& first, iterator_t const& last,
Chris@16 489 bool /*is_leaf_node*/)
Chris@16 490 {
Chris@16 491 return node_t(first, last);
Chris@16 492 }
Chris@16 493
Chris@16 494 static node_t empty_node()
Chris@16 495 {
Chris@16 496 return node_t();
Chris@16 497 }
Chris@16 498
Chris@16 499 template <typename ContainerT>
Chris@16 500 static node_t group_nodes(ContainerT const& nodes)
Chris@16 501 {
Chris@16 502 typename node_t::container_t c;
Chris@16 503 typename ContainerT::const_iterator i_end = nodes.end();
Chris@16 504 // copy all the nodes text into a new one
Chris@16 505 for (typename ContainerT::const_iterator i = nodes.begin();
Chris@16 506 i != i_end; ++i)
Chris@16 507 {
Chris@16 508 BOOST_ASSERT(i->children.size() == 0);
Chris@16 509 c.insert(c.end(), i->value.begin(), i->value.end());
Chris@16 510 }
Chris@16 511 return node_t(c.begin(), c.end());
Chris@16 512 }
Chris@16 513 };
Chris@16 514 };
Chris@16 515
Chris@16 516 namespace impl {
Chris@16 517
Chris@16 518 ///////////////////////////////////////////////////////////////////////////
Chris@16 519 // can't call unqualified swap from within classname::swap
Chris@16 520 // as Koenig lookup rules will find only the classname::swap
Chris@16 521 // member function not the global declaration, so use cp_swap
Chris@16 522 // as a forwarding function (JM):
Chris@16 523 #if __GNUC__ == 2
Chris@16 524 using ::std::swap;
Chris@16 525 #endif
Chris@16 526 template <typename T>
Chris@16 527 inline void cp_swap(T& t1, T& t2)
Chris@16 528 {
Chris@16 529 using std::swap;
Chris@16 530 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 531 using boost::swap;
Chris@16 532 swap(t1, t2);
Chris@16 533 }
Chris@16 534 }
Chris@16 535
Chris@16 536 //////////////////////////////////
Chris@16 537 template <typename IteratorT, typename NodeFactoryT, typename T>
Chris@16 538 class tree_match : public match<T>
Chris@16 539 {
Chris@16 540 public:
Chris@16 541
Chris@16 542 typedef typename NodeFactoryT::template factory<IteratorT> node_factory_t;
Chris@16 543 typedef typename node_factory_t::node_t parse_node_t;
Chris@16 544 typedef tree_node<parse_node_t> node_t;
Chris@16 545 typedef typename node_t::children_t container_t;
Chris@16 546 typedef typename container_t::iterator tree_iterator;
Chris@16 547 typedef typename container_t::const_iterator const_tree_iterator;
Chris@16 548
Chris@16 549 typedef T attr_t;
Chris@16 550 typedef typename boost::call_traits<T>::param_type param_type;
Chris@16 551 typedef typename boost::call_traits<T>::reference reference;
Chris@16 552 typedef typename boost::call_traits<T>::const_reference const_reference;
Chris@16 553
Chris@16 554 tree_match()
Chris@16 555 : match<T>(), trees()
Chris@16 556 {}
Chris@16 557
Chris@16 558 explicit
Chris@16 559 tree_match(std::size_t length_)
Chris@16 560 : match<T>(length_), trees()
Chris@16 561 {}
Chris@16 562
Chris@16 563 tree_match(std::size_t length_, parse_node_t const& n)
Chris@16 564 : match<T>(length_), trees()
Chris@16 565 {
Chris@16 566 trees.push_back(node_t(n));
Chris@16 567 }
Chris@16 568
Chris@16 569 tree_match(std::size_t length_, param_type val, parse_node_t const& n)
Chris@16 570 : match<T>(length_, val), trees()
Chris@16 571 {
Chris@16 572 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 573 trees.reserve(10); // this is more or less an arbitrary number...
Chris@16 574 #endif
Chris@16 575 trees.push_back(node_t(n));
Chris@16 576 }
Chris@16 577
Chris@16 578 // attention, these constructors will change the second parameter!
Chris@16 579 tree_match(std::size_t length_, container_t& c)
Chris@16 580 : match<T>(length_), trees()
Chris@16 581 {
Chris@16 582 impl::cp_swap(trees, c);
Chris@16 583 }
Chris@16 584
Chris@16 585 tree_match(std::size_t length_, param_type val, container_t& c)
Chris@16 586 : match<T>(length_, val), trees()
Chris@16 587 {
Chris@16 588 impl::cp_swap(trees, c);
Chris@16 589 }
Chris@16 590
Chris@16 591 template <typename T2>
Chris@16 592 tree_match(match<T2> const& other)
Chris@16 593 : match<T>(other), trees()
Chris@16 594 {}
Chris@16 595
Chris@16 596 template <typename T2, typename T3, typename T4>
Chris@16 597 tree_match(tree_match<T2, T3, T4> const& other)
Chris@16 598 : match<T>(other), trees()
Chris@16 599 { impl::cp_swap(trees, other.trees); }
Chris@16 600
Chris@16 601 template <typename T2>
Chris@16 602 tree_match&
Chris@16 603 operator=(match<T2> const& other)
Chris@16 604 {
Chris@16 605 match<T>::operator=(other);
Chris@16 606 return *this;
Chris@16 607 }
Chris@16 608
Chris@16 609 template <typename T2, typename T3, typename T4>
Chris@16 610 tree_match&
Chris@16 611 operator=(tree_match<T2, T3, T4> const& other)
Chris@16 612 {
Chris@16 613 match<T>::operator=(other);
Chris@16 614 impl::cp_swap(trees, other.trees);
Chris@16 615 return *this;
Chris@16 616 }
Chris@16 617
Chris@16 618 tree_match(tree_match const& x)
Chris@16 619 : match<T>(x), trees()
Chris@16 620 {
Chris@16 621 // use auto_ptr like ownership for the trees data member
Chris@16 622 impl::cp_swap(trees, x.trees);
Chris@16 623 }
Chris@16 624
Chris@16 625 tree_match& operator=(tree_match const& x)
Chris@16 626 {
Chris@16 627 tree_match tmp(x);
Chris@16 628 this->swap(tmp);
Chris@16 629 return *this;
Chris@16 630 }
Chris@16 631
Chris@16 632 void swap(tree_match& x)
Chris@16 633 {
Chris@16 634 match<T>::swap(x);
Chris@16 635 impl::cp_swap(trees, x.trees);
Chris@16 636 }
Chris@16 637
Chris@16 638 mutable container_t trees;
Chris@16 639 };
Chris@16 640
Chris@16 641 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 642 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 643 template <typename IteratorT, typename NodeFactoryT, typename T>
Chris@16 644 inline std::ostream&
Chris@16 645 operator<<(std::ostream& o, tree_match<IteratorT, NodeFactoryT, T> const& m)
Chris@16 646 {
Chris@16 647 typedef
Chris@16 648 typename tree_match<IteratorT, NodeFactoryT, T>::container_t::iterator
Chris@16 649 iterator;
Chris@16 650
Chris@16 651 o << "(length = " << (int)m.length();
Chris@16 652 int c = 0;
Chris@16 653 for (iterator i = m.trees.begin(); i != m.trees.end(); ++i)
Chris@16 654 {
Chris@16 655 o << " trees[" << c++ << "] = " << *i;
Chris@16 656 }
Chris@16 657 o << "\n)";
Chris@16 658 return o;
Chris@16 659 }
Chris@16 660 #endif
Chris@16 661
Chris@16 662 //////////////////////////////////
Chris@16 663 struct tree_policy
Chris@16 664 {
Chris@16 665 template <typename FunctorT, typename MatchT>
Chris@16 666 static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/)
Chris@16 667 {}
Chris@16 668
Chris@16 669 template <typename MatchT, typename Iterator1T, typename Iterator2T>
Chris@16 670 static void group_match(MatchT& /*m*/, parser_id const& /*id*/,
Chris@16 671 Iterator1T const& /*first*/, Iterator2T const& /*last*/)
Chris@16 672 {}
Chris@16 673
Chris@16 674 template <typename MatchT>
Chris@16 675 static void concat(MatchT& /*a*/, MatchT const& /*b*/)
Chris@16 676 {}
Chris@16 677 };
Chris@16 678
Chris@16 679 //////////////////////////////////
Chris@16 680 template <
Chris@16 681 typename MatchPolicyT,
Chris@16 682 typename IteratorT,
Chris@16 683 typename NodeFactoryT,
Chris@16 684 typename TreePolicyT,
Chris@16 685 typename T
Chris@16 686 >
Chris@16 687 struct common_tree_match_policy : public match_policy
Chris@16 688 {
Chris@16 689 common_tree_match_policy()
Chris@16 690 {
Chris@16 691 }
Chris@16 692
Chris@16 693 template <typename PolicyT>
Chris@16 694 common_tree_match_policy(PolicyT const & policies)
Chris@16 695 : match_policy((match_policy const &)policies)
Chris@16 696 {
Chris@16 697 }
Chris@16 698
Chris@16 699 template <typename U>
Chris@16 700 struct result { typedef tree_match<IteratorT, NodeFactoryT, U> type; };
Chris@16 701
Chris@16 702 typedef tree_match<IteratorT, NodeFactoryT, T> match_t;
Chris@16 703 typedef IteratorT iterator_t;
Chris@16 704 typedef TreePolicyT tree_policy_t;
Chris@16 705 typedef NodeFactoryT factory_t;
Chris@16 706
Chris@16 707 static const match_t no_match() { return match_t(); }
Chris@16 708 static const match_t empty_match()
Chris@16 709 { return match_t(0, tree_policy_t::empty_node()); }
Chris@16 710
Chris@16 711 template <typename AttrT, typename Iterator1T, typename Iterator2T>
Chris@16 712 static tree_match<IteratorT, NodeFactoryT, AttrT> create_match(
Chris@16 713 std::size_t length,
Chris@16 714 AttrT const& val,
Chris@16 715 Iterator1T const& first,
Chris@16 716 Iterator2T const& last)
Chris@16 717 {
Chris@16 718 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 719 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 720
Chris@16 721 BOOST_SPIRIT_DEBUG_OUT << "\n>>> create_node(begin) <<<\n"
Chris@16 722 "creating node text: \"";
Chris@16 723 for (Iterator1T it = first; it != last; ++it)
Chris@16 724 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
Chris@16 725 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
Chris@16 726 BOOST_SPIRIT_DEBUG_OUT << ">>> create_node(end) <<<\n\n";
Chris@16 727 #endif
Chris@16 728 return tree_match<IteratorT, NodeFactoryT, AttrT>(length, val,
Chris@16 729 tree_policy_t::create_node(length, first, last, true));
Chris@16 730 }
Chris@16 731
Chris@16 732 template <typename Match1T, typename Match2T>
Chris@16 733 static void concat_match(Match1T& a, Match2T const& b)
Chris@16 734 {
Chris@16 735 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 736 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 737
Chris@16 738 BOOST_SPIRIT_DEBUG_OUT << "\n>>> concat_match(begin) <<<\n";
Chris@16 739 BOOST_SPIRIT_DEBUG_OUT << "tree a:\n" << a << "\n";
Chris@16 740 BOOST_SPIRIT_DEBUG_OUT << "tree b:\n" << b << "\n";
Chris@16 741 BOOST_SPIRIT_DEBUG_OUT << ">>> concat_match(end) <<<\n\n";
Chris@16 742 #endif
Chris@16 743 BOOST_SPIRIT_ASSERT(a && b);
Chris@16 744 if (a.length() == 0)
Chris@16 745 {
Chris@16 746 a = b;
Chris@16 747 return;
Chris@16 748 }
Chris@16 749 else if (b.length() == 0
Chris@16 750 #ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING
Chris@16 751 && !b.trees.begin()->value.id().to_long()
Chris@16 752 #endif
Chris@16 753 )
Chris@16 754 {
Chris@16 755 return;
Chris@16 756 }
Chris@16 757 a.concat(b);
Chris@16 758 tree_policy_t::concat(a, b);
Chris@16 759 }
Chris@16 760
Chris@16 761 template <typename MatchT, typename IteratorT2>
Chris@16 762 void
Chris@16 763 group_match(
Chris@16 764 MatchT& m,
Chris@16 765 parser_id const& id,
Chris@16 766 IteratorT2 const& first,
Chris@16 767 IteratorT2 const& last) const
Chris@16 768 {
Chris@16 769 if (!m) return;
Chris@16 770
Chris@16 771 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 772 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_TREES)
Chris@16 773
Chris@16 774 BOOST_SPIRIT_DEBUG_OUT << "\n>>> group_match(begin) <<<\n"
Chris@16 775 "new node(" << id << ") \"";
Chris@16 776 for (IteratorT2 it = first; it != last; ++it)
Chris@16 777 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
Chris@16 778 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
Chris@16 779 BOOST_SPIRIT_DEBUG_OUT << "new child tree (before grouping):\n" << m << "\n";
Chris@16 780
Chris@16 781 tree_policy_t::group_match(m, id, first, last);
Chris@16 782
Chris@16 783 BOOST_SPIRIT_DEBUG_OUT << "new child tree (after grouping):\n" << m << "\n";
Chris@16 784 BOOST_SPIRIT_DEBUG_OUT << ">>> group_match(end) <<<\n\n";
Chris@16 785 #else
Chris@16 786 tree_policy_t::group_match(m, id, first, last);
Chris@16 787 #endif
Chris@16 788 }
Chris@16 789 };
Chris@16 790
Chris@16 791 //////////////////////////////////
Chris@16 792 template <typename MatchPolicyT, typename NodeFactoryT>
Chris@16 793 struct common_tree_tree_policy
Chris@16 794 {
Chris@16 795 typedef typename MatchPolicyT::iterator_t iterator_t;
Chris@16 796 typedef typename MatchPolicyT::match_t match_t;
Chris@16 797 typedef typename NodeFactoryT::template factory<iterator_t> factory_t;
Chris@16 798 typedef typename factory_t::node_t node_t;
Chris@16 799
Chris@16 800 template <typename Iterator1T, typename Iterator2T>
Chris@16 801 static node_t
Chris@16 802 create_node(std::size_t /*length*/, Iterator1T const& first,
Chris@16 803 Iterator2T const& last, bool leaf_node)
Chris@16 804 {
Chris@16 805 return factory_t::create_node(first, last, leaf_node);
Chris@16 806 }
Chris@16 807
Chris@16 808 static node_t
Chris@16 809 empty_node()
Chris@16 810 {
Chris@16 811 return factory_t::empty_node();
Chris@16 812 }
Chris@16 813
Chris@16 814 template <typename FunctorT>
Chris@16 815 static void apply_op_to_match(FunctorT const& op, match_t& m)
Chris@16 816 {
Chris@16 817 op(m);
Chris@16 818 }
Chris@16 819 };
Chris@16 820
Chris@16 821 //////////////////////////////////
Chris@16 822 // directives to modify how the parse tree is generated
Chris@16 823
Chris@16 824 struct no_tree_gen_node_parser_gen;
Chris@16 825
Chris@16 826 template <typename T>
Chris@16 827 struct no_tree_gen_node_parser
Chris@16 828 : public unary<T, parser<no_tree_gen_node_parser<T> > >
Chris@16 829 {
Chris@16 830 typedef no_tree_gen_node_parser<T> self_t;
Chris@16 831 typedef no_tree_gen_node_parser_gen parser_generator_t;
Chris@16 832 typedef unary_parser_category parser_category_t;
Chris@16 833
Chris@16 834 no_tree_gen_node_parser(T const& a)
Chris@16 835 : unary<T, parser<no_tree_gen_node_parser<T> > >(a) {}
Chris@16 836
Chris@16 837 template <typename ScannerT>
Chris@16 838 typename parser_result<self_t, ScannerT>::type
Chris@16 839 parse(ScannerT const& scanner) const
Chris@16 840 {
Chris@16 841 typedef typename ScannerT::iteration_policy_t iteration_policy_t;
Chris@16 842 typedef match_policy match_policy_t;
Chris@16 843 typedef typename ScannerT::action_policy_t action_policy_t;
Chris@16 844 typedef scanner_policies<
Chris@16 845 iteration_policy_t,
Chris@16 846 match_policy_t,
Chris@16 847 action_policy_t
Chris@16 848 > policies_t;
Chris@16 849
Chris@16 850 return this->subject().parse(scanner.change_policies(policies_t(scanner)));
Chris@16 851 }
Chris@16 852 };
Chris@16 853
Chris@16 854 struct no_tree_gen_node_parser_gen
Chris@16 855 {
Chris@16 856 template <typename T>
Chris@16 857 struct result {
Chris@16 858
Chris@16 859 typedef no_tree_gen_node_parser<T> type;
Chris@16 860 };
Chris@16 861
Chris@16 862 template <typename T>
Chris@16 863 static no_tree_gen_node_parser<T>
Chris@16 864 generate(parser<T> const& s)
Chris@16 865 {
Chris@16 866 return no_tree_gen_node_parser<T>(s.derived());
Chris@16 867 }
Chris@16 868
Chris@16 869 template <typename T>
Chris@16 870 no_tree_gen_node_parser<T>
Chris@16 871 operator[](parser<T> const& s) const
Chris@16 872 {
Chris@16 873 return no_tree_gen_node_parser<T>(s.derived());
Chris@16 874 }
Chris@16 875 };
Chris@16 876
Chris@16 877 const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen();
Chris@16 878
Chris@16 879 //////////////////////////////////
Chris@16 880
Chris@16 881 struct leaf_node_parser_gen;
Chris@16 882
Chris@16 883 template<typename T>
Chris@16 884 struct leaf_node_parser
Chris@16 885 : public unary<T, parser<leaf_node_parser<T> > >
Chris@16 886 {
Chris@16 887 typedef leaf_node_parser<T> self_t;
Chris@16 888 typedef leaf_node_parser_gen parser_generator_t;
Chris@16 889 typedef unary_parser_category parser_category_t;
Chris@16 890
Chris@16 891 leaf_node_parser(T const& a)
Chris@16 892 : unary<T, parser<leaf_node_parser<T> > >(a) {}
Chris@16 893
Chris@16 894 template <typename ScannerT>
Chris@16 895 typename parser_result<self_t, ScannerT>::type
Chris@16 896 parse(ScannerT const& scanner) const
Chris@16 897 {
Chris@16 898 typedef scanner_policies< typename ScannerT::iteration_policy_t,
Chris@16 899 match_policy, typename ScannerT::action_policy_t > policies_t;
Chris@16 900
Chris@16 901 typedef typename ScannerT::iterator_t iterator_t;
Chris@16 902 typedef typename parser_result<self_t, ScannerT>::type result_t;
Chris@16 903 typedef typename result_t::node_factory_t factory_t;
Chris@16 904
Chris@16 905 iterator_t from = scanner.first;
Chris@16 906 result_t hit = impl::contiguous_parser_parse<result_t>(this->subject(),
Chris@16 907 scanner.change_policies(policies_t(scanner,match_policy(),scanner)),
Chris@16 908 scanner);
Chris@16 909
Chris@16 910 if (hit)
Chris@16 911 return result_t(hit.length(),
Chris@16 912 factory_t::create_node(from, scanner.first, true));
Chris@16 913 else
Chris@16 914 return result_t(hit.length());
Chris@16 915 }
Chris@16 916 };
Chris@16 917
Chris@16 918 struct leaf_node_parser_gen
Chris@16 919 {
Chris@16 920 template <typename T>
Chris@16 921 struct result {
Chris@16 922
Chris@16 923 typedef leaf_node_parser<T> type;
Chris@16 924 };
Chris@16 925
Chris@16 926 template <typename T>
Chris@16 927 static leaf_node_parser<T>
Chris@16 928 generate(parser<T> const& s)
Chris@16 929 {
Chris@16 930 return leaf_node_parser<T>(s.derived());
Chris@16 931 }
Chris@16 932
Chris@16 933 template <typename T>
Chris@16 934 leaf_node_parser<T>
Chris@16 935 operator[](parser<T> const& s) const
Chris@16 936 {
Chris@16 937 return leaf_node_parser<T>(s.derived());
Chris@16 938 }
Chris@16 939 };
Chris@16 940
Chris@16 941 const leaf_node_parser_gen leaf_node_d = leaf_node_parser_gen();
Chris@16 942 const leaf_node_parser_gen token_node_d = leaf_node_parser_gen();
Chris@16 943
Chris@16 944 //////////////////////////////////
Chris@16 945 namespace impl {
Chris@16 946
Chris@16 947 template <typename MatchPolicyT>
Chris@16 948 struct tree_policy_selector
Chris@16 949 {
Chris@16 950 typedef tree_policy type;
Chris@16 951 };
Chris@16 952
Chris@16 953 } // namespace impl
Chris@16 954
Chris@16 955 //////////////////////////////////
Chris@16 956 template <typename NodeParserT>
Chris@16 957 struct node_parser_gen;
Chris@16 958
Chris@16 959 template <typename T, typename NodeParserT>
Chris@16 960 struct node_parser
Chris@16 961 : public unary<T, parser<node_parser<T, NodeParserT> > >
Chris@16 962 {
Chris@16 963 typedef node_parser<T, NodeParserT> self_t;
Chris@16 964 typedef node_parser_gen<NodeParserT> parser_generator_t;
Chris@16 965 typedef unary_parser_category parser_category_t;
Chris@16 966
Chris@16 967 node_parser(T const& a)
Chris@16 968 : unary<T, parser<node_parser<T, NodeParserT> > >(a) {}
Chris@16 969
Chris@16 970 template <typename ScannerT>
Chris@16 971 struct result
Chris@16 972 {
Chris@16 973 typedef typename parser_result<T, ScannerT>::type type;
Chris@16 974 };
Chris@16 975
Chris@16 976 template <typename ScannerT>
Chris@16 977 typename parser_result<self_t, ScannerT>::type
Chris@16 978 parse(ScannerT const& scanner) const
Chris@16 979 {
Chris@16 980 typename parser_result<self_t, ScannerT>::type hit = this->subject().parse(scanner);
Chris@16 981 if (hit)
Chris@16 982 {
Chris@16 983 impl::tree_policy_selector<typename ScannerT::match_policy_t>::type::apply_op_to_match(NodeParserT(), hit);
Chris@16 984 }
Chris@16 985 return hit;
Chris@16 986 }
Chris@16 987 };
Chris@16 988
Chris@16 989 template <typename NodeParserT>
Chris@16 990 struct node_parser_gen
Chris@16 991 {
Chris@16 992 template <typename T>
Chris@16 993 struct result {
Chris@16 994
Chris@16 995 typedef node_parser<T, NodeParserT> type;
Chris@16 996 };
Chris@16 997
Chris@16 998 template <typename T>
Chris@16 999 static node_parser<T, NodeParserT>
Chris@16 1000 generate(parser<T> const& s)
Chris@16 1001 {
Chris@16 1002 return node_parser<T, NodeParserT>(s.derived());
Chris@16 1003 }
Chris@16 1004
Chris@16 1005 template <typename T>
Chris@16 1006 node_parser<T, NodeParserT>
Chris@16 1007 operator[](parser<T> const& s) const
Chris@16 1008 {
Chris@16 1009 return node_parser<T, NodeParserT>(s.derived());
Chris@16 1010 }
Chris@16 1011 };
Chris@16 1012 //////////////////////////////////
Chris@16 1013 struct reduced_node_op
Chris@16 1014 {
Chris@16 1015 template <typename MatchT>
Chris@16 1016 void operator()(MatchT& m) const
Chris@16 1017 {
Chris@16 1018 if (m.trees.size() == 1)
Chris@16 1019 {
Chris@16 1020 m.trees.begin()->children.clear();
Chris@16 1021 }
Chris@16 1022 else if (m.trees.size() > 1)
Chris@16 1023 {
Chris@16 1024 typedef typename MatchT::node_factory_t node_factory_t;
Chris@16 1025 m = MatchT(m.length(), node_factory_t::group_nodes(m.trees));
Chris@16 1026 }
Chris@16 1027 }
Chris@16 1028 };
Chris@16 1029
Chris@16 1030 const node_parser_gen<reduced_node_op> reduced_node_d =
Chris@16 1031 node_parser_gen<reduced_node_op>();
Chris@16 1032
Chris@16 1033
Chris@16 1034 struct discard_node_op
Chris@16 1035 {
Chris@16 1036 template <typename MatchT>
Chris@16 1037 void operator()(MatchT& m) const
Chris@16 1038 {
Chris@16 1039 m.trees.clear();
Chris@16 1040 }
Chris@16 1041 };
Chris@16 1042
Chris@16 1043 const node_parser_gen<discard_node_op> discard_node_d =
Chris@16 1044 node_parser_gen<discard_node_op>();
Chris@16 1045
Chris@16 1046 struct infix_node_op
Chris@16 1047 {
Chris@16 1048 template <typename MatchT>
Chris@16 1049 void operator()(MatchT& m) const
Chris@16 1050 {
Chris@16 1051 typedef typename MatchT::container_t container_t;
Chris@16 1052 typedef typename MatchT::container_t::iterator iter_t;
Chris@16 1053 typedef typename MatchT::container_t::value_type value_t;
Chris@16 1054
Chris@16 1055 using std::swap;
Chris@16 1056 using boost::swap;
Chris@16 1057 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1058
Chris@16 1059 // copying the tree nodes is expensive, since it may copy a whole
Chris@16 1060 // tree. swapping them is cheap, so swap the nodes we want into
Chris@16 1061 // a new container of children.
Chris@16 1062 container_t new_children;
Chris@16 1063 std::size_t length = 0;
Chris@16 1064 std::size_t tree_size = m.trees.size();
Chris@16 1065
Chris@16 1066 // the infix_node_d[] make no sense for nodes with no subnodes
Chris@16 1067 BOOST_SPIRIT_ASSERT(tree_size >= 1);
Chris@16 1068
Chris@16 1069 bool keep = true;
Chris@16 1070 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 1071 new_children.reserve((tree_size+1)/2);
Chris@16 1072 #endif
Chris@16 1073 iter_t i_end = m.trees.end();
Chris@16 1074 for (iter_t i = m.trees.begin(); i != i_end; ++i)
Chris@16 1075 {
Chris@16 1076 if (keep) {
Chris@16 1077 // adjust the length
Chris@16 1078 length += std::distance((*i).value.begin(), (*i).value.end());
Chris@16 1079
Chris@16 1080 // move the child node
Chris@16 1081 new_children.push_back(value_t());
Chris@16 1082 swap(new_children.back(), *i);
Chris@16 1083 keep = false;
Chris@16 1084 }
Chris@16 1085 else {
Chris@16 1086 // ignore this child node
Chris@16 1087 keep = true;
Chris@16 1088 }
Chris@16 1089 }
Chris@16 1090
Chris@16 1091 m = MatchT(length, new_children);
Chris@16 1092 }
Chris@16 1093 };
Chris@16 1094
Chris@16 1095 const node_parser_gen<infix_node_op> infix_node_d =
Chris@16 1096 node_parser_gen<infix_node_op>();
Chris@16 1097
Chris@16 1098 struct discard_first_node_op
Chris@16 1099 {
Chris@16 1100 template <typename MatchT>
Chris@16 1101 void operator()(MatchT& m) const
Chris@16 1102 {
Chris@16 1103 typedef typename MatchT::container_t container_t;
Chris@16 1104 typedef typename MatchT::container_t::iterator iter_t;
Chris@16 1105 typedef typename MatchT::container_t::value_type value_t;
Chris@16 1106
Chris@16 1107 using std::swap;
Chris@16 1108 using boost::swap;
Chris@16 1109 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1110
Chris@16 1111 // copying the tree nodes is expensive, since it may copy a whole
Chris@16 1112 // tree. swapping them is cheap, so swap the nodes we want into
Chris@16 1113 // a new container of children, instead of saying
Chris@16 1114 // m.trees.erase(m.trees.begin()) because, on a container_t that will
Chris@16 1115 // cause all the nodes afterwards to be copied into the previous
Chris@16 1116 // position.
Chris@16 1117 container_t new_children;
Chris@16 1118 std::size_t length = 0;
Chris@16 1119 std::size_t tree_size = m.trees.size();
Chris@16 1120
Chris@16 1121 // the discard_first_node_d[] make no sense for nodes with no subnodes
Chris@16 1122 BOOST_SPIRIT_ASSERT(tree_size >= 1);
Chris@16 1123
Chris@16 1124 if (tree_size > 1) {
Chris@16 1125 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 1126 new_children.reserve(tree_size - 1);
Chris@16 1127 #endif
Chris@16 1128 iter_t i = m.trees.begin(), i_end = m.trees.end();
Chris@16 1129 for (++i; i != i_end; ++i)
Chris@16 1130 {
Chris@16 1131 // adjust the length
Chris@16 1132 length += std::distance((*i).value.begin(), (*i).value.end());
Chris@16 1133
Chris@16 1134 // move the child node
Chris@16 1135 new_children.push_back(value_t());
Chris@16 1136 swap(new_children.back(), *i);
Chris@16 1137 }
Chris@16 1138 }
Chris@16 1139 else {
Chris@16 1140 // if there was a tree and now there isn't any, insert an empty node
Chris@16 1141 iter_t i = m.trees.begin();
Chris@16 1142
Chris@16 1143 // This isn't entirely correct, since the empty node will reference
Chris@16 1144 // the end of the discarded node, but I currently don't see any way to
Chris@16 1145 // get at the begin of the node following this subnode.
Chris@16 1146 // This should be safe anyway because the it shouldn't get dereferenced
Chris@16 1147 // under any circumstances.
Chris@16 1148 typedef typename value_t::parse_node_t::iterator_t iterator_type;
Chris@16 1149 iterator_type it = (*i).value.end();
Chris@16 1150
Chris@16 1151 new_children.push_back(
Chris@16 1152 value_t(typename value_t::parse_node_t(it, it)));
Chris@16 1153 }
Chris@16 1154
Chris@16 1155 m = MatchT(length, new_children);
Chris@16 1156 }
Chris@16 1157 };
Chris@16 1158
Chris@16 1159 const node_parser_gen<discard_first_node_op> discard_first_node_d =
Chris@16 1160 node_parser_gen<discard_first_node_op>();
Chris@16 1161
Chris@16 1162 struct discard_last_node_op
Chris@16 1163 {
Chris@16 1164 template <typename MatchT>
Chris@16 1165 void operator()(MatchT& m) const
Chris@16 1166 {
Chris@16 1167 typedef typename MatchT::container_t container_t;
Chris@16 1168 typedef typename MatchT::container_t::iterator iter_t;
Chris@16 1169 typedef typename MatchT::container_t::value_type value_t;
Chris@16 1170
Chris@16 1171 using std::swap;
Chris@16 1172 using boost::swap;
Chris@16 1173 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1174
Chris@16 1175 // copying the tree nodes is expensive, since it may copy a whole
Chris@16 1176 // tree. swapping them is cheap, so swap the nodes we want into
Chris@16 1177 // a new container of children, instead of saying
Chris@16 1178 // m.trees.erase(m.trees.begin()) because, on a container_t that will
Chris@16 1179 // cause all the nodes afterwards to be copied into the previous
Chris@16 1180 // position.
Chris@16 1181 container_t new_children;
Chris@16 1182 std::size_t length = 0;
Chris@16 1183 std::size_t tree_size = m.trees.size();
Chris@16 1184
Chris@16 1185 // the discard_last_node_d[] make no sense for nodes with no subnodes
Chris@16 1186 BOOST_SPIRIT_ASSERT(tree_size >= 1);
Chris@16 1187
Chris@16 1188 if (tree_size > 1) {
Chris@16 1189 m.trees.pop_back();
Chris@16 1190 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 1191 new_children.reserve(tree_size - 1);
Chris@16 1192 #endif
Chris@16 1193 iter_t i_end = m.trees.end();
Chris@16 1194 for (iter_t i = m.trees.begin(); i != i_end; ++i)
Chris@16 1195 {
Chris@16 1196 // adjust the length
Chris@16 1197 length += std::distance((*i).value.begin(), (*i).value.end());
Chris@16 1198
Chris@16 1199 // move the child node
Chris@16 1200 new_children.push_back(value_t());
Chris@16 1201 swap(new_children.back(), *i);
Chris@16 1202 }
Chris@16 1203 }
Chris@16 1204 else {
Chris@16 1205 // if there was a tree and now there isn't any, insert an empty node
Chris@16 1206 iter_t i = m.trees.begin();
Chris@16 1207
Chris@16 1208 typedef typename value_t::parse_node_t::iterator_t iterator_type;
Chris@16 1209 iterator_type it = (*i).value.begin();
Chris@16 1210
Chris@16 1211 new_children.push_back(
Chris@16 1212 value_t(typename value_t::parse_node_t(it, it)));
Chris@16 1213 }
Chris@16 1214
Chris@16 1215 m = MatchT(length, new_children);
Chris@16 1216 }
Chris@16 1217 };
Chris@16 1218
Chris@16 1219 const node_parser_gen<discard_last_node_op> discard_last_node_d =
Chris@16 1220 node_parser_gen<discard_last_node_op>();
Chris@16 1221
Chris@16 1222 struct inner_node_op
Chris@16 1223 {
Chris@16 1224 template <typename MatchT>
Chris@16 1225 void operator()(MatchT& m) const
Chris@16 1226 {
Chris@16 1227 typedef typename MatchT::container_t container_t;
Chris@16 1228 typedef typename MatchT::container_t::iterator iter_t;
Chris@16 1229 typedef typename MatchT::container_t::value_type value_t;
Chris@16 1230
Chris@16 1231 using std::swap;
Chris@16 1232 using boost::swap;
Chris@16 1233 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1234
Chris@16 1235 // copying the tree nodes is expensive, since it may copy a whole
Chris@16 1236 // tree. swapping them is cheap, so swap the nodes we want into
Chris@16 1237 // a new container of children, instead of saying
Chris@16 1238 // m.trees.erase(m.trees.begin()) because, on a container_t that will
Chris@16 1239 // cause all the nodes afterwards to be copied into the previous
Chris@16 1240 // position.
Chris@16 1241 container_t new_children;
Chris@16 1242 std::size_t length = 0;
Chris@16 1243 std::size_t tree_size = m.trees.size();
Chris@16 1244
Chris@16 1245 // the inner_node_d[] make no sense for nodes with less then 2 subnodes
Chris@16 1246 BOOST_SPIRIT_ASSERT(tree_size >= 2);
Chris@16 1247
Chris@16 1248 if (tree_size > 2) {
Chris@16 1249 m.trees.pop_back(); // erase the last element
Chris@16 1250 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 1251 new_children.reserve(tree_size - 1);
Chris@16 1252 #endif
Chris@16 1253 iter_t i = m.trees.begin(); // skip over the first element
Chris@16 1254 iter_t i_end = m.trees.end();
Chris@16 1255 for (++i; i != i_end; ++i)
Chris@16 1256 {
Chris@16 1257 // adjust the length
Chris@16 1258 length += std::distance((*i).value.begin(), (*i).value.end());
Chris@16 1259
Chris@16 1260 // move the child node
Chris@16 1261 new_children.push_back(value_t());
Chris@16 1262 swap(new_children.back(), *i);
Chris@16 1263 }
Chris@16 1264 }
Chris@16 1265 else {
Chris@16 1266 // if there was a tree and now there isn't any, insert an empty node
Chris@16 1267 iter_t i = m.trees.begin(); // skip over the first element
Chris@16 1268
Chris@16 1269 typedef typename value_t::parse_node_t::iterator_t iterator_type;
Chris@16 1270 iterator_type it = (*++i).value.begin();
Chris@16 1271
Chris@16 1272 new_children.push_back(
Chris@16 1273 value_t(typename value_t::parse_node_t(it, it)));
Chris@16 1274 }
Chris@16 1275
Chris@16 1276 m = MatchT(length, new_children);
Chris@16 1277 }
Chris@16 1278 };
Chris@16 1279
Chris@16 1280 const node_parser_gen<inner_node_op> inner_node_d =
Chris@16 1281 node_parser_gen<inner_node_op>();
Chris@16 1282
Chris@16 1283
Chris@16 1284 //////////////////////////////////
Chris@16 1285 // action_directive_parser and action_directive_parser_gen
Chris@16 1286 // are meant to be used as a template to create directives that
Chris@16 1287 // generate action classes. For example access_match and
Chris@16 1288 // access_node. The ActionParserT template parameter must be
Chris@16 1289 // a class that has an innter class called action that is templated
Chris@16 1290 // on the parser type and the action type.
Chris@16 1291 template <typename ActionParserT>
Chris@16 1292 struct action_directive_parser_gen;
Chris@16 1293
Chris@16 1294 template <typename T, typename ActionParserT>
Chris@16 1295 struct action_directive_parser
Chris@16 1296 : public unary<T, parser<action_directive_parser<T, ActionParserT> > >
Chris@16 1297 {
Chris@16 1298 typedef action_directive_parser<T, ActionParserT> self_t;
Chris@16 1299 typedef action_directive_parser_gen<ActionParserT> parser_generator_t;
Chris@16 1300 typedef unary_parser_category parser_category_t;
Chris@16 1301
Chris@16 1302 action_directive_parser(T const& a)
Chris@16 1303 : unary<T, parser<action_directive_parser<T, ActionParserT> > >(a) {}
Chris@16 1304
Chris@16 1305 template <typename ScannerT>
Chris@16 1306 struct result
Chris@16 1307 {
Chris@16 1308 typedef typename parser_result<T, ScannerT>::type type;
Chris@16 1309 };
Chris@16 1310
Chris@16 1311 template <typename ScannerT>
Chris@16 1312 typename parser_result<self_t, ScannerT>::type
Chris@16 1313 parse(ScannerT const& scanner) const
Chris@16 1314 {
Chris@16 1315 return this->subject().parse(scanner);
Chris@16 1316 }
Chris@16 1317
Chris@16 1318 template <typename ActionT>
Chris@16 1319 typename ActionParserT::template action<action_directive_parser<T, ActionParserT>, ActionT>
Chris@16 1320 operator[](ActionT const& actor) const
Chris@16 1321 {
Chris@16 1322 typedef typename
Chris@16 1323 ActionParserT::template action<action_directive_parser, ActionT>
Chris@16 1324 action_t;
Chris@16 1325 return action_t(*this, actor);
Chris@16 1326 }
Chris@16 1327 };
Chris@16 1328
Chris@16 1329 //////////////////////////////////
Chris@16 1330 template <typename ActionParserT>
Chris@16 1331 struct action_directive_parser_gen
Chris@16 1332 {
Chris@16 1333 template <typename T>
Chris@16 1334 struct result {
Chris@16 1335
Chris@16 1336 typedef action_directive_parser<T, ActionParserT> type;
Chris@16 1337 };
Chris@16 1338
Chris@16 1339 template <typename T>
Chris@16 1340 static action_directive_parser<T, ActionParserT>
Chris@16 1341 generate(parser<T> const& s)
Chris@16 1342 {
Chris@16 1343 return action_directive_parser<T, ActionParserT>(s.derived());
Chris@16 1344 }
Chris@16 1345
Chris@16 1346 template <typename T>
Chris@16 1347 action_directive_parser<T, ActionParserT>
Chris@16 1348 operator[](parser<T> const& s) const
Chris@16 1349 {
Chris@16 1350 return action_directive_parser<T, ActionParserT>(s.derived());
Chris@16 1351 }
Chris@16 1352 };
Chris@16 1353
Chris@16 1354 //////////////////////////////////
Chris@16 1355 // Calls the attached action passing it the match from the parser
Chris@16 1356 // and the first and last iterators.
Chris@16 1357 // The inner template class is used to simulate template-template parameters
Chris@16 1358 // (declared in common_fwd.hpp).
Chris@16 1359 template <typename ParserT, typename ActionT>
Chris@16 1360 struct access_match_action::action
Chris@16 1361 : public unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >
Chris@16 1362 {
Chris@16 1363 typedef action_parser_category parser_category;
Chris@16 1364 typedef action<ParserT, ActionT> self_t;
Chris@16 1365
Chris@16 1366 template <typename ScannerT>
Chris@16 1367 struct result
Chris@16 1368 {
Chris@16 1369 typedef typename parser_result<ParserT, ScannerT>::type type;
Chris@16 1370 };
Chris@16 1371
Chris@16 1372 action( ParserT const& subject,
Chris@16 1373 ActionT const& actor_);
Chris@16 1374
Chris@16 1375 template <typename ScannerT>
Chris@16 1376 typename parser_result<self_t, ScannerT>::type
Chris@16 1377 parse(ScannerT const& scanner) const;
Chris@16 1378
Chris@16 1379 ActionT const &predicate() const;
Chris@16 1380
Chris@16 1381 private:
Chris@16 1382 ActionT actor;
Chris@16 1383 };
Chris@16 1384
Chris@16 1385 //////////////////////////////////
Chris@16 1386 template <typename ParserT, typename ActionT>
Chris@16 1387 access_match_action::action<ParserT, ActionT>::action(
Chris@16 1388 ParserT const& subject,
Chris@16 1389 ActionT const& actor_)
Chris@16 1390 : unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >(subject)
Chris@16 1391 , actor(actor_)
Chris@16 1392 {}
Chris@16 1393
Chris@16 1394 //////////////////////////////////
Chris@16 1395 template <typename ParserT, typename ActionT>
Chris@16 1396 template <typename ScannerT>
Chris@16 1397 typename parser_result<access_match_action::action<ParserT, ActionT>, ScannerT>::type
Chris@16 1398 access_match_action::action<ParserT, ActionT>::
Chris@16 1399 parse(ScannerT const& scan) const
Chris@16 1400 {
Chris@16 1401 typedef typename ScannerT::iterator_t iterator_t;
Chris@16 1402 typedef typename parser_result<self_t, ScannerT>::type result_t;
Chris@16 1403 if (!scan.at_end())
Chris@16 1404 {
Chris@16 1405 iterator_t save = scan.first;
Chris@16 1406 result_t hit = this->subject().parse(scan);
Chris@16 1407 actor(hit, save, scan.first);
Chris@16 1408 return hit;
Chris@16 1409 }
Chris@16 1410 return scan.no_match();
Chris@16 1411 }
Chris@16 1412
Chris@16 1413 //////////////////////////////////
Chris@16 1414 template <typename ParserT, typename ActionT>
Chris@16 1415 ActionT const &access_match_action::action<ParserT, ActionT>::predicate() const
Chris@16 1416 {
Chris@16 1417 return actor;
Chris@16 1418 }
Chris@16 1419
Chris@16 1420 //////////////////////////////////
Chris@16 1421 const action_directive_parser_gen<access_match_action> access_match_d
Chris@16 1422 = action_directive_parser_gen<access_match_action>();
Chris@16 1423
Chris@16 1424
Chris@16 1425
Chris@16 1426 //////////////////////////////////
Chris@16 1427 // Calls the attached action passing it the node from the parser
Chris@16 1428 // and the first and last iterators
Chris@16 1429 // The inner template class is used to simulate template-template parameters
Chris@16 1430 // (declared in common_fwd.hpp).
Chris@16 1431 template <typename ParserT, typename ActionT>
Chris@16 1432 struct access_node_action::action
Chris@16 1433 : public unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >
Chris@16 1434 {
Chris@16 1435 typedef action_parser_category parser_category;
Chris@16 1436 typedef action<ParserT, ActionT> self_t;
Chris@16 1437
Chris@16 1438 template <typename ScannerT>
Chris@16 1439 struct result
Chris@16 1440 {
Chris@16 1441 typedef typename parser_result<ParserT, ScannerT>::type type;
Chris@16 1442 };
Chris@16 1443
Chris@16 1444 action( ParserT const& subject,
Chris@16 1445 ActionT const& actor_);
Chris@16 1446
Chris@16 1447 template <typename ScannerT>
Chris@16 1448 typename parser_result<self_t, ScannerT>::type
Chris@16 1449 parse(ScannerT const& scanner) const;
Chris@16 1450
Chris@16 1451 ActionT const &predicate() const;
Chris@16 1452
Chris@16 1453 private:
Chris@16 1454 ActionT actor;
Chris@16 1455 };
Chris@16 1456
Chris@16 1457 //////////////////////////////////
Chris@16 1458 template <typename ParserT, typename ActionT>
Chris@16 1459 access_node_action::action<ParserT, ActionT>::action(
Chris@16 1460 ParserT const& subject,
Chris@16 1461 ActionT const& actor_)
Chris@16 1462 : unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >(subject)
Chris@16 1463 , actor(actor_)
Chris@16 1464 {}
Chris@16 1465
Chris@16 1466 //////////////////////////////////
Chris@16 1467 template <typename ParserT, typename ActionT>
Chris@16 1468 template <typename ScannerT>
Chris@16 1469 typename parser_result<access_node_action::action<ParserT, ActionT>, ScannerT>::type
Chris@16 1470 access_node_action::action<ParserT, ActionT>::
Chris@16 1471 parse(ScannerT const& scan) const
Chris@16 1472 {
Chris@16 1473 typedef typename ScannerT::iterator_t iterator_t;
Chris@16 1474 typedef typename parser_result<self_t, ScannerT>::type result_t;
Chris@16 1475 if (!scan.at_end())
Chris@16 1476 {
Chris@16 1477 iterator_t save = scan.first;
Chris@16 1478 result_t hit = this->subject().parse(scan);
Chris@16 1479 if (hit && hit.trees.size() > 0)
Chris@16 1480 actor(*hit.trees.begin(), save, scan.first);
Chris@16 1481 return hit;
Chris@16 1482 }
Chris@16 1483 return scan.no_match();
Chris@16 1484 }
Chris@16 1485
Chris@16 1486 //////////////////////////////////
Chris@16 1487 template <typename ParserT, typename ActionT>
Chris@16 1488 ActionT const &access_node_action::action<ParserT, ActionT>::predicate() const
Chris@16 1489 {
Chris@16 1490 return actor;
Chris@16 1491 }
Chris@16 1492
Chris@16 1493 //////////////////////////////////
Chris@16 1494 const action_directive_parser_gen<access_node_action> access_node_d
Chris@16 1495 = action_directive_parser_gen<access_node_action>();
Chris@16 1496
Chris@16 1497
Chris@16 1498
Chris@16 1499 //////////////////////////////////
Chris@16 1500
Chris@16 1501 ///////////////////////////////////////////////////////////////////////////////
Chris@16 1502 //
Chris@16 1503 // tree_parse_info
Chris@16 1504 //
Chris@16 1505 // Results returned by the tree parse functions:
Chris@16 1506 //
Chris@16 1507 // stop: points to the final parse position (i.e parsing
Chris@16 1508 // processed the input up to this point).
Chris@16 1509 //
Chris@16 1510 // match: true if parsing is successful. This may be full:
Chris@16 1511 // the parser consumed all the input, or partial:
Chris@16 1512 // the parser consumed only a portion of the input.
Chris@16 1513 //
Chris@16 1514 // full: true when we have a full match (i.e the parser
Chris@16 1515 // consumed all the input.
Chris@16 1516 //
Chris@16 1517 // length: The number of characters consumed by the parser.
Chris@16 1518 // This is valid only if we have a successful match
Chris@16 1519 // (either partial or full). A negative value means
Chris@16 1520 // that the match is unsucessful.
Chris@16 1521 //
Chris@16 1522 // trees: Contains the root node(s) of the tree.
Chris@16 1523 //
Chris@16 1524 ///////////////////////////////////////////////////////////////////////////////
Chris@16 1525 template <
Chris@16 1526 typename IteratorT,
Chris@16 1527 typename NodeFactoryT,
Chris@16 1528 typename T
Chris@16 1529 >
Chris@16 1530 struct tree_parse_info
Chris@16 1531 {
Chris@16 1532 IteratorT stop;
Chris@16 1533 bool match;
Chris@16 1534 bool full;
Chris@16 1535 std::size_t length;
Chris@16 1536 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees;
Chris@16 1537
Chris@16 1538 tree_parse_info()
Chris@16 1539 : stop()
Chris@16 1540 , match(false)
Chris@16 1541 , full(false)
Chris@16 1542 , length(0)
Chris@16 1543 , trees()
Chris@16 1544 {}
Chris@16 1545
Chris@16 1546 template <typename IteratorT2>
Chris@16 1547 tree_parse_info(tree_parse_info<IteratorT2> const& pi)
Chris@16 1548 : stop(pi.stop)
Chris@16 1549 , match(pi.match)
Chris@16 1550 , full(pi.full)
Chris@16 1551 , length(pi.length)
Chris@16 1552 , trees()
Chris@16 1553 {
Chris@16 1554 using std::swap;
Chris@16 1555 using boost::swap;
Chris@16 1556 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1557
Chris@16 1558 // use auto_ptr like ownership for the trees data member
Chris@16 1559 swap(trees, pi.trees);
Chris@16 1560 }
Chris@16 1561
Chris@16 1562 tree_parse_info(
Chris@16 1563 IteratorT stop_,
Chris@16 1564 bool match_,
Chris@16 1565 bool full_,
Chris@16 1566 std::size_t length_,
Chris@16 1567 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees_)
Chris@16 1568 : stop(stop_)
Chris@16 1569 , match(match_)
Chris@16 1570 , full(full_)
Chris@16 1571 , length(length_)
Chris@16 1572 , trees()
Chris@16 1573 {
Chris@16 1574 using std::swap;
Chris@16 1575 using boost::swap;
Chris@16 1576 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1577
Chris@16 1578 // use auto_ptr like ownership for the trees data member
Chris@16 1579 swap(trees, trees_);
Chris@16 1580 }
Chris@16 1581 };
Chris@16 1582
Chris@16 1583 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
Chris@16 1584
Chris@16 1585 }} // namespace BOOST_SPIRIT_CLASSIC_NS
Chris@16 1586
Chris@16 1587 #endif
Chris@16 1588