liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
///////////////////////////////////////////////////////////////////////////////
// matchable.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_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_DYNAMIC_MATCHABLE_HPP_EAN_10_04_2005
 
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
 
#include <boost/assert.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/xpressive/detail/core/quant_style.hpp>
#include <boost/xpressive/detail/utility/counted_base.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/sequence.hpp>
#include <boost/xpressive/regex_error.hpp>
 
namespace boost { namespace xpressive { namespace detail
{
 
//////////////////////////////////////////////////////////////////////////
// quant_spec
struct quant_spec
{
    unsigned int min_;
    unsigned int max_;
    bool greedy_;
    std::size_t *hidden_mark_count_;
};
 
///////////////////////////////////////////////////////////////////////////////
// matchable
template<typename BidiIter>
struct matchable
{
    typedef BidiIter iterator_type;
    typedef typename iterator_value<iterator_type>::type char_type;
    virtual ~matchable() {}
    virtual bool match(match_state<BidiIter> &state) const = 0;
};
 
///////////////////////////////////////////////////////////////////////////////
// matchable_ex
template<typename BidiIter>
struct matchable_ex
  : matchable<BidiIter>
  , counted_base<matchable_ex<BidiIter> >
{
    typedef BidiIter iterator_type;
    typedef typename iterator_value<iterator_type>::type char_type;
 
    virtual void link(xpression_linker<char_type> &) const
    {
    }
 
    virtual void peek(xpression_peeker<char_type> &peeker) const
    {
        peeker.fail();
    }
 
    virtual void repeat(quant_spec const &, sequence<BidiIter> &) const
    {
        BOOST_THROW_EXCEPTION(
            regex_error(regex_constants::error_badrepeat, "expression cannot be quantified")
        );
    }
 
    ///////////////////////////////////////////////////////////////////////////////////////////////
    // The following 4 functions (push_match, top_match, pop_match and skip_match) are
    // used to implement looping and branching across the matchers. Call push_match to record
    // a position. Then, another matcher further down the xpression chain has the
    // option to call either top_match, pop_match or skip_match. top_match and pop_match will
    // jump back to the place recorded by push_match, whereas skip_match will skip the jump and
    // pass execution down the xpression chain. top_match will leave the xpression on top of the
    // stack, whereas pop_match will remove it. Each function comes in 2 flavors: one for
    // statically bound xpressions and one for dynamically bound xpressions.
    //
 
    template<typename Top>
    bool push_match(match_state<BidiIter> &state) const
    {
        BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >));
        return this->match(state);
    }
 
    static bool top_match(match_state<BidiIter> &state, void const *top)
    {
        return static_cast<matchable_ex<BidiIter> const *>(top)->match(state);
    }
 
    static bool pop_match(match_state<BidiIter> &state, void const *top)
    {
        return static_cast<matchable_ex<BidiIter> const *>(top)->match(state);
    }
 
    bool skip_match(match_state<BidiIter> &state) const
    {
        return this->match(state);
    }
};
 
///////////////////////////////////////////////////////////////////////////////
// shared_matchable
template<typename BidiIter>
struct shared_matchable
{
    typedef BidiIter iterator_type;
    typedef typename iterator_value<BidiIter>::type char_type;
    typedef intrusive_ptr<matchable_ex<BidiIter> const> matchable_ptr;
 
    BOOST_STATIC_CONSTANT(std::size_t, width = unknown_width::value);
    BOOST_STATIC_CONSTANT(bool, pure = false);
 
    shared_matchable(matchable_ptr const &xpr = matchable_ptr())
      : xpr_(xpr)
    {
    }
 
    bool operator !() const
    {
        return !this->xpr_;
    }
 
    friend bool operator ==(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right)
    {
        return left.xpr_ == right.xpr_;
    }
 
    friend bool operator !=(shared_matchable<BidiIter> const &left, shared_matchable<BidiIter> const &right)
    {
        return left.xpr_ != right.xpr_;
    }
 
    matchable_ptr const &matchable() const
    {
        return this->xpr_;
    }
 
    bool match(match_state<BidiIter> &state) const
    {
        return this->xpr_->match(state);
    }
 
    void link(xpression_linker<char_type> &linker) const
    {
        this->xpr_->link(linker);
    }
 
    void peek(xpression_peeker<char_type> &peeker) const
    {
        this->xpr_->peek(peeker);
    }
 
    // BUGBUG yuk!
    template<typename Top>
    bool push_match(match_state<BidiIter> &state) const
    {
        BOOST_MPL_ASSERT((is_same<Top, matchable_ex<BidiIter> >));
        return this->match(state);
    }
 
private:
    matchable_ptr xpr_;
};
 
}}} // namespace boost::xpressive::detail
 
#endif