summaryrefslogtreecommitdiff
path: root/boost/xpressive/detail/static/visitor.hpp
blob: 5a0213f695ef31d05e82699664a53c5dd612837a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
///////////////////////////////////////////////////////////////////////////////
// visitor.hpp
//
//  Copyright 2008 Eric Niebler. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_XPRESSIVE_DETAIL_STATIC_VISITOR_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_STATIC_VISITOR_HPP_EAN_10_04_2005

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif

#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>
#include <boost/xpressive/detail/static/transmogrify.hpp>
#include <boost/xpressive/detail/core/matcher/mark_begin_matcher.hpp>

namespace boost { namespace xpressive { namespace detail
{
    ///////////////////////////////////////////////////////////////////////////////
    //
    template<typename BidiIter>
    struct xpression_visitor_base
    {
        explicit xpression_visitor_base(shared_ptr<regex_impl<BidiIter> > const &self)
          : self_(self)
        {
        }

        void swap(xpression_visitor_base<BidiIter> &that)
        {
            this->self_.swap(that.self_);
        }

        int get_hidden_mark()
        {
            return -(int)(++this->self_->hidden_mark_count_);
        }

        void mark_number(int mark_nbr)
        {
            if(0 < mark_nbr)
            {
                this->self_->mark_count_ =
                    (std::max)(this->self_->mark_count_, (std::size_t)mark_nbr);
            }
        }

        shared_ptr<regex_impl<BidiIter> > &self()
        {
            return this->self_;
        }

    protected:

        template<typename Matcher>
        void visit_(Matcher const &)
        {
        }

        void visit_(reference_wrapper<basic_regex<BidiIter> > const &rex)
        {
            // when visiting an embedded regex, track the references
            this->self_->track_reference(*detail::core_access<BidiIter>::get_regex_impl(rex.get()));
        }

        void visit_(reference_wrapper<basic_regex<BidiIter> const> const &rex)
        {
            // when visiting an embedded regex, track the references
            this->self_->track_reference(*detail::core_access<BidiIter>::get_regex_impl(rex.get()));
        }

        void visit_(tracking_ptr<regex_impl<BidiIter> > const &rex)
        {
            // when visiting an embedded regex, track the references
            this->self_->track_reference(*rex.get());
        }

        void visit_(mark_placeholder const &backref)
        {
            // keep track of the largest mark number found
            this->mark_number(backref.mark_number_);
        }

        void visit_(mark_begin_matcher const &mark_begin)
        {
            // keep track of the largest mark number found
            this->mark_number(mark_begin.mark_number_);
        }

    private:
        shared_ptr<regex_impl<BidiIter> > self_;
    };

    ///////////////////////////////////////////////////////////////////////////////
    //
    template<typename BidiIter, typename ICase, typename Traits>
    struct xpression_visitor
      : xpression_visitor_base<BidiIter>
    {
        typedef BidiIter iterator_type;
        typedef ICase icase_type;
        typedef Traits traits_type;
        typedef typename boost::iterator_value<BidiIter>::type char_type;

        explicit xpression_visitor(Traits const &tr, shared_ptr<regex_impl<BidiIter> > const &self)
          : xpression_visitor_base<BidiIter>(self)
          , traits_(tr)
        {
        }

        template<typename Matcher>
        struct apply
        {
            typedef typename transmogrify<BidiIter, ICase, Traits, Matcher>::type type;
        };

        template<typename Matcher>
        typename apply<Matcher>::type
        call(Matcher const &matcher)
        {
            this->visit_(matcher);
            return transmogrify<BidiIter, ICase, Traits, Matcher>::call(matcher, *this);
        }

        Traits const &traits() const
        {
            return this->traits_;
        }

    private:

        Traits traits_;
    };

}}}

#endif