summaryrefslogtreecommitdiff
path: root/boost/boost/xpressive/basic_regex.hpp
blob: 91c71b7af0f5693ce2545078a1a6d8a876fe8c96 (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
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
///////////////////////////////////////////////////////////////////////////////
/// \file basic_regex.hpp
/// Contains the definition of the basic_regex\<\> class template and its
/// associated helper functions.
//
//  Copyright 2004 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_BASIC_REGEX_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005

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

#ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
# include <iostream>
#endif
#include <boost/mpl/bool.hpp>
#include <boost/xpressive/proto/proto_fwd.hpp>
#include <boost/xpressive/regex_constants.hpp>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/core/regex_impl.hpp>

namespace boost { namespace xpressive
{

///////////////////////////////////////////////////////////////////////////////
// basic_regex
//
/// \brief Class template basic_regex\<\> is a class for holding a compiled regular expression.
template<typename BidiIter>
struct basic_regex
{
    typedef BidiIter iterator_type;
    typedef typename iterator_value<BidiIter>::type char_type;
    typedef std::basic_string<char_type> string_type;
    typedef regex_constants::syntax_option_type flag_type;

    /// \post regex_id()    == 0
    /// \post mark_count()  == 0
    basic_regex()
      : impl_()
    {
    }

    /// \param that The basic_regex object to copy.
    /// \post regex_id()    == that.regex_id()
    /// \post mark_count()  == that.mark_count()
    basic_regex(basic_regex<BidiIter> const &that)
      : impl_(that.impl_)
    {
    }

    /// \param that The basic_regex object to copy.
    /// \post regex_id()    == that.regex_id()
    /// \post mark_count()  == that.mark_count()
    /// \return *this
    basic_regex<BidiIter> &operator =(basic_regex<BidiIter> const &that)
    {
        this->impl_ = that.impl_;
        return *this;
    }

    /// Construct from a static regular expression.
    ///
    /// \param  xpr The static regular expression
    /// \pre    Xpr is the type of a static regular expression.
    /// \post   regex_id()   != 0
    /// \post   mark_count() \>= 0
    template<typename Xpr>
    basic_regex(Xpr const &xpr)
      : impl_()
    {
        this->operator =(xpr);
    }

    /// Construct from a static regular expression.
    ///
    /// \param  xpr The static regular expression.
    /// \pre    Xpr is the type of a static regular expression.
    /// \post   regex_id()   != 0
    /// \post   mark_count() \>= 0
    /// \throw  std::bad_alloc on out of memory
    /// \return *this
    template<typename Xpr>
    basic_regex<BidiIter> &operator =(Xpr const &xpr)
    {
        detail::static_compile(xpr, *this->impl_.get());
        return *this;
    }

    /// Returns the count of capturing sub-expressions in this regular expression
    ///
    std::size_t mark_count() const
    {
        return this->impl_ ? this->impl_->mark_count_ : 0;
    }

    /// Returns a token which uniquely identifies this regular expression.
    ///
    regex_id_type regex_id() const
    {
        return this->impl_ ? this->impl_->xpr_.get() : 0;
    }

    /// Swaps the contents of this basic_regex object with another.
    ///
    /// \param      that The other basic_regex object.
    /// \attention  This is a shallow swap that does not do reference tracking. If you embed
    /// a basic_regex object by reference in another regular expression and then swap its
    /// contents with another basic_regex object, the change will not be visible to the enclosing
    /// regular expression. It is done this way to ensure that swap() cannot throw.
    /// \throw nothrow
    void swap(basic_regex<BidiIter> &that) // throw()
    {
        this->impl_.swap(that.impl_);
    }

    /// Factory method for building a regex object from a string.
    /// Equivalent to regex_compiler\< BidiIter \>().compile(str, flags);
    ///
    /// \param str The std::basic_string containing the regular expression.
    /// \param flags Optional bitmask of type syntax_option_type to control how str is interpreted.
    static basic_regex<BidiIter> compile(string_type const &str, flag_type flags = regex_constants::ECMAScript)
    {
        return regex_compiler<BidiIter>().compile(str, flags);
    }

    // for binding actions to this regex when it is nested statically in another regex
    /// INTERNAL ONLY
    template<typename Action>
    proto::binary_op
    <
        proto::unary_op<basic_regex<BidiIter>, proto::noop_tag>
      , proto::unary_op<Action, proto::noop_tag>
      , proto::right_shift_tag
    > const
    operator [](detail::action_matcher<Action> const &action) const
    {
        return proto::noop(*this) >> proto::noop(*static_cast<Action const *>(&action));
    }

    //{{AFX_DEBUG
    #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
    // BUGBUG debug only
    /// INTERNAL ONLY
    friend std::ostream &operator <<(std::ostream &sout, basic_regex<BidiIter> const &rex)
    {
        rex.dump_(sout);
        return sout;
    }
    #endif
    //}}AFX_DEBUG

private:
    friend struct detail::core_access<BidiIter>;

    // Avoid a common programming mistake. Construction from a string is ambiguous. It could mean
    //   sregex rx = sregex::compile(str); // compile the string into a regex
    // or
    //   sregex rx = as_xpr(str);          // treat the string as a literal
    // Since there is no easy way to disambiguate, disallow it and force users to say what they mean
    /// INTERNAL ONLY
    basic_regex(char_type const *);
    /// INTERNAL ONLY
    basic_regex(string_type const &);

    // used from parser, via core_access
    /// INTERNAL ONLY
    explicit basic_regex(detail::regex_impl<BidiIter> const &that)
      : impl_()
    {
        this->impl_.tracking_copy(that);
    }

    /// INTERNAL ONLY
    bool match_(detail::state_type<BidiIter> &state) const
    {
        return this->impl_->xpr_->match(state);
    }

    // Returns true if this basic_regex object does not contain a valid regular expression.
    /// INTERNAL ONLY
    bool invalid_() const
    {
        return !this->impl_ || !this->impl_->xpr_;
    }

    /// INTERNAL ONLY
    void dump_(std::ostream &sout) const;

    // the tracking_ptr manages lazy-init, COW, cycle-breaking, and
    // reference/dependency tracking.
    detail::tracking_ptr<detail::regex_impl<BidiIter> > impl_;
};

//{{AFX_DEBUG
#ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
///////////////////////////////////////////////////////////////////////////////
// dump_
/// INTERNAL ONLY
template<typename BidiIter>
inline void basic_regex<BidiIter>::dump_(std::ostream &sout) const
{
    if(!this->impl_)
    {
        sout << "<null> refs={} deps={}";
    }
    else
    {
        sout << *this->impl_;
    }
}
#endif
//}}AFX_DEBUG

///////////////////////////////////////////////////////////////////////////////
// swap
/// \brief      Swaps the contents of two basic_regex objects.
/// \param      left The first basic_regex object.
/// \param      right The second basic_regex object.
/// \attention  This is a shallow swap that does not do reference tracking.
/// If you embed a basic_regex object by reference in another regular expression
/// and then swap its contents with another basic_regex object, the change will
/// not be visible to the enclosing regular expression. It is done this way to
/// ensure that swap() cannot throw.
/// \throw nothrow
template<typename BidiIter>
inline void swap(basic_regex<BidiIter> &left, basic_regex<BidiIter> &right) // throw()
{
    left.swap(right);
}

}} // namespace boost::xpressive

#endif // BOOST_XPRESSIVE_REGEX_HPP_EAN_10_04_2005