Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 /// \file basic_regex.hpp
|
Chris@16
|
3 /// Contains the definition of the basic_regex\<\> class template and its
|
Chris@16
|
4 /// associated helper functions.
|
Chris@16
|
5 //
|
Chris@16
|
6 // Copyright 2008 Eric Niebler. Distributed under the Boost
|
Chris@16
|
7 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9
|
Chris@16
|
10 #ifndef BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005
|
Chris@16
|
11 #define BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005
|
Chris@16
|
12
|
Chris@16
|
13 // MS compatible compilers support #pragma once
|
Chris@101
|
14 #if defined(_MSC_VER)
|
Chris@16
|
15 # pragma once
|
Chris@16
|
16 #endif
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/config.hpp>
|
Chris@16
|
19 #include <boost/mpl/bool.hpp>
|
Chris@16
|
20 #include <boost/xpressive/xpressive_fwd.hpp>
|
Chris@16
|
21 #include <boost/xpressive/regex_constants.hpp>
|
Chris@16
|
22 #include <boost/xpressive/detail/detail_fwd.hpp>
|
Chris@16
|
23 #include <boost/xpressive/detail/core/regex_impl.hpp>
|
Chris@16
|
24 #include <boost/xpressive/detail/core/regex_domain.hpp>
|
Chris@16
|
25
|
Chris@16
|
26 // Doxygen can't handle proto :-(
|
Chris@16
|
27 #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
|
Chris@16
|
28 # include <boost/xpressive/detail/static/grammar.hpp>
|
Chris@16
|
29 # include <boost/proto/extends.hpp>
|
Chris@16
|
30 #endif
|
Chris@16
|
31
|
Chris@16
|
32 #if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD
|
Chris@16
|
33 # include <excpt.h> // for _exception_code()
|
Chris@16
|
34 # include <malloc.h> // for _resetstkoflw()
|
Chris@16
|
35 #endif
|
Chris@16
|
36
|
Chris@16
|
37 namespace boost { namespace xpressive
|
Chris@16
|
38 {
|
Chris@16
|
39
|
Chris@16
|
40 namespace detail
|
Chris@16
|
41 {
|
Chris@16
|
42 inline void throw_on_stack_error(bool stack_error)
|
Chris@16
|
43 {
|
Chris@16
|
44 BOOST_XPR_ENSURE_(!stack_error, regex_constants::error_stack, "Regex stack space exhausted");
|
Chris@16
|
45 }
|
Chris@16
|
46 }
|
Chris@16
|
47
|
Chris@16
|
48 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
49 // basic_regex
|
Chris@16
|
50 //
|
Chris@16
|
51 /// \brief Class template basic_regex\<\> is a class for holding a compiled regular expression.
|
Chris@16
|
52 template<typename BidiIter>
|
Chris@16
|
53 struct basic_regex
|
Chris@16
|
54 : proto::extends<
|
Chris@16
|
55 proto::expr<proto::tag::terminal, proto::term<detail::tracking_ptr<detail::regex_impl<BidiIter> > >, 0>
|
Chris@16
|
56 , basic_regex<BidiIter>
|
Chris@16
|
57 , detail::regex_domain
|
Chris@16
|
58 >
|
Chris@16
|
59 {
|
Chris@16
|
60 private:
|
Chris@16
|
61 typedef proto::expr<proto::tag::terminal, proto::term<detail::tracking_ptr<detail::regex_impl<BidiIter> > >, 0> pimpl_type;
|
Chris@16
|
62 typedef proto::extends<pimpl_type, basic_regex<BidiIter>, detail::regex_domain> base_type;
|
Chris@16
|
63
|
Chris@16
|
64 public:
|
Chris@16
|
65 typedef BidiIter iterator_type;
|
Chris@16
|
66 typedef typename iterator_value<BidiIter>::type char_type;
|
Chris@16
|
67 // For compatibility with std::basic_regex
|
Chris@16
|
68 typedef typename iterator_value<BidiIter>::type value_type;
|
Chris@16
|
69 typedef typename detail::string_type<char_type>::type string_type;
|
Chris@16
|
70 typedef regex_constants::syntax_option_type flag_type;
|
Chris@16
|
71
|
Chris@16
|
72 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, ECMAScript = regex_constants::ECMAScript);
|
Chris@16
|
73 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, icase = regex_constants::icase_);
|
Chris@16
|
74 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, nosubs = regex_constants::nosubs);
|
Chris@16
|
75 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, optimize = regex_constants::optimize);
|
Chris@16
|
76 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, collate = regex_constants::collate);
|
Chris@16
|
77 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, single_line = regex_constants::single_line);
|
Chris@16
|
78 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, not_dot_null = regex_constants::not_dot_null);
|
Chris@16
|
79 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, not_dot_newline = regex_constants::not_dot_newline);
|
Chris@16
|
80 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, ignore_white_space = regex_constants::ignore_white_space);
|
Chris@16
|
81
|
Chris@16
|
82 /// \post regex_id() == 0
|
Chris@16
|
83 /// \post mark_count() == 0
|
Chris@16
|
84 basic_regex()
|
Chris@16
|
85 : base_type()
|
Chris@16
|
86 {
|
Chris@16
|
87 }
|
Chris@16
|
88
|
Chris@16
|
89 /// \param that The basic_regex object to copy.
|
Chris@16
|
90 /// \post regex_id() == that.regex_id()
|
Chris@16
|
91 /// \post mark_count() == that.mark_count()
|
Chris@16
|
92 basic_regex(basic_regex<BidiIter> const &that)
|
Chris@16
|
93 : base_type(that)
|
Chris@16
|
94 {
|
Chris@16
|
95 }
|
Chris@16
|
96
|
Chris@16
|
97 /// \param that The basic_regex object to copy.
|
Chris@16
|
98 /// \post regex_id() == that.regex_id()
|
Chris@16
|
99 /// \post mark_count() == that.mark_count()
|
Chris@16
|
100 /// \return *this
|
Chris@16
|
101 basic_regex<BidiIter> &operator =(basic_regex<BidiIter> const &that)
|
Chris@16
|
102 {
|
Chris@16
|
103 proto::value(*this) = proto::value(that);
|
Chris@16
|
104 return *this;
|
Chris@16
|
105 }
|
Chris@16
|
106
|
Chris@16
|
107 /// Construct from a static regular expression.
|
Chris@16
|
108 ///
|
Chris@16
|
109 /// \param expr The static regular expression
|
Chris@16
|
110 /// \pre Expr is the type of a static regular expression.
|
Chris@16
|
111 /// \post regex_id() != 0
|
Chris@16
|
112 /// \post mark_count() \>= 0
|
Chris@16
|
113 template<typename Expr>
|
Chris@16
|
114 basic_regex(Expr const &expr)
|
Chris@16
|
115 : base_type()
|
Chris@16
|
116 {
|
Chris@16
|
117 BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type);
|
Chris@16
|
118 this->compile_(expr, is_valid_regex<Expr, char_type>());
|
Chris@16
|
119 }
|
Chris@16
|
120
|
Chris@16
|
121 /// Construct from a static regular expression.
|
Chris@16
|
122 ///
|
Chris@16
|
123 /// \param expr The static regular expression.
|
Chris@16
|
124 /// \pre Expr is the type of a static regular expression.
|
Chris@16
|
125 /// \post regex_id() != 0
|
Chris@16
|
126 /// \post mark_count() \>= 0
|
Chris@16
|
127 /// \throw std::bad_alloc on out of memory
|
Chris@16
|
128 /// \return *this
|
Chris@16
|
129 template<typename Expr>
|
Chris@16
|
130 basic_regex<BidiIter> &operator =(Expr const &expr)
|
Chris@16
|
131 {
|
Chris@16
|
132 BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type);
|
Chris@16
|
133 this->compile_(expr, is_valid_regex<Expr, char_type>());
|
Chris@16
|
134 return *this;
|
Chris@16
|
135 }
|
Chris@16
|
136
|
Chris@16
|
137 /// Returns the count of capturing sub-expressions in this regular expression
|
Chris@16
|
138 ///
|
Chris@16
|
139 std::size_t mark_count() const
|
Chris@16
|
140 {
|
Chris@16
|
141 return proto::value(*this) ? proto::value(*this)->mark_count_ : 0;
|
Chris@16
|
142 }
|
Chris@16
|
143
|
Chris@16
|
144 /// Returns a token which uniquely identifies this regular expression.
|
Chris@16
|
145 ///
|
Chris@16
|
146 regex_id_type regex_id() const
|
Chris@16
|
147 {
|
Chris@16
|
148 return proto::value(*this) ? proto::value(*this)->xpr_.get() : 0;
|
Chris@16
|
149 }
|
Chris@16
|
150
|
Chris@16
|
151 /// Swaps the contents of this basic_regex object with another.
|
Chris@16
|
152 ///
|
Chris@16
|
153 /// \param that The other basic_regex object.
|
Chris@16
|
154 /// \attention This is a shallow swap that does not do reference tracking.
|
Chris@16
|
155 /// If you embed a basic_regex object by reference in another
|
Chris@16
|
156 /// regular expression and then swap its contents with another
|
Chris@16
|
157 /// basic_regex object, the change will not be visible to the
|
Chris@16
|
158 /// enclosing regular expression. It is done this way to ensure
|
Chris@16
|
159 /// that swap() cannot throw.
|
Chris@16
|
160 /// \throw nothrow
|
Chris@16
|
161 void swap(basic_regex<BidiIter> &that) // throw()
|
Chris@16
|
162 {
|
Chris@16
|
163 proto::value(*this).swap(proto::value(that));
|
Chris@16
|
164 }
|
Chris@16
|
165
|
Chris@16
|
166 /// Factory method for building a regex object from a range of characters.
|
Chris@16
|
167 /// Equivalent to regex_compiler\< BidiIter \>().compile(begin, end, flags);
|
Chris@16
|
168 ///
|
Chris@16
|
169 /// \param begin The beginning of a range of characters representing the
|
Chris@16
|
170 /// regular expression to compile.
|
Chris@16
|
171 /// \param end The end of a range of characters representing the
|
Chris@16
|
172 /// regular expression to compile.
|
Chris@16
|
173 /// \param flags Optional bitmask that determines how the pat string is
|
Chris@16
|
174 /// interpreted. (See syntax_option_type.)
|
Chris@16
|
175 /// \return A basic_regex object corresponding to the regular expression
|
Chris@16
|
176 /// represented by the character range.
|
Chris@16
|
177 /// \pre [begin,end) is a valid range.
|
Chris@16
|
178 /// \pre The range of characters specified by [begin,end) contains a
|
Chris@16
|
179 /// valid string-based representation of a regular expression.
|
Chris@16
|
180 /// \throw regex_error when the range of characters has invalid regular
|
Chris@16
|
181 /// expression syntax.
|
Chris@16
|
182 template<typename InputIter>
|
Chris@16
|
183 static basic_regex<BidiIter> compile(InputIter begin, InputIter end, flag_type flags = regex_constants::ECMAScript)
|
Chris@16
|
184 {
|
Chris@16
|
185 return regex_compiler<BidiIter>().compile(begin, end, flags);
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 /// \overload
|
Chris@16
|
189 ///
|
Chris@16
|
190 template<typename InputRange>
|
Chris@16
|
191 static basic_regex<BidiIter> compile(InputRange const &pat, flag_type flags = regex_constants::ECMAScript)
|
Chris@16
|
192 {
|
Chris@16
|
193 return regex_compiler<BidiIter>().compile(pat, flags);
|
Chris@16
|
194 }
|
Chris@16
|
195
|
Chris@16
|
196 /// \overload
|
Chris@16
|
197 ///
|
Chris@16
|
198 static basic_regex<BidiIter> compile(char_type const *begin, flag_type flags = regex_constants::ECMAScript)
|
Chris@16
|
199 {
|
Chris@16
|
200 return regex_compiler<BidiIter>().compile(begin, flags);
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 /// \overload
|
Chris@16
|
204 ///
|
Chris@16
|
205 static basic_regex<BidiIter> compile(char_type const *begin, std::size_t len, flag_type flags)
|
Chris@16
|
206 {
|
Chris@16
|
207 return regex_compiler<BidiIter>().compile(begin, len, flags);
|
Chris@16
|
208 }
|
Chris@16
|
209
|
Chris@16
|
210 private:
|
Chris@16
|
211 friend struct detail::core_access<BidiIter>;
|
Chris@16
|
212
|
Chris@16
|
213 // Avoid a common programming mistake. Construction from a string is
|
Chris@16
|
214 // ambiguous. It could mean:
|
Chris@16
|
215 // sregex rx = sregex::compile(str); // compile the string into a regex
|
Chris@16
|
216 // or
|
Chris@16
|
217 // sregex rx = as_xpr(str); // treat the string as a literal
|
Chris@16
|
218 // Since there is no easy way to disambiguate, it is disallowed. You must
|
Chris@16
|
219 // say what you mean.
|
Chris@16
|
220
|
Chris@16
|
221 /// INTERNAL ONLY
|
Chris@16
|
222 basic_regex(char_type const *);
|
Chris@16
|
223 /// INTERNAL ONLY
|
Chris@16
|
224 basic_regex(string_type const &);
|
Chris@16
|
225
|
Chris@16
|
226 /// INTERNAL ONLY
|
Chris@16
|
227 bool match_(detail::match_state<BidiIter> &state) const
|
Chris@16
|
228 {
|
Chris@16
|
229 #if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD
|
Chris@16
|
230 bool success = false, stack_error = false;
|
Chris@16
|
231 __try
|
Chris@16
|
232 {
|
Chris@16
|
233 success = proto::value(*this)->xpr_->match(state);
|
Chris@16
|
234 }
|
Chris@16
|
235 __except(_exception_code() == 0xC00000FDUL)
|
Chris@16
|
236 {
|
Chris@16
|
237 stack_error = true;
|
Chris@16
|
238 _resetstkoflw();
|
Chris@16
|
239 }
|
Chris@16
|
240 detail::throw_on_stack_error(stack_error);
|
Chris@16
|
241 return success;
|
Chris@16
|
242 #else
|
Chris@16
|
243 return proto::value(*this)->xpr_->match(state);
|
Chris@16
|
244 #endif
|
Chris@16
|
245 }
|
Chris@16
|
246
|
Chris@16
|
247 // Compiles valid static regexes into a state machine.
|
Chris@16
|
248 /// INTERNAL ONLY
|
Chris@16
|
249 template<typename Expr>
|
Chris@16
|
250 void compile_(Expr const &expr, mpl::true_)
|
Chris@16
|
251 {
|
Chris@16
|
252 detail::static_compile(expr, proto::value(*this).get());
|
Chris@16
|
253 }
|
Chris@16
|
254
|
Chris@16
|
255 // No-op for invalid static regexes.
|
Chris@16
|
256 /// INTERNAL ONLY
|
Chris@16
|
257 template<typename Expr>
|
Chris@16
|
258 void compile_(Expr const &, mpl::false_)
|
Chris@16
|
259 {
|
Chris@16
|
260 }
|
Chris@16
|
261 };
|
Chris@16
|
262
|
Chris@16
|
263 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
Chris@16
|
264 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::ECMAScript;
|
Chris@16
|
265 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::icase;
|
Chris@16
|
266 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::nosubs;
|
Chris@16
|
267 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::optimize;
|
Chris@16
|
268 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::collate;
|
Chris@16
|
269 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::single_line;
|
Chris@16
|
270 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::not_dot_null;
|
Chris@16
|
271 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::not_dot_newline;
|
Chris@16
|
272 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::ignore_white_space;
|
Chris@16
|
273 #endif
|
Chris@16
|
274
|
Chris@16
|
275 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
276 // swap
|
Chris@16
|
277 /// \brief Swaps the contents of two basic_regex objects.
|
Chris@16
|
278 /// \param left The first basic_regex object.
|
Chris@16
|
279 /// \param right The second basic_regex object.
|
Chris@16
|
280 /// \attention This is a shallow swap that does not do reference tracking.
|
Chris@16
|
281 /// If you embed a basic_regex object by reference in another
|
Chris@16
|
282 /// regular expression and then swap its contents with another
|
Chris@16
|
283 /// basic_regex object, the change will not be visible to the
|
Chris@16
|
284 /// enclosing regular expression. It is done this way to ensure
|
Chris@16
|
285 /// that swap() cannot throw.
|
Chris@16
|
286 /// \throw nothrow
|
Chris@16
|
287 template<typename BidiIter>
|
Chris@16
|
288 inline void swap(basic_regex<BidiIter> &left, basic_regex<BidiIter> &right) // throw()
|
Chris@16
|
289 {
|
Chris@16
|
290 left.swap(right);
|
Chris@16
|
291 }
|
Chris@16
|
292
|
Chris@16
|
293 }} // namespace boost::xpressive
|
Chris@16
|
294
|
Chris@16
|
295 #endif // BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005
|