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