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

source code of boost/boost/xpressive/basic_regex.hpp