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