Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/spirit/tree/common.hpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

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