annotate DEPENDENCIES/generic/include/boost/spirit/home/classic/tree/common.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
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 template <typename T>
Chris@16 524 inline void cp_swap(T& t1, T& t2)
Chris@16 525 {
Chris@16 526 using std::swap;
Chris@16 527 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 528 using boost::swap;
Chris@16 529 swap(t1, t2);
Chris@16 530 }
Chris@16 531 }
Chris@16 532
Chris@16 533 //////////////////////////////////
Chris@16 534 template <typename IteratorT, typename NodeFactoryT, typename T>
Chris@16 535 class tree_match : public match<T>
Chris@16 536 {
Chris@16 537 public:
Chris@16 538
Chris@16 539 typedef typename NodeFactoryT::template factory<IteratorT> node_factory_t;
Chris@16 540 typedef typename node_factory_t::node_t parse_node_t;
Chris@16 541 typedef tree_node<parse_node_t> node_t;
Chris@16 542 typedef typename node_t::children_t container_t;
Chris@16 543 typedef typename container_t::iterator tree_iterator;
Chris@16 544 typedef typename container_t::const_iterator const_tree_iterator;
Chris@16 545
Chris@16 546 typedef T attr_t;
Chris@16 547 typedef typename boost::call_traits<T>::param_type param_type;
Chris@16 548 typedef typename boost::call_traits<T>::reference reference;
Chris@16 549 typedef typename boost::call_traits<T>::const_reference const_reference;
Chris@16 550
Chris@16 551 tree_match()
Chris@16 552 : match<T>(), trees()
Chris@16 553 {}
Chris@16 554
Chris@16 555 explicit
Chris@16 556 tree_match(std::size_t length_)
Chris@16 557 : match<T>(length_), trees()
Chris@16 558 {}
Chris@16 559
Chris@16 560 tree_match(std::size_t length_, parse_node_t const& n)
Chris@16 561 : match<T>(length_), trees()
Chris@16 562 {
Chris@16 563 trees.push_back(node_t(n));
Chris@16 564 }
Chris@16 565
Chris@16 566 tree_match(std::size_t length_, param_type val, parse_node_t const& n)
Chris@16 567 : match<T>(length_, val), trees()
Chris@16 568 {
Chris@16 569 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 570 trees.reserve(10); // this is more or less an arbitrary number...
Chris@16 571 #endif
Chris@16 572 trees.push_back(node_t(n));
Chris@16 573 }
Chris@16 574
Chris@16 575 // attention, these constructors will change the second parameter!
Chris@16 576 tree_match(std::size_t length_, container_t& c)
Chris@16 577 : match<T>(length_), trees()
Chris@16 578 {
Chris@16 579 impl::cp_swap(trees, c);
Chris@16 580 }
Chris@16 581
Chris@16 582 tree_match(std::size_t length_, param_type val, container_t& c)
Chris@16 583 : match<T>(length_, val), trees()
Chris@16 584 {
Chris@16 585 impl::cp_swap(trees, c);
Chris@16 586 }
Chris@16 587
Chris@16 588 template <typename T2>
Chris@16 589 tree_match(match<T2> const& other)
Chris@16 590 : match<T>(other), trees()
Chris@16 591 {}
Chris@16 592
Chris@16 593 template <typename T2, typename T3, typename T4>
Chris@16 594 tree_match(tree_match<T2, T3, T4> const& other)
Chris@16 595 : match<T>(other), trees()
Chris@16 596 { impl::cp_swap(trees, other.trees); }
Chris@16 597
Chris@16 598 template <typename T2>
Chris@16 599 tree_match&
Chris@16 600 operator=(match<T2> const& other)
Chris@16 601 {
Chris@16 602 match<T>::operator=(other);
Chris@16 603 return *this;
Chris@16 604 }
Chris@16 605
Chris@16 606 template <typename T2, typename T3, typename T4>
Chris@16 607 tree_match&
Chris@16 608 operator=(tree_match<T2, T3, T4> const& other)
Chris@16 609 {
Chris@16 610 match<T>::operator=(other);
Chris@16 611 impl::cp_swap(trees, other.trees);
Chris@16 612 return *this;
Chris@16 613 }
Chris@16 614
Chris@16 615 tree_match(tree_match const& x)
Chris@16 616 : match<T>(x), trees()
Chris@16 617 {
Chris@16 618 // use auto_ptr like ownership for the trees data member
Chris@16 619 impl::cp_swap(trees, x.trees);
Chris@16 620 }
Chris@16 621
Chris@16 622 tree_match& operator=(tree_match const& x)
Chris@16 623 {
Chris@16 624 tree_match tmp(x);
Chris@16 625 this->swap(tmp);
Chris@16 626 return *this;
Chris@16 627 }
Chris@16 628
Chris@16 629 void swap(tree_match& x)
Chris@16 630 {
Chris@16 631 match<T>::swap(x);
Chris@16 632 impl::cp_swap(trees, x.trees);
Chris@16 633 }
Chris@16 634
Chris@16 635 mutable container_t trees;
Chris@16 636 };
Chris@16 637
Chris@16 638 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 639 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 640 template <typename IteratorT, typename NodeFactoryT, typename T>
Chris@16 641 inline std::ostream&
Chris@16 642 operator<<(std::ostream& o, tree_match<IteratorT, NodeFactoryT, T> const& m)
Chris@16 643 {
Chris@16 644 typedef
Chris@16 645 typename tree_match<IteratorT, NodeFactoryT, T>::container_t::iterator
Chris@16 646 iterator;
Chris@16 647
Chris@16 648 o << "(length = " << (int)m.length();
Chris@16 649 int c = 0;
Chris@16 650 for (iterator i = m.trees.begin(); i != m.trees.end(); ++i)
Chris@16 651 {
Chris@16 652 o << " trees[" << c++ << "] = " << *i;
Chris@16 653 }
Chris@16 654 o << "\n)";
Chris@16 655 return o;
Chris@16 656 }
Chris@16 657 #endif
Chris@16 658
Chris@16 659 //////////////////////////////////
Chris@16 660 struct tree_policy
Chris@16 661 {
Chris@16 662 template <typename FunctorT, typename MatchT>
Chris@16 663 static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/)
Chris@16 664 {}
Chris@16 665
Chris@16 666 template <typename MatchT, typename Iterator1T, typename Iterator2T>
Chris@16 667 static void group_match(MatchT& /*m*/, parser_id const& /*id*/,
Chris@16 668 Iterator1T const& /*first*/, Iterator2T const& /*last*/)
Chris@16 669 {}
Chris@16 670
Chris@16 671 template <typename MatchT>
Chris@16 672 static void concat(MatchT& /*a*/, MatchT const& /*b*/)
Chris@16 673 {}
Chris@16 674 };
Chris@16 675
Chris@16 676 //////////////////////////////////
Chris@16 677 template <
Chris@16 678 typename MatchPolicyT,
Chris@16 679 typename IteratorT,
Chris@16 680 typename NodeFactoryT,
Chris@16 681 typename TreePolicyT,
Chris@16 682 typename T
Chris@16 683 >
Chris@16 684 struct common_tree_match_policy : public match_policy
Chris@16 685 {
Chris@16 686 common_tree_match_policy()
Chris@16 687 {
Chris@16 688 }
Chris@16 689
Chris@16 690 template <typename PolicyT>
Chris@16 691 common_tree_match_policy(PolicyT const & policies)
Chris@16 692 : match_policy((match_policy const &)policies)
Chris@16 693 {
Chris@16 694 }
Chris@16 695
Chris@16 696 template <typename U>
Chris@16 697 struct result { typedef tree_match<IteratorT, NodeFactoryT, U> type; };
Chris@16 698
Chris@16 699 typedef tree_match<IteratorT, NodeFactoryT, T> match_t;
Chris@16 700 typedef IteratorT iterator_t;
Chris@16 701 typedef TreePolicyT tree_policy_t;
Chris@16 702 typedef NodeFactoryT factory_t;
Chris@16 703
Chris@16 704 static const match_t no_match() { return match_t(); }
Chris@16 705 static const match_t empty_match()
Chris@16 706 { return match_t(0, tree_policy_t::empty_node()); }
Chris@16 707
Chris@16 708 template <typename AttrT, typename Iterator1T, typename Iterator2T>
Chris@16 709 static tree_match<IteratorT, NodeFactoryT, AttrT> create_match(
Chris@16 710 std::size_t length,
Chris@16 711 AttrT const& val,
Chris@16 712 Iterator1T const& first,
Chris@16 713 Iterator2T const& last)
Chris@16 714 {
Chris@16 715 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 716 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 717
Chris@16 718 BOOST_SPIRIT_DEBUG_OUT << "\n>>> create_node(begin) <<<\n"
Chris@16 719 "creating node text: \"";
Chris@16 720 for (Iterator1T it = first; it != last; ++it)
Chris@16 721 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
Chris@16 722 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
Chris@16 723 BOOST_SPIRIT_DEBUG_OUT << ">>> create_node(end) <<<\n\n";
Chris@16 724 #endif
Chris@16 725 return tree_match<IteratorT, NodeFactoryT, AttrT>(length, val,
Chris@16 726 tree_policy_t::create_node(length, first, last, true));
Chris@16 727 }
Chris@16 728
Chris@16 729 template <typename Match1T, typename Match2T>
Chris@16 730 static void concat_match(Match1T& a, Match2T const& b)
Chris@16 731 {
Chris@16 732 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 733 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES)
Chris@16 734
Chris@16 735 BOOST_SPIRIT_DEBUG_OUT << "\n>>> concat_match(begin) <<<\n";
Chris@16 736 BOOST_SPIRIT_DEBUG_OUT << "tree a:\n" << a << "\n";
Chris@16 737 BOOST_SPIRIT_DEBUG_OUT << "tree b:\n" << b << "\n";
Chris@16 738 BOOST_SPIRIT_DEBUG_OUT << ">>> concat_match(end) <<<\n\n";
Chris@16 739 #endif
Chris@16 740 BOOST_SPIRIT_ASSERT(a && b);
Chris@16 741 if (a.length() == 0)
Chris@16 742 {
Chris@16 743 a = b;
Chris@16 744 return;
Chris@16 745 }
Chris@16 746 else if (b.length() == 0
Chris@16 747 #ifdef BOOST_SPIRIT_NO_TREE_NODE_COLLAPSING
Chris@16 748 && !b.trees.begin()->value.id().to_long()
Chris@16 749 #endif
Chris@16 750 )
Chris@16 751 {
Chris@16 752 return;
Chris@16 753 }
Chris@16 754 a.concat(b);
Chris@16 755 tree_policy_t::concat(a, b);
Chris@16 756 }
Chris@16 757
Chris@16 758 template <typename MatchT, typename IteratorT2>
Chris@16 759 void
Chris@16 760 group_match(
Chris@16 761 MatchT& m,
Chris@16 762 parser_id const& id,
Chris@16 763 IteratorT2 const& first,
Chris@16 764 IteratorT2 const& last) const
Chris@16 765 {
Chris@16 766 if (!m) return;
Chris@16 767
Chris@16 768 #if defined(BOOST_SPIRIT_DEBUG) && \
Chris@16 769 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_TREES)
Chris@16 770
Chris@16 771 BOOST_SPIRIT_DEBUG_OUT << "\n>>> group_match(begin) <<<\n"
Chris@16 772 "new node(" << id << ") \"";
Chris@16 773 for (IteratorT2 it = first; it != last; ++it)
Chris@16 774 impl::token_printer(BOOST_SPIRIT_DEBUG_OUT, *it);
Chris@16 775 BOOST_SPIRIT_DEBUG_OUT << "\"\n";
Chris@16 776 BOOST_SPIRIT_DEBUG_OUT << "new child tree (before grouping):\n" << m << "\n";
Chris@16 777
Chris@16 778 tree_policy_t::group_match(m, id, first, last);
Chris@16 779
Chris@16 780 BOOST_SPIRIT_DEBUG_OUT << "new child tree (after grouping):\n" << m << "\n";
Chris@16 781 BOOST_SPIRIT_DEBUG_OUT << ">>> group_match(end) <<<\n\n";
Chris@16 782 #else
Chris@16 783 tree_policy_t::group_match(m, id, first, last);
Chris@16 784 #endif
Chris@16 785 }
Chris@16 786 };
Chris@16 787
Chris@16 788 //////////////////////////////////
Chris@16 789 template <typename MatchPolicyT, typename NodeFactoryT>
Chris@16 790 struct common_tree_tree_policy
Chris@16 791 {
Chris@16 792 typedef typename MatchPolicyT::iterator_t iterator_t;
Chris@16 793 typedef typename MatchPolicyT::match_t match_t;
Chris@16 794 typedef typename NodeFactoryT::template factory<iterator_t> factory_t;
Chris@16 795 typedef typename factory_t::node_t node_t;
Chris@16 796
Chris@16 797 template <typename Iterator1T, typename Iterator2T>
Chris@16 798 static node_t
Chris@16 799 create_node(std::size_t /*length*/, Iterator1T const& first,
Chris@16 800 Iterator2T const& last, bool leaf_node)
Chris@16 801 {
Chris@16 802 return factory_t::create_node(first, last, leaf_node);
Chris@16 803 }
Chris@16 804
Chris@16 805 static node_t
Chris@16 806 empty_node()
Chris@16 807 {
Chris@16 808 return factory_t::empty_node();
Chris@16 809 }
Chris@16 810
Chris@16 811 template <typename FunctorT>
Chris@16 812 static void apply_op_to_match(FunctorT const& op, match_t& m)
Chris@16 813 {
Chris@16 814 op(m);
Chris@16 815 }
Chris@16 816 };
Chris@16 817
Chris@16 818 //////////////////////////////////
Chris@16 819 // directives to modify how the parse tree is generated
Chris@16 820
Chris@16 821 struct no_tree_gen_node_parser_gen;
Chris@16 822
Chris@16 823 template <typename T>
Chris@16 824 struct no_tree_gen_node_parser
Chris@16 825 : public unary<T, parser<no_tree_gen_node_parser<T> > >
Chris@16 826 {
Chris@16 827 typedef no_tree_gen_node_parser<T> self_t;
Chris@16 828 typedef no_tree_gen_node_parser_gen parser_generator_t;
Chris@16 829 typedef unary_parser_category parser_category_t;
Chris@16 830
Chris@16 831 no_tree_gen_node_parser(T const& a)
Chris@16 832 : unary<T, parser<no_tree_gen_node_parser<T> > >(a) {}
Chris@16 833
Chris@16 834 template <typename ScannerT>
Chris@16 835 typename parser_result<self_t, ScannerT>::type
Chris@16 836 parse(ScannerT const& scanner) const
Chris@16 837 {
Chris@16 838 typedef typename ScannerT::iteration_policy_t iteration_policy_t;
Chris@16 839 typedef match_policy match_policy_t;
Chris@16 840 typedef typename ScannerT::action_policy_t action_policy_t;
Chris@16 841 typedef scanner_policies<
Chris@16 842 iteration_policy_t,
Chris@16 843 match_policy_t,
Chris@16 844 action_policy_t
Chris@16 845 > policies_t;
Chris@16 846
Chris@16 847 return this->subject().parse(scanner.change_policies(policies_t(scanner)));
Chris@16 848 }
Chris@16 849 };
Chris@16 850
Chris@16 851 struct no_tree_gen_node_parser_gen
Chris@16 852 {
Chris@16 853 template <typename T>
Chris@16 854 struct result {
Chris@16 855
Chris@16 856 typedef no_tree_gen_node_parser<T> type;
Chris@16 857 };
Chris@16 858
Chris@16 859 template <typename T>
Chris@16 860 static no_tree_gen_node_parser<T>
Chris@16 861 generate(parser<T> const& s)
Chris@16 862 {
Chris@16 863 return no_tree_gen_node_parser<T>(s.derived());
Chris@16 864 }
Chris@16 865
Chris@16 866 template <typename T>
Chris@16 867 no_tree_gen_node_parser<T>
Chris@16 868 operator[](parser<T> const& s) const
Chris@16 869 {
Chris@16 870 return no_tree_gen_node_parser<T>(s.derived());
Chris@16 871 }
Chris@16 872 };
Chris@16 873
Chris@16 874 const no_tree_gen_node_parser_gen no_node_d = no_tree_gen_node_parser_gen();
Chris@16 875
Chris@16 876 //////////////////////////////////
Chris@16 877
Chris@16 878 struct leaf_node_parser_gen;
Chris@16 879
Chris@16 880 template<typename T>
Chris@16 881 struct leaf_node_parser
Chris@16 882 : public unary<T, parser<leaf_node_parser<T> > >
Chris@16 883 {
Chris@16 884 typedef leaf_node_parser<T> self_t;
Chris@16 885 typedef leaf_node_parser_gen parser_generator_t;
Chris@16 886 typedef unary_parser_category parser_category_t;
Chris@16 887
Chris@16 888 leaf_node_parser(T const& a)
Chris@16 889 : unary<T, parser<leaf_node_parser<T> > >(a) {}
Chris@16 890
Chris@16 891 template <typename ScannerT>
Chris@16 892 typename parser_result<self_t, ScannerT>::type
Chris@16 893 parse(ScannerT const& scanner) const
Chris@16 894 {
Chris@16 895 typedef scanner_policies< typename ScannerT::iteration_policy_t,
Chris@16 896 match_policy, typename ScannerT::action_policy_t > policies_t;
Chris@16 897
Chris@16 898 typedef typename ScannerT::iterator_t iterator_t;
Chris@16 899 typedef typename parser_result<self_t, ScannerT>::type result_t;
Chris@16 900 typedef typename result_t::node_factory_t factory_t;
Chris@16 901
Chris@16 902 iterator_t from = scanner.first;
Chris@16 903 result_t hit = impl::contiguous_parser_parse<result_t>(this->subject(),
Chris@16 904 scanner.change_policies(policies_t(scanner,match_policy(),scanner)),
Chris@16 905 scanner);
Chris@16 906
Chris@16 907 if (hit)
Chris@16 908 return result_t(hit.length(),
Chris@16 909 factory_t::create_node(from, scanner.first, true));
Chris@16 910 else
Chris@16 911 return result_t(hit.length());
Chris@16 912 }
Chris@16 913 };
Chris@16 914
Chris@16 915 struct leaf_node_parser_gen
Chris@16 916 {
Chris@16 917 template <typename T>
Chris@16 918 struct result {
Chris@16 919
Chris@16 920 typedef leaf_node_parser<T> type;
Chris@16 921 };
Chris@16 922
Chris@16 923 template <typename T>
Chris@16 924 static leaf_node_parser<T>
Chris@16 925 generate(parser<T> const& s)
Chris@16 926 {
Chris@16 927 return leaf_node_parser<T>(s.derived());
Chris@16 928 }
Chris@16 929
Chris@16 930 template <typename T>
Chris@16 931 leaf_node_parser<T>
Chris@16 932 operator[](parser<T> const& s) const
Chris@16 933 {
Chris@16 934 return leaf_node_parser<T>(s.derived());
Chris@16 935 }
Chris@16 936 };
Chris@16 937
Chris@16 938 const leaf_node_parser_gen leaf_node_d = leaf_node_parser_gen();
Chris@16 939 const leaf_node_parser_gen token_node_d = leaf_node_parser_gen();
Chris@16 940
Chris@16 941 //////////////////////////////////
Chris@16 942 namespace impl {
Chris@16 943
Chris@16 944 template <typename MatchPolicyT>
Chris@16 945 struct tree_policy_selector
Chris@16 946 {
Chris@16 947 typedef tree_policy type;
Chris@16 948 };
Chris@16 949
Chris@16 950 } // namespace impl
Chris@16 951
Chris@16 952 //////////////////////////////////
Chris@16 953 template <typename NodeParserT>
Chris@16 954 struct node_parser_gen;
Chris@16 955
Chris@16 956 template <typename T, typename NodeParserT>
Chris@16 957 struct node_parser
Chris@16 958 : public unary<T, parser<node_parser<T, NodeParserT> > >
Chris@16 959 {
Chris@16 960 typedef node_parser<T, NodeParserT> self_t;
Chris@16 961 typedef node_parser_gen<NodeParserT> parser_generator_t;
Chris@16 962 typedef unary_parser_category parser_category_t;
Chris@16 963
Chris@16 964 node_parser(T const& a)
Chris@16 965 : unary<T, parser<node_parser<T, NodeParserT> > >(a) {}
Chris@16 966
Chris@16 967 template <typename ScannerT>
Chris@16 968 struct result
Chris@16 969 {
Chris@16 970 typedef typename parser_result<T, ScannerT>::type type;
Chris@16 971 };
Chris@16 972
Chris@16 973 template <typename ScannerT>
Chris@16 974 typename parser_result<self_t, ScannerT>::type
Chris@16 975 parse(ScannerT const& scanner) const
Chris@16 976 {
Chris@16 977 typename parser_result<self_t, ScannerT>::type hit = this->subject().parse(scanner);
Chris@16 978 if (hit)
Chris@16 979 {
Chris@16 980 impl::tree_policy_selector<typename ScannerT::match_policy_t>::type::apply_op_to_match(NodeParserT(), hit);
Chris@16 981 }
Chris@16 982 return hit;
Chris@16 983 }
Chris@16 984 };
Chris@16 985
Chris@16 986 template <typename NodeParserT>
Chris@16 987 struct node_parser_gen
Chris@16 988 {
Chris@16 989 template <typename T>
Chris@16 990 struct result {
Chris@16 991
Chris@16 992 typedef node_parser<T, NodeParserT> type;
Chris@16 993 };
Chris@16 994
Chris@16 995 template <typename T>
Chris@16 996 static node_parser<T, NodeParserT>
Chris@16 997 generate(parser<T> const& s)
Chris@16 998 {
Chris@16 999 return node_parser<T, NodeParserT>(s.derived());
Chris@16 1000 }
Chris@16 1001
Chris@16 1002 template <typename T>
Chris@16 1003 node_parser<T, NodeParserT>
Chris@16 1004 operator[](parser<T> const& s) const
Chris@16 1005 {
Chris@16 1006 return node_parser<T, NodeParserT>(s.derived());
Chris@16 1007 }
Chris@16 1008 };
Chris@16 1009 //////////////////////////////////
Chris@16 1010 struct reduced_node_op
Chris@16 1011 {
Chris@16 1012 template <typename MatchT>
Chris@16 1013 void operator()(MatchT& m) const
Chris@16 1014 {
Chris@16 1015 if (m.trees.size() == 1)
Chris@16 1016 {
Chris@16 1017 m.trees.begin()->children.clear();
Chris@16 1018 }
Chris@16 1019 else if (m.trees.size() > 1)
Chris@16 1020 {
Chris@16 1021 typedef typename MatchT::node_factory_t node_factory_t;
Chris@16 1022 m = MatchT(m.length(), node_factory_t::group_nodes(m.trees));
Chris@16 1023 }
Chris@16 1024 }
Chris@16 1025 };
Chris@16 1026
Chris@16 1027 const node_parser_gen<reduced_node_op> reduced_node_d =
Chris@16 1028 node_parser_gen<reduced_node_op>();
Chris@16 1029
Chris@16 1030
Chris@16 1031 struct discard_node_op
Chris@16 1032 {
Chris@16 1033 template <typename MatchT>
Chris@16 1034 void operator()(MatchT& m) const
Chris@16 1035 {
Chris@16 1036 m.trees.clear();
Chris@16 1037 }
Chris@16 1038 };
Chris@16 1039
Chris@16 1040 const node_parser_gen<discard_node_op> discard_node_d =
Chris@16 1041 node_parser_gen<discard_node_op>();
Chris@16 1042
Chris@16 1043 struct infix_node_op
Chris@16 1044 {
Chris@16 1045 template <typename MatchT>
Chris@16 1046 void operator()(MatchT& m) const
Chris@16 1047 {
Chris@16 1048 typedef typename MatchT::container_t container_t;
Chris@16 1049 typedef typename MatchT::container_t::iterator iter_t;
Chris@16 1050 typedef typename MatchT::container_t::value_type value_t;
Chris@16 1051
Chris@16 1052 using std::swap;
Chris@16 1053 using boost::swap;
Chris@16 1054 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1055
Chris@16 1056 // copying the tree nodes is expensive, since it may copy a whole
Chris@16 1057 // tree. swapping them is cheap, so swap the nodes we want into
Chris@16 1058 // a new container of children.
Chris@16 1059 container_t new_children;
Chris@16 1060 std::size_t length = 0;
Chris@16 1061 std::size_t tree_size = m.trees.size();
Chris@16 1062
Chris@16 1063 // the infix_node_d[] make no sense for nodes with no subnodes
Chris@16 1064 BOOST_SPIRIT_ASSERT(tree_size >= 1);
Chris@16 1065
Chris@16 1066 bool keep = true;
Chris@16 1067 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 1068 new_children.reserve((tree_size+1)/2);
Chris@16 1069 #endif
Chris@16 1070 iter_t i_end = m.trees.end();
Chris@16 1071 for (iter_t i = m.trees.begin(); i != i_end; ++i)
Chris@16 1072 {
Chris@16 1073 if (keep) {
Chris@16 1074 // adjust the length
Chris@16 1075 length += std::distance((*i).value.begin(), (*i).value.end());
Chris@16 1076
Chris@16 1077 // move the child node
Chris@16 1078 new_children.push_back(value_t());
Chris@16 1079 swap(new_children.back(), *i);
Chris@16 1080 keep = false;
Chris@16 1081 }
Chris@16 1082 else {
Chris@16 1083 // ignore this child node
Chris@16 1084 keep = true;
Chris@16 1085 }
Chris@16 1086 }
Chris@16 1087
Chris@16 1088 m = MatchT(length, new_children);
Chris@16 1089 }
Chris@16 1090 };
Chris@16 1091
Chris@16 1092 const node_parser_gen<infix_node_op> infix_node_d =
Chris@16 1093 node_parser_gen<infix_node_op>();
Chris@16 1094
Chris@16 1095 struct discard_first_node_op
Chris@16 1096 {
Chris@16 1097 template <typename MatchT>
Chris@16 1098 void operator()(MatchT& m) const
Chris@16 1099 {
Chris@16 1100 typedef typename MatchT::container_t container_t;
Chris@16 1101 typedef typename MatchT::container_t::iterator iter_t;
Chris@16 1102 typedef typename MatchT::container_t::value_type value_t;
Chris@16 1103
Chris@16 1104 using std::swap;
Chris@16 1105 using boost::swap;
Chris@16 1106 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1107
Chris@16 1108 // copying the tree nodes is expensive, since it may copy a whole
Chris@16 1109 // tree. swapping them is cheap, so swap the nodes we want into
Chris@16 1110 // a new container of children, instead of saying
Chris@16 1111 // m.trees.erase(m.trees.begin()) because, on a container_t that will
Chris@16 1112 // cause all the nodes afterwards to be copied into the previous
Chris@16 1113 // position.
Chris@16 1114 container_t new_children;
Chris@16 1115 std::size_t length = 0;
Chris@16 1116 std::size_t tree_size = m.trees.size();
Chris@16 1117
Chris@16 1118 // the discard_first_node_d[] make no sense for nodes with no subnodes
Chris@16 1119 BOOST_SPIRIT_ASSERT(tree_size >= 1);
Chris@16 1120
Chris@16 1121 if (tree_size > 1) {
Chris@16 1122 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 1123 new_children.reserve(tree_size - 1);
Chris@16 1124 #endif
Chris@16 1125 iter_t i = m.trees.begin(), i_end = m.trees.end();
Chris@16 1126 for (++i; i != i_end; ++i)
Chris@16 1127 {
Chris@16 1128 // adjust the length
Chris@16 1129 length += std::distance((*i).value.begin(), (*i).value.end());
Chris@16 1130
Chris@16 1131 // move the child node
Chris@16 1132 new_children.push_back(value_t());
Chris@16 1133 swap(new_children.back(), *i);
Chris@16 1134 }
Chris@16 1135 }
Chris@16 1136 else {
Chris@16 1137 // if there was a tree and now there isn't any, insert an empty node
Chris@16 1138 iter_t i = m.trees.begin();
Chris@16 1139
Chris@16 1140 // This isn't entirely correct, since the empty node will reference
Chris@16 1141 // the end of the discarded node, but I currently don't see any way to
Chris@16 1142 // get at the begin of the node following this subnode.
Chris@16 1143 // This should be safe anyway because the it shouldn't get dereferenced
Chris@16 1144 // under any circumstances.
Chris@16 1145 typedef typename value_t::parse_node_t::iterator_t iterator_type;
Chris@16 1146 iterator_type it = (*i).value.end();
Chris@16 1147
Chris@16 1148 new_children.push_back(
Chris@16 1149 value_t(typename value_t::parse_node_t(it, it)));
Chris@16 1150 }
Chris@16 1151
Chris@16 1152 m = MatchT(length, new_children);
Chris@16 1153 }
Chris@16 1154 };
Chris@16 1155
Chris@16 1156 const node_parser_gen<discard_first_node_op> discard_first_node_d =
Chris@16 1157 node_parser_gen<discard_first_node_op>();
Chris@16 1158
Chris@16 1159 struct discard_last_node_op
Chris@16 1160 {
Chris@16 1161 template <typename MatchT>
Chris@16 1162 void operator()(MatchT& m) const
Chris@16 1163 {
Chris@16 1164 typedef typename MatchT::container_t container_t;
Chris@16 1165 typedef typename MatchT::container_t::iterator iter_t;
Chris@16 1166 typedef typename MatchT::container_t::value_type value_t;
Chris@16 1167
Chris@16 1168 using std::swap;
Chris@16 1169 using boost::swap;
Chris@16 1170 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1171
Chris@16 1172 // copying the tree nodes is expensive, since it may copy a whole
Chris@16 1173 // tree. swapping them is cheap, so swap the nodes we want into
Chris@16 1174 // a new container of children, instead of saying
Chris@16 1175 // m.trees.erase(m.trees.begin()) because, on a container_t that will
Chris@16 1176 // cause all the nodes afterwards to be copied into the previous
Chris@16 1177 // position.
Chris@16 1178 container_t new_children;
Chris@16 1179 std::size_t length = 0;
Chris@16 1180 std::size_t tree_size = m.trees.size();
Chris@16 1181
Chris@16 1182 // the discard_last_node_d[] make no sense for nodes with no subnodes
Chris@16 1183 BOOST_SPIRIT_ASSERT(tree_size >= 1);
Chris@16 1184
Chris@16 1185 if (tree_size > 1) {
Chris@16 1186 m.trees.pop_back();
Chris@16 1187 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 1188 new_children.reserve(tree_size - 1);
Chris@16 1189 #endif
Chris@16 1190 iter_t i_end = m.trees.end();
Chris@16 1191 for (iter_t i = m.trees.begin(); i != i_end; ++i)
Chris@16 1192 {
Chris@16 1193 // adjust the length
Chris@16 1194 length += std::distance((*i).value.begin(), (*i).value.end());
Chris@16 1195
Chris@16 1196 // move the child node
Chris@16 1197 new_children.push_back(value_t());
Chris@16 1198 swap(new_children.back(), *i);
Chris@16 1199 }
Chris@16 1200 }
Chris@16 1201 else {
Chris@16 1202 // if there was a tree and now there isn't any, insert an empty node
Chris@16 1203 iter_t i = m.trees.begin();
Chris@16 1204
Chris@16 1205 typedef typename value_t::parse_node_t::iterator_t iterator_type;
Chris@16 1206 iterator_type it = (*i).value.begin();
Chris@16 1207
Chris@16 1208 new_children.push_back(
Chris@16 1209 value_t(typename value_t::parse_node_t(it, it)));
Chris@16 1210 }
Chris@16 1211
Chris@16 1212 m = MatchT(length, new_children);
Chris@16 1213 }
Chris@16 1214 };
Chris@16 1215
Chris@16 1216 const node_parser_gen<discard_last_node_op> discard_last_node_d =
Chris@16 1217 node_parser_gen<discard_last_node_op>();
Chris@16 1218
Chris@16 1219 struct inner_node_op
Chris@16 1220 {
Chris@16 1221 template <typename MatchT>
Chris@16 1222 void operator()(MatchT& m) const
Chris@16 1223 {
Chris@16 1224 typedef typename MatchT::container_t container_t;
Chris@16 1225 typedef typename MatchT::container_t::iterator iter_t;
Chris@16 1226 typedef typename MatchT::container_t::value_type value_t;
Chris@16 1227
Chris@16 1228 using std::swap;
Chris@16 1229 using boost::swap;
Chris@16 1230 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1231
Chris@16 1232 // copying the tree nodes is expensive, since it may copy a whole
Chris@16 1233 // tree. swapping them is cheap, so swap the nodes we want into
Chris@16 1234 // a new container of children, instead of saying
Chris@16 1235 // m.trees.erase(m.trees.begin()) because, on a container_t that will
Chris@16 1236 // cause all the nodes afterwards to be copied into the previous
Chris@16 1237 // position.
Chris@16 1238 container_t new_children;
Chris@16 1239 std::size_t length = 0;
Chris@16 1240 std::size_t tree_size = m.trees.size();
Chris@16 1241
Chris@16 1242 // the inner_node_d[] make no sense for nodes with less then 2 subnodes
Chris@16 1243 BOOST_SPIRIT_ASSERT(tree_size >= 2);
Chris@16 1244
Chris@16 1245 if (tree_size > 2) {
Chris@16 1246 m.trees.pop_back(); // erase the last element
Chris@16 1247 #if !defined(BOOST_SPIRIT_USE_LIST_FOR_TREES)
Chris@16 1248 new_children.reserve(tree_size - 1);
Chris@16 1249 #endif
Chris@16 1250 iter_t i = m.trees.begin(); // skip over the first element
Chris@16 1251 iter_t i_end = m.trees.end();
Chris@16 1252 for (++i; i != i_end; ++i)
Chris@16 1253 {
Chris@16 1254 // adjust the length
Chris@16 1255 length += std::distance((*i).value.begin(), (*i).value.end());
Chris@16 1256
Chris@16 1257 // move the child node
Chris@16 1258 new_children.push_back(value_t());
Chris@16 1259 swap(new_children.back(), *i);
Chris@16 1260 }
Chris@16 1261 }
Chris@16 1262 else {
Chris@16 1263 // if there was a tree and now there isn't any, insert an empty node
Chris@16 1264 iter_t i = m.trees.begin(); // skip over the first element
Chris@16 1265
Chris@16 1266 typedef typename value_t::parse_node_t::iterator_t iterator_type;
Chris@16 1267 iterator_type it = (*++i).value.begin();
Chris@16 1268
Chris@16 1269 new_children.push_back(
Chris@16 1270 value_t(typename value_t::parse_node_t(it, it)));
Chris@16 1271 }
Chris@16 1272
Chris@16 1273 m = MatchT(length, new_children);
Chris@16 1274 }
Chris@16 1275 };
Chris@16 1276
Chris@16 1277 const node_parser_gen<inner_node_op> inner_node_d =
Chris@16 1278 node_parser_gen<inner_node_op>();
Chris@16 1279
Chris@16 1280
Chris@16 1281 //////////////////////////////////
Chris@16 1282 // action_directive_parser and action_directive_parser_gen
Chris@16 1283 // are meant to be used as a template to create directives that
Chris@16 1284 // generate action classes. For example access_match and
Chris@16 1285 // access_node. The ActionParserT template parameter must be
Chris@16 1286 // a class that has an innter class called action that is templated
Chris@16 1287 // on the parser type and the action type.
Chris@16 1288 template <typename ActionParserT>
Chris@16 1289 struct action_directive_parser_gen;
Chris@16 1290
Chris@16 1291 template <typename T, typename ActionParserT>
Chris@16 1292 struct action_directive_parser
Chris@16 1293 : public unary<T, parser<action_directive_parser<T, ActionParserT> > >
Chris@16 1294 {
Chris@16 1295 typedef action_directive_parser<T, ActionParserT> self_t;
Chris@16 1296 typedef action_directive_parser_gen<ActionParserT> parser_generator_t;
Chris@16 1297 typedef unary_parser_category parser_category_t;
Chris@16 1298
Chris@16 1299 action_directive_parser(T const& a)
Chris@16 1300 : unary<T, parser<action_directive_parser<T, ActionParserT> > >(a) {}
Chris@16 1301
Chris@16 1302 template <typename ScannerT>
Chris@16 1303 struct result
Chris@16 1304 {
Chris@16 1305 typedef typename parser_result<T, ScannerT>::type type;
Chris@16 1306 };
Chris@16 1307
Chris@16 1308 template <typename ScannerT>
Chris@16 1309 typename parser_result<self_t, ScannerT>::type
Chris@16 1310 parse(ScannerT const& scanner) const
Chris@16 1311 {
Chris@16 1312 return this->subject().parse(scanner);
Chris@16 1313 }
Chris@16 1314
Chris@16 1315 template <typename ActionT>
Chris@16 1316 typename ActionParserT::template action<action_directive_parser<T, ActionParserT>, ActionT>
Chris@16 1317 operator[](ActionT const& actor) const
Chris@16 1318 {
Chris@16 1319 typedef typename
Chris@16 1320 ActionParserT::template action<action_directive_parser, ActionT>
Chris@16 1321 action_t;
Chris@16 1322 return action_t(*this, actor);
Chris@16 1323 }
Chris@16 1324 };
Chris@16 1325
Chris@16 1326 //////////////////////////////////
Chris@16 1327 template <typename ActionParserT>
Chris@16 1328 struct action_directive_parser_gen
Chris@16 1329 {
Chris@16 1330 template <typename T>
Chris@16 1331 struct result {
Chris@16 1332
Chris@16 1333 typedef action_directive_parser<T, ActionParserT> type;
Chris@16 1334 };
Chris@16 1335
Chris@16 1336 template <typename T>
Chris@16 1337 static action_directive_parser<T, ActionParserT>
Chris@16 1338 generate(parser<T> const& s)
Chris@16 1339 {
Chris@16 1340 return action_directive_parser<T, ActionParserT>(s.derived());
Chris@16 1341 }
Chris@16 1342
Chris@16 1343 template <typename T>
Chris@16 1344 action_directive_parser<T, ActionParserT>
Chris@16 1345 operator[](parser<T> const& s) const
Chris@16 1346 {
Chris@16 1347 return action_directive_parser<T, ActionParserT>(s.derived());
Chris@16 1348 }
Chris@16 1349 };
Chris@16 1350
Chris@16 1351 //////////////////////////////////
Chris@16 1352 // Calls the attached action passing it the match from the parser
Chris@16 1353 // and the first and last iterators.
Chris@16 1354 // The inner template class is used to simulate template-template parameters
Chris@16 1355 // (declared in common_fwd.hpp).
Chris@16 1356 template <typename ParserT, typename ActionT>
Chris@16 1357 struct access_match_action::action
Chris@16 1358 : public unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >
Chris@16 1359 {
Chris@16 1360 typedef action_parser_category parser_category;
Chris@16 1361 typedef action<ParserT, ActionT> self_t;
Chris@16 1362
Chris@16 1363 template <typename ScannerT>
Chris@16 1364 struct result
Chris@16 1365 {
Chris@16 1366 typedef typename parser_result<ParserT, ScannerT>::type type;
Chris@16 1367 };
Chris@16 1368
Chris@16 1369 action( ParserT const& subject,
Chris@16 1370 ActionT const& actor_);
Chris@16 1371
Chris@16 1372 template <typename ScannerT>
Chris@16 1373 typename parser_result<self_t, ScannerT>::type
Chris@16 1374 parse(ScannerT const& scanner) const;
Chris@16 1375
Chris@16 1376 ActionT const &predicate() const;
Chris@16 1377
Chris@16 1378 private:
Chris@16 1379 ActionT actor;
Chris@16 1380 };
Chris@16 1381
Chris@16 1382 //////////////////////////////////
Chris@16 1383 template <typename ParserT, typename ActionT>
Chris@16 1384 access_match_action::action<ParserT, ActionT>::action(
Chris@16 1385 ParserT const& subject,
Chris@16 1386 ActionT const& actor_)
Chris@16 1387 : unary<ParserT, parser<access_match_action::action<ParserT, ActionT> > >(subject)
Chris@16 1388 , actor(actor_)
Chris@16 1389 {}
Chris@16 1390
Chris@16 1391 //////////////////////////////////
Chris@16 1392 template <typename ParserT, typename ActionT>
Chris@16 1393 template <typename ScannerT>
Chris@16 1394 typename parser_result<access_match_action::action<ParserT, ActionT>, ScannerT>::type
Chris@16 1395 access_match_action::action<ParserT, ActionT>::
Chris@16 1396 parse(ScannerT const& scan) const
Chris@16 1397 {
Chris@16 1398 typedef typename ScannerT::iterator_t iterator_t;
Chris@16 1399 typedef typename parser_result<self_t, ScannerT>::type result_t;
Chris@16 1400 if (!scan.at_end())
Chris@16 1401 {
Chris@16 1402 iterator_t save = scan.first;
Chris@16 1403 result_t hit = this->subject().parse(scan);
Chris@16 1404 actor(hit, save, scan.first);
Chris@16 1405 return hit;
Chris@16 1406 }
Chris@16 1407 return scan.no_match();
Chris@16 1408 }
Chris@16 1409
Chris@16 1410 //////////////////////////////////
Chris@16 1411 template <typename ParserT, typename ActionT>
Chris@16 1412 ActionT const &access_match_action::action<ParserT, ActionT>::predicate() const
Chris@16 1413 {
Chris@16 1414 return actor;
Chris@16 1415 }
Chris@16 1416
Chris@16 1417 //////////////////////////////////
Chris@16 1418 const action_directive_parser_gen<access_match_action> access_match_d
Chris@16 1419 = action_directive_parser_gen<access_match_action>();
Chris@16 1420
Chris@16 1421
Chris@16 1422
Chris@16 1423 //////////////////////////////////
Chris@16 1424 // Calls the attached action passing it the node from the parser
Chris@16 1425 // and the first and last iterators
Chris@16 1426 // The inner template class is used to simulate template-template parameters
Chris@16 1427 // (declared in common_fwd.hpp).
Chris@16 1428 template <typename ParserT, typename ActionT>
Chris@16 1429 struct access_node_action::action
Chris@16 1430 : public unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >
Chris@16 1431 {
Chris@16 1432 typedef action_parser_category parser_category;
Chris@16 1433 typedef action<ParserT, ActionT> self_t;
Chris@16 1434
Chris@16 1435 template <typename ScannerT>
Chris@16 1436 struct result
Chris@16 1437 {
Chris@16 1438 typedef typename parser_result<ParserT, ScannerT>::type type;
Chris@16 1439 };
Chris@16 1440
Chris@16 1441 action( ParserT const& subject,
Chris@16 1442 ActionT const& actor_);
Chris@16 1443
Chris@16 1444 template <typename ScannerT>
Chris@16 1445 typename parser_result<self_t, ScannerT>::type
Chris@16 1446 parse(ScannerT const& scanner) const;
Chris@16 1447
Chris@16 1448 ActionT const &predicate() const;
Chris@16 1449
Chris@16 1450 private:
Chris@16 1451 ActionT actor;
Chris@16 1452 };
Chris@16 1453
Chris@16 1454 //////////////////////////////////
Chris@16 1455 template <typename ParserT, typename ActionT>
Chris@16 1456 access_node_action::action<ParserT, ActionT>::action(
Chris@16 1457 ParserT const& subject,
Chris@16 1458 ActionT const& actor_)
Chris@16 1459 : unary<ParserT, parser<access_node_action::action<ParserT, ActionT> > >(subject)
Chris@16 1460 , actor(actor_)
Chris@16 1461 {}
Chris@16 1462
Chris@16 1463 //////////////////////////////////
Chris@16 1464 template <typename ParserT, typename ActionT>
Chris@16 1465 template <typename ScannerT>
Chris@16 1466 typename parser_result<access_node_action::action<ParserT, ActionT>, ScannerT>::type
Chris@16 1467 access_node_action::action<ParserT, ActionT>::
Chris@16 1468 parse(ScannerT const& scan) const
Chris@16 1469 {
Chris@16 1470 typedef typename ScannerT::iterator_t iterator_t;
Chris@16 1471 typedef typename parser_result<self_t, ScannerT>::type result_t;
Chris@16 1472 if (!scan.at_end())
Chris@16 1473 {
Chris@16 1474 iterator_t save = scan.first;
Chris@16 1475 result_t hit = this->subject().parse(scan);
Chris@16 1476 if (hit && hit.trees.size() > 0)
Chris@16 1477 actor(*hit.trees.begin(), save, scan.first);
Chris@16 1478 return hit;
Chris@16 1479 }
Chris@16 1480 return scan.no_match();
Chris@16 1481 }
Chris@16 1482
Chris@16 1483 //////////////////////////////////
Chris@16 1484 template <typename ParserT, typename ActionT>
Chris@16 1485 ActionT const &access_node_action::action<ParserT, ActionT>::predicate() const
Chris@16 1486 {
Chris@16 1487 return actor;
Chris@16 1488 }
Chris@16 1489
Chris@16 1490 //////////////////////////////////
Chris@16 1491 const action_directive_parser_gen<access_node_action> access_node_d
Chris@16 1492 = action_directive_parser_gen<access_node_action>();
Chris@16 1493
Chris@16 1494
Chris@16 1495
Chris@16 1496 //////////////////////////////////
Chris@16 1497
Chris@16 1498 ///////////////////////////////////////////////////////////////////////////////
Chris@16 1499 //
Chris@16 1500 // tree_parse_info
Chris@16 1501 //
Chris@16 1502 // Results returned by the tree parse functions:
Chris@16 1503 //
Chris@16 1504 // stop: points to the final parse position (i.e parsing
Chris@16 1505 // processed the input up to this point).
Chris@16 1506 //
Chris@16 1507 // match: true if parsing is successful. This may be full:
Chris@16 1508 // the parser consumed all the input, or partial:
Chris@16 1509 // the parser consumed only a portion of the input.
Chris@16 1510 //
Chris@16 1511 // full: true when we have a full match (i.e the parser
Chris@16 1512 // consumed all the input.
Chris@16 1513 //
Chris@16 1514 // length: The number of characters consumed by the parser.
Chris@16 1515 // This is valid only if we have a successful match
Chris@16 1516 // (either partial or full). A negative value means
Chris@16 1517 // that the match is unsucessful.
Chris@16 1518 //
Chris@16 1519 // trees: Contains the root node(s) of the tree.
Chris@16 1520 //
Chris@16 1521 ///////////////////////////////////////////////////////////////////////////////
Chris@16 1522 template <
Chris@16 1523 typename IteratorT,
Chris@16 1524 typename NodeFactoryT,
Chris@16 1525 typename T
Chris@16 1526 >
Chris@16 1527 struct tree_parse_info
Chris@16 1528 {
Chris@16 1529 IteratorT stop;
Chris@16 1530 bool match;
Chris@16 1531 bool full;
Chris@16 1532 std::size_t length;
Chris@16 1533 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees;
Chris@16 1534
Chris@16 1535 tree_parse_info()
Chris@16 1536 : stop()
Chris@16 1537 , match(false)
Chris@16 1538 , full(false)
Chris@16 1539 , length(0)
Chris@16 1540 , trees()
Chris@16 1541 {}
Chris@16 1542
Chris@16 1543 template <typename IteratorT2>
Chris@16 1544 tree_parse_info(tree_parse_info<IteratorT2> const& pi)
Chris@16 1545 : stop(pi.stop)
Chris@16 1546 , match(pi.match)
Chris@16 1547 , full(pi.full)
Chris@16 1548 , length(pi.length)
Chris@16 1549 , trees()
Chris@16 1550 {
Chris@16 1551 using std::swap;
Chris@16 1552 using boost::swap;
Chris@16 1553 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1554
Chris@16 1555 // use auto_ptr like ownership for the trees data member
Chris@16 1556 swap(trees, pi.trees);
Chris@16 1557 }
Chris@16 1558
Chris@16 1559 tree_parse_info(
Chris@16 1560 IteratorT stop_,
Chris@16 1561 bool match_,
Chris@16 1562 bool full_,
Chris@16 1563 std::size_t length_,
Chris@16 1564 typename tree_match<IteratorT, NodeFactoryT, T>::container_t trees_)
Chris@16 1565 : stop(stop_)
Chris@16 1566 , match(match_)
Chris@16 1567 , full(full_)
Chris@16 1568 , length(length_)
Chris@16 1569 , trees()
Chris@16 1570 {
Chris@16 1571 using std::swap;
Chris@16 1572 using boost::swap;
Chris@16 1573 using BOOST_SPIRIT_CLASSIC_NS::swap;
Chris@16 1574
Chris@16 1575 // use auto_ptr like ownership for the trees data member
Chris@16 1576 swap(trees, trees_);
Chris@16 1577 }
Chris@16 1578 };
Chris@16 1579
Chris@16 1580 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
Chris@16 1581
Chris@16 1582 }} // namespace BOOST_SPIRIT_CLASSIC_NS
Chris@16 1583
Chris@16 1584 #endif
Chris@16 1585