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