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
tree_nodeboost::spirit::tree_node81 tree_node()
82 : value()
83 , children()
84 {}
85
tree_nodeboost::spirit::tree_node86 explicit tree_node(T const& v)
87 : value(v)
88 , children()
89 {}
90
tree_nodeboost::spirit::tree_node91 tree_node(T const& v, children_t const& c)
92 : value(v)
93 , children(c)
94 {}
95
swapboost::spirit::tree_node96 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=
operator =boost::spirit::tree_node103 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&
operator <<(std::ostream & o,tree_node<T> const & n)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
node_iter_databoost::spirit::node_iter_data142 node_iter_data()
143 : first(), last(), is_root_(false), parser_id_(), value_()
144 {}
145
node_iter_databoost::spirit::node_iter_data146 node_iter_data(IteratorT const& _first, IteratorT const& _last)
147 : first(_first), last(_last), is_root_(false), parser_id_(), value_()
148 {}
149
swapboost::spirit::node_iter_data150 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
beginboost::spirit::node_iter_data159 IteratorT begin()
160 {
161 return first;
162 }
163
beginboost::spirit::node_iter_data164 IteratorT const& begin() const
165 {
166 return first;
167 }
168
endboost::spirit::node_iter_data169 IteratorT end()
170 {
171 return last;
172 }
173
endboost::spirit::node_iter_data174 IteratorT const& end() const
175 {
176 return last;
177 }
178
is_rootboost::spirit::node_iter_data179 bool is_root() const
180 {
181 return is_root_;
182 }
183
is_rootboost::spirit::node_iter_data184 void is_root(bool b)
185 {
186 is_root_ = b;
187 }
188
idboost::spirit::node_iter_data189 parser_id id() const
190 {
191 return parser_id_;
192 }
193
idboost::spirit::node_iter_data194 void id(parser_id r)
195 {
196 parser_id_ = r;
197 }
198
valueboost::spirit::node_iter_data199 ValueT const& value() const
200 {
201 return value_;
202 }
203
valueboost::spirit::node_iter_data204 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&
operator <<(std::ostream & o,nil_t const &)221 operator<<(std::ostream& o, nil_t const&)
222 {
223 return o;
224 }
225
226 template <typename IteratorT, typename ValueT>
227 inline std::ostream&
operator <<(std::ostream & o,node_iter_data<IteratorT,ValueT> const & n)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
node_val_databoost::spirit::node_val_data266 node_val_data()
267 : text(), is_root_(false), parser_id_(), value_()
268 {}
269
270 #if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
node_val_databoost::spirit::node_val_data271 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>
node_val_databoost::spirit::node_val_data279 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
node_val_databoost::spirit::node_val_data285 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>
node_val_databoost::spirit::node_val_data291 node_val_data(IteratorT2 const& _first, IteratorT2 const& _last)
292 : text(_first, _last), is_root_(false), parser_id_(), value_()
293 {}
294 #endif
295
swapboost::spirit::node_val_data296 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
beginboost::spirit::node_val_data304 typename container_t::iterator begin()
305 {
306 return text.begin();
307 }
308
beginboost::spirit::node_val_data309 typename container_t::const_iterator begin() const
310 {
311 return text.begin();
312 }
313
endboost::spirit::node_val_data314 typename container_t::iterator end()
315 {
316 return text.end();
317 }
318
endboost::spirit::node_val_data319 typename container_t::const_iterator end() const
320 {
321 return text.end();
322 }
323
is_rootboost::spirit::node_val_data324 bool is_root() const
325 {
326 return is_root_;
327 }
328
is_rootboost::spirit::node_val_data329 void is_root(bool b)
330 {
331 is_root_ = b;
332 }
333
idboost::spirit::node_val_data334 parser_id id() const
335 {
336 return parser_id_;
337 }
338
idboost::spirit::node_val_data339 void id(parser_id r)
340 {
341 parser_id_ = r;
342 }
343
valueboost::spirit::node_val_data344 ValueT const& value() const
345 {
346 return value_;
347 }
348
valueboost::spirit::node_val_data349 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&
operator <<(std::ostream & o,node_val_data<IteratorT,ValueT> const & n)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
swap(tree_node<T> & a,tree_node<T> & b)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
swap(node_iter_data<T,V> & a,node_iter_data<T,V> & b)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
create_node(iterator_t const & first,iterator_t const & last,bool)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
empty_node()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>
group_nodes(ContainerT const & nodes)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
create_node(iterator_t const & first,iterator_t const & last,bool is_leaf_node)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
empty_node()451 static node_t empty_node()
452 {
453 return node_t();
454 }
455
456 template <typename ContainerT>
group_nodes(ContainerT const & nodes)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
create_node(iterator_t const & first,iterator_t const & last,bool)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
empty_node()495 static node_t empty_node()
496 {
497 return node_t();
498 }
499
500 template <typename ContainerT>
group_nodes(ContainerT const & nodes)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>
cp_swap(T & t1,T & t2)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
tree_match()552 tree_match()
553 : match<T>(), trees()
554 {}
555
556 explicit
tree_match(std::size_t length_)557 tree_match(std::size_t length_)
558 : match<T>(length_), trees()
559 {}
560
tree_match(std::size_t length_,parse_node_t const & n)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
tree_match(std::size_t length_,param_type val,parse_node_t const & n)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!
tree_match(std::size_t length_,container_t & c)577 tree_match(std::size_t length_, container_t& c)
578 : match<T>(length_), trees()
579 {
580 impl::cp_swap(trees, c);
581 }
582
tree_match(std::size_t length_,param_type val,container_t & c)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>
tree_match(match<T2> const & other)590 tree_match(match<T2> const& other)
591 : match<T>(other), trees()
592 {}
593
594 template <typename T2, typename T3, typename T4>
tree_match(tree_match<T2,T3,T4> const & other)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&
operator =(match<T2> const & other)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&
operator =(tree_match<T2,T3,T4> const & other)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
tree_match(tree_match const & x)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
operator =(tree_match const & x)623 tree_match& operator=(tree_match const& x)
624 {
625 tree_match tmp(x);
626 this->swap(tmp);
627 return *this;
628 }
629
swap(tree_match & x)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&
operator <<(std::ostream & o,tree_match<IteratorT,NodeFactoryT,T> const & m)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>
apply_op_to_matchboost::spirit::tree_policy664 static void apply_op_to_match(FunctorT const& /*op*/, MatchT& /*m*/)
665 {}
666
667 template <typename MatchT, typename Iterator1T, typename Iterator2T>
group_matchboost::spirit::tree_policy668 static void group_match(MatchT& /*m*/, parser_id const& /*id*/,
669 Iterator1T const& /*first*/, Iterator2T const& /*last*/)
670 {}
671
672 template <typename MatchT>
concatboost::spirit::tree_policy673 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 {
common_tree_match_policyboost::spirit::common_tree_match_policy687 common_tree_match_policy()
688 {
689 }
690
691 template <typename PolicyT>
common_tree_match_policyboost::spirit::common_tree_match_policy692 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
no_matchboost::spirit::common_tree_match_policy705 static const match_t no_match() { return match_t(); }
empty_matchboost::spirit::common_tree_match_policy706 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>
create_matchboost::spirit::common_tree_match_policy710 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>
concat_matchboost::spirit::common_tree_match_policy731 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
group_matchboost::spirit::common_tree_match_policy761 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
create_nodeboost::spirit::common_tree_tree_policy800 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
empty_nodeboost::spirit::common_tree_tree_policy807 empty_node()
808 {
809 return factory_t::empty_node();
810 }
811
812 template <typename FunctorT>
apply_op_to_matchboost::spirit::common_tree_tree_policy813 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
no_tree_gen_node_parserboost::spirit::no_tree_gen_node_parser832 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
parseboost::spirit::no_tree_gen_node_parser837 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>
generateboost::spirit::no_tree_gen_node_parser_gen862 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>
operator []boost::spirit::no_tree_gen_node_parser_gen869 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
leaf_node_parserboost::spirit::leaf_node_parser889 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
parseboost::spirit::leaf_node_parser894 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>
generateboost::spirit::leaf_node_parser_gen926 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>
operator []boost::spirit::leaf_node_parser_gen933 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
node_parserboost::spirit::node_parser965 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
parseboost::spirit::node_parser976 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>
generateboost::spirit::node_parser_gen998 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>
operator []boost::spirit::node_parser_gen1005 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>
operator ()boost::spirit::reduced_node_op1014 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>
operator ()boost::spirit::discard_node_op1035 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>
operator ()boost::spirit::infix_node_op1047 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>
operator ()boost::spirit::discard_first_node_op1099 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>
operator ()boost::spirit::discard_last_node_op1163 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>
operator ()boost::spirit::inner_node_op1223 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
action_directive_parserboost::spirit::action_directive_parser1300 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
parseboost::spirit::action_directive_parser1311 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>
operator []boost::spirit::action_directive_parser1318 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>
generateboost::spirit::action_directive_parser_gen1339 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>
operator []boost::spirit::action_directive_parser_gen1346 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>
action(ParserT const & subject,ActionT const & actor_)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>::
parse(ScannerT const & scan) const1397 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>
predicate() const1413 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>
action(ParserT const & subject,ActionT const & actor_)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>::
parse(ScannerT const & scan) const1469 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>
predicate() const1486 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 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
tree_parse_infoboost::spirit::tree_parse_info1536 tree_parse_info()
1537 : stop()
1538 , match(false)
1539 , full(false)
1540 , length(0)
1541 , trees()
1542 {}
1543
1544 template <typename IteratorT2>
tree_parse_infoboost::spirit::tree_parse_info1545 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
tree_parse_infoboost::spirit::tree_parse_info1560 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
1587