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