Chris@16
|
1 /*
|
Chris@16
|
2 *
|
Chris@16
|
3 * Copyright (c) 2002
|
Chris@16
|
4 * John Maddock
|
Chris@16
|
5 *
|
Chris@16
|
6 * Use, modification and distribution are subject to the
|
Chris@16
|
7 * Boost 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 */
|
Chris@16
|
11
|
Chris@16
|
12 /*
|
Chris@16
|
13 * LOCATION: see http://www.boost.org for most recent version.
|
Chris@16
|
14 * FILE perl_matcher_common.cpp
|
Chris@16
|
15 * VERSION see <boost/version.hpp>
|
Chris@16
|
16 * DESCRIPTION: Definitions of perl_matcher member functions that are
|
Chris@16
|
17 * specific to the recursive implementation.
|
Chris@16
|
18 */
|
Chris@16
|
19
|
Chris@16
|
20 #ifndef BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP
|
Chris@16
|
21 #define BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP
|
Chris@16
|
22
|
Chris@16
|
23 #ifdef BOOST_MSVC
|
Chris@16
|
24 #pragma warning(push)
|
Chris@16
|
25 #pragma warning(disable: 4103)
|
Chris@16
|
26 #endif
|
Chris@16
|
27 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
28 # include BOOST_ABI_PREFIX
|
Chris@16
|
29 #endif
|
Chris@16
|
30 #ifdef BOOST_MSVC
|
Chris@16
|
31 #pragma warning(pop)
|
Chris@16
|
32 #endif
|
Chris@16
|
33
|
Chris@16
|
34 #ifdef BOOST_MSVC
|
Chris@16
|
35 #pragma warning(push)
|
Chris@16
|
36 #pragma warning(disable: 4800)
|
Chris@16
|
37 #endif
|
Chris@16
|
38
|
Chris@16
|
39 namespace boost{
|
Chris@16
|
40 namespace re_detail{
|
Chris@16
|
41
|
Chris@16
|
42 template <class BidiIterator>
|
Chris@16
|
43 class backup_subex
|
Chris@16
|
44 {
|
Chris@16
|
45 int index;
|
Chris@16
|
46 sub_match<BidiIterator> sub;
|
Chris@16
|
47 public:
|
Chris@16
|
48 template <class A>
|
Chris@16
|
49 backup_subex(const match_results<BidiIterator, A>& w, int i)
|
Chris@16
|
50 : index(i), sub(w[i], false) {}
|
Chris@16
|
51 template <class A>
|
Chris@16
|
52 void restore(match_results<BidiIterator, A>& w)
|
Chris@16
|
53 {
|
Chris@16
|
54 w.set_first(sub.first, index, index == 0);
|
Chris@16
|
55 w.set_second(sub.second, index, sub.matched, index == 0);
|
Chris@16
|
56 }
|
Chris@16
|
57 const sub_match<BidiIterator>& get() { return sub; }
|
Chris@16
|
58 };
|
Chris@16
|
59
|
Chris@16
|
60 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
61 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
Chris@16
|
62 {
|
Chris@16
|
63 static matcher_proc_type const s_match_vtable[30] =
|
Chris@16
|
64 {
|
Chris@16
|
65 (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
|
Chris@16
|
66 &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
|
Chris@16
|
67 &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
|
Chris@16
|
68 &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
|
Chris@16
|
69 &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
|
Chris@16
|
70 &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
|
Chris@16
|
71 &perl_matcher<BidiIterator, Allocator, traits>::match_match,
|
Chris@16
|
72 &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
|
Chris@16
|
73 &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
|
Chris@16
|
74 &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
|
Chris@16
|
75 &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
|
Chris@16
|
76 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
|
Chris@16
|
77 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
|
Chris@16
|
78 &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
|
Chris@16
|
79 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
|
Chris@16
|
80 &perl_matcher<BidiIterator, Allocator, traits>::match_set,
|
Chris@16
|
81 &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
|
Chris@16
|
82 &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
|
Chris@16
|
83 &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
|
Chris@16
|
84 &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
|
Chris@16
|
85 &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
|
Chris@16
|
86 &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
|
Chris@16
|
87 // Although this next line *should* be evaluated at compile time, in practice
|
Chris@16
|
88 // some compilers (VC++) emit run-time initialisation which breaks thread
|
Chris@16
|
89 // safety, so use a dispatch function instead:
|
Chris@16
|
90 //(::boost::is_random_access_iterator<BidiIterator>::value ? &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast : &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow),
|
Chris@16
|
91 &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
|
Chris@16
|
92 &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
|
Chris@16
|
93 &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
|
Chris@16
|
94 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
|
Chris@16
|
95 &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
|
Chris@16
|
96 &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
|
Chris@16
|
97 &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
|
Chris@16
|
98 &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
|
Chris@16
|
99 };
|
Chris@16
|
100
|
Chris@16
|
101 if(state_count > max_state_count)
|
Chris@16
|
102 raise_error(traits_inst, regex_constants::error_complexity);
|
Chris@16
|
103 while(pstate)
|
Chris@16
|
104 {
|
Chris@16
|
105 matcher_proc_type proc = s_match_vtable[pstate->type];
|
Chris@16
|
106 ++state_count;
|
Chris@16
|
107 if(!(this->*proc)())
|
Chris@16
|
108 {
|
Chris@16
|
109 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
|
Chris@16
|
110 m_has_partial_match = true;
|
Chris@16
|
111 return 0;
|
Chris@16
|
112 }
|
Chris@16
|
113 }
|
Chris@16
|
114 return true;
|
Chris@16
|
115 }
|
Chris@16
|
116
|
Chris@16
|
117 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
118 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
|
Chris@16
|
119 {
|
Chris@16
|
120 int index = static_cast<const re_brace*>(pstate)->index;
|
Chris@16
|
121 icase = static_cast<const re_brace*>(pstate)->icase;
|
Chris@16
|
122 bool r = true;
|
Chris@16
|
123 switch(index)
|
Chris@16
|
124 {
|
Chris@16
|
125 case 0:
|
Chris@16
|
126 pstate = pstate->next.p;
|
Chris@16
|
127 break;
|
Chris@16
|
128 case -1:
|
Chris@16
|
129 case -2:
|
Chris@16
|
130 {
|
Chris@16
|
131 // forward lookahead assert:
|
Chris@16
|
132 BidiIterator old_position(position);
|
Chris@16
|
133 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
|
Chris@16
|
134 pstate = pstate->next.p->next.p;
|
Chris@16
|
135 r = match_all_states();
|
Chris@16
|
136 pstate = next_pstate;
|
Chris@16
|
137 position = old_position;
|
Chris@16
|
138 if((r && (index != -1)) || (!r && (index != -2)))
|
Chris@16
|
139 r = false;
|
Chris@16
|
140 else
|
Chris@16
|
141 r = true;
|
Chris@16
|
142 break;
|
Chris@16
|
143 }
|
Chris@16
|
144 case -3:
|
Chris@16
|
145 {
|
Chris@16
|
146 // independent sub-expression:
|
Chris@16
|
147 bool old_independent = m_independent;
|
Chris@16
|
148 m_independent = true;
|
Chris@16
|
149 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
|
Chris@16
|
150 pstate = pstate->next.p->next.p;
|
Chris@16
|
151 r = match_all_states();
|
Chris@16
|
152 pstate = next_pstate;
|
Chris@16
|
153 m_independent = old_independent;
|
Chris@16
|
154 #ifdef BOOST_REGEX_MATCH_EXTRA
|
Chris@16
|
155 if(r && (m_match_flags & match_extra))
|
Chris@16
|
156 {
|
Chris@16
|
157 //
|
Chris@16
|
158 // our captures have been stored in *m_presult
|
Chris@16
|
159 // we need to unpack them, and insert them
|
Chris@16
|
160 // back in the right order when we unwind the stack:
|
Chris@16
|
161 //
|
Chris@16
|
162 unsigned i;
|
Chris@16
|
163 match_results<BidiIterator, Allocator> tm(*m_presult);
|
Chris@16
|
164 for(i = 0; i < tm.size(); ++i)
|
Chris@16
|
165 (*m_presult)[i].get_captures().clear();
|
Chris@16
|
166 // match everything else:
|
Chris@16
|
167 r = match_all_states();
|
Chris@16
|
168 // now place the stored captures back:
|
Chris@16
|
169 for(i = 0; i < tm.size(); ++i)
|
Chris@16
|
170 {
|
Chris@16
|
171 typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
|
Chris@16
|
172 seq& s1 = (*m_presult)[i].get_captures();
|
Chris@16
|
173 const seq& s2 = tm[i].captures();
|
Chris@16
|
174 s1.insert(
|
Chris@16
|
175 s1.end(),
|
Chris@16
|
176 s2.begin(),
|
Chris@16
|
177 s2.end());
|
Chris@16
|
178 }
|
Chris@16
|
179 }
|
Chris@16
|
180 #endif
|
Chris@16
|
181 break;
|
Chris@16
|
182 }
|
Chris@16
|
183 case -4:
|
Chris@16
|
184 {
|
Chris@16
|
185 // conditional expression:
|
Chris@16
|
186 const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
|
Chris@16
|
187 BOOST_ASSERT(alt->type == syntax_element_alt);
|
Chris@16
|
188 pstate = alt->next.p;
|
Chris@16
|
189 if(pstate->type == syntax_element_assert_backref)
|
Chris@16
|
190 {
|
Chris@16
|
191 if(!match_assert_backref())
|
Chris@16
|
192 pstate = alt->alt.p;
|
Chris@16
|
193 break;
|
Chris@16
|
194 }
|
Chris@16
|
195 else
|
Chris@16
|
196 {
|
Chris@16
|
197 // zero width assertion, have to match this recursively:
|
Chris@16
|
198 BOOST_ASSERT(pstate->type == syntax_element_startmark);
|
Chris@16
|
199 bool negated = static_cast<const re_brace*>(pstate)->index == -2;
|
Chris@16
|
200 BidiIterator saved_position = position;
|
Chris@16
|
201 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
|
Chris@16
|
202 pstate = pstate->next.p->next.p;
|
Chris@16
|
203 bool res = match_all_states();
|
Chris@16
|
204 position = saved_position;
|
Chris@16
|
205 if(negated)
|
Chris@16
|
206 res = !res;
|
Chris@16
|
207 if(res)
|
Chris@16
|
208 pstate = next_pstate;
|
Chris@16
|
209 else
|
Chris@16
|
210 pstate = alt->alt.p;
|
Chris@16
|
211 break;
|
Chris@16
|
212 }
|
Chris@16
|
213 }
|
Chris@16
|
214 case -5:
|
Chris@16
|
215 {
|
Chris@16
|
216 // Reset start of $0, since we have a \K escape
|
Chris@16
|
217 backup_subex<BidiIterator> sub(*m_presult, 0);
|
Chris@16
|
218 m_presult->set_first(position, 0, true);
|
Chris@16
|
219 pstate = pstate->next.p;
|
Chris@16
|
220 r = match_all_states();
|
Chris@16
|
221 if(r == false)
|
Chris@16
|
222 sub.restore(*m_presult);
|
Chris@16
|
223 break;
|
Chris@16
|
224 }
|
Chris@16
|
225 default:
|
Chris@16
|
226 {
|
Chris@16
|
227 BOOST_ASSERT(index > 0);
|
Chris@16
|
228 if((m_match_flags & match_nosubs) == 0)
|
Chris@16
|
229 {
|
Chris@16
|
230 backup_subex<BidiIterator> sub(*m_presult, index);
|
Chris@16
|
231 m_presult->set_first(position, index);
|
Chris@16
|
232 pstate = pstate->next.p;
|
Chris@16
|
233 r = match_all_states();
|
Chris@16
|
234 if(r == false)
|
Chris@16
|
235 sub.restore(*m_presult);
|
Chris@16
|
236 #ifdef BOOST_REGEX_MATCH_EXTRA
|
Chris@16
|
237 //
|
Chris@16
|
238 // we have a match, push the capture information onto the stack:
|
Chris@16
|
239 //
|
Chris@16
|
240 else if(sub.get().matched && (match_extra & m_match_flags))
|
Chris@16
|
241 ((*m_presult)[index]).get_captures().push_back(sub.get());
|
Chris@16
|
242 #endif
|
Chris@16
|
243 }
|
Chris@16
|
244 else
|
Chris@16
|
245 {
|
Chris@16
|
246 pstate = pstate->next.p;
|
Chris@16
|
247 }
|
Chris@16
|
248 break;
|
Chris@16
|
249 }
|
Chris@16
|
250 }
|
Chris@16
|
251 return r;
|
Chris@16
|
252 }
|
Chris@16
|
253
|
Chris@16
|
254 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
255 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
|
Chris@16
|
256 {
|
Chris@16
|
257 bool take_first, take_second;
|
Chris@16
|
258 const re_alt* jmp = static_cast<const re_alt*>(pstate);
|
Chris@16
|
259
|
Chris@16
|
260 // find out which of these two alternatives we need to take:
|
Chris@16
|
261 if(position == last)
|
Chris@16
|
262 {
|
Chris@16
|
263 take_first = jmp->can_be_null & mask_take;
|
Chris@16
|
264 take_second = jmp->can_be_null & mask_skip;
|
Chris@16
|
265 }
|
Chris@16
|
266 else
|
Chris@16
|
267 {
|
Chris@16
|
268 take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
|
Chris@16
|
269 take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
|
Chris@16
|
270 }
|
Chris@16
|
271
|
Chris@16
|
272 if(take_first)
|
Chris@16
|
273 {
|
Chris@16
|
274 // we can take the first alternative,
|
Chris@16
|
275 // see if we need to push next alternative:
|
Chris@16
|
276 if(take_second)
|
Chris@16
|
277 {
|
Chris@16
|
278 BidiIterator oldposition(position);
|
Chris@16
|
279 const re_syntax_base* old_pstate = jmp->alt.p;
|
Chris@16
|
280 pstate = pstate->next.p;
|
Chris@16
|
281 if(!match_all_states())
|
Chris@16
|
282 {
|
Chris@16
|
283 pstate = old_pstate;
|
Chris@16
|
284 position = oldposition;
|
Chris@16
|
285 }
|
Chris@16
|
286 return true;
|
Chris@16
|
287 }
|
Chris@16
|
288 pstate = pstate->next.p;
|
Chris@16
|
289 return true;
|
Chris@16
|
290 }
|
Chris@16
|
291 if(take_second)
|
Chris@16
|
292 {
|
Chris@16
|
293 pstate = jmp->alt.p;
|
Chris@16
|
294 return true;
|
Chris@16
|
295 }
|
Chris@16
|
296 return false; // neither option is possible
|
Chris@16
|
297 }
|
Chris@16
|
298
|
Chris@16
|
299 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
300 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
|
Chris@16
|
301 {
|
Chris@16
|
302 #ifdef BOOST_MSVC
|
Chris@16
|
303 #pragma warning(push)
|
Chris@16
|
304 #pragma warning(disable:4127 4244)
|
Chris@16
|
305 #endif
|
Chris@16
|
306 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
307 //
|
Chris@16
|
308 // Always copy the repeat count, so that the state is restored
|
Chris@16
|
309 // when we exit this scope:
|
Chris@16
|
310 //
|
Chris@16
|
311 repeater_count<BidiIterator> r(rep->state_id, &next_count, position);
|
Chris@16
|
312 //
|
Chris@16
|
313 // If we've had at least one repeat already, and the last one
|
Chris@16
|
314 // matched the NULL string then set the repeat count to
|
Chris@16
|
315 // maximum:
|
Chris@16
|
316 //
|
Chris@16
|
317 next_count->check_null_repeat(position, rep->max);
|
Chris@16
|
318
|
Chris@16
|
319 // find out which of these two alternatives we need to take:
|
Chris@16
|
320 bool take_first, take_second;
|
Chris@16
|
321 if(position == last)
|
Chris@16
|
322 {
|
Chris@16
|
323 take_first = rep->can_be_null & mask_take;
|
Chris@16
|
324 take_second = rep->can_be_null & mask_skip;
|
Chris@16
|
325 }
|
Chris@16
|
326 else
|
Chris@16
|
327 {
|
Chris@16
|
328 take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
|
Chris@16
|
329 take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
|
Chris@16
|
330 }
|
Chris@16
|
331
|
Chris@16
|
332 if(next_count->get_count() < rep->min)
|
Chris@16
|
333 {
|
Chris@16
|
334 // we must take the repeat:
|
Chris@16
|
335 if(take_first)
|
Chris@16
|
336 {
|
Chris@16
|
337 // increase the counter:
|
Chris@16
|
338 ++(*next_count);
|
Chris@16
|
339 pstate = rep->next.p;
|
Chris@16
|
340 return match_all_states();
|
Chris@16
|
341 }
|
Chris@16
|
342 return false;
|
Chris@16
|
343 }
|
Chris@16
|
344 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
345 if(greedy)
|
Chris@16
|
346 {
|
Chris@16
|
347 // try and take the repeat if we can:
|
Chris@16
|
348 if((next_count->get_count() < rep->max) && take_first)
|
Chris@16
|
349 {
|
Chris@16
|
350 // store position in case we fail:
|
Chris@16
|
351 BidiIterator pos = position;
|
Chris@16
|
352 // increase the counter:
|
Chris@16
|
353 ++(*next_count);
|
Chris@16
|
354 pstate = rep->next.p;
|
Chris@16
|
355 if(match_all_states())
|
Chris@16
|
356 return true;
|
Chris@16
|
357 // failed repeat, reset posistion and fall through for alternative:
|
Chris@16
|
358 position = pos;
|
Chris@16
|
359 }
|
Chris@16
|
360 if(take_second)
|
Chris@16
|
361 {
|
Chris@16
|
362 pstate = rep->alt.p;
|
Chris@16
|
363 return true;
|
Chris@16
|
364 }
|
Chris@16
|
365 return false; // can't take anything, fail...
|
Chris@16
|
366 }
|
Chris@16
|
367 else // non-greedy
|
Chris@16
|
368 {
|
Chris@16
|
369 // try and skip the repeat if we can:
|
Chris@16
|
370 if(take_second)
|
Chris@16
|
371 {
|
Chris@16
|
372 // store position in case we fail:
|
Chris@16
|
373 BidiIterator pos = position;
|
Chris@16
|
374 pstate = rep->alt.p;
|
Chris@16
|
375 if(match_all_states())
|
Chris@16
|
376 return true;
|
Chris@16
|
377 // failed alternative, reset posistion and fall through for repeat:
|
Chris@16
|
378 position = pos;
|
Chris@16
|
379 }
|
Chris@16
|
380 if((next_count->get_count() < rep->max) && take_first)
|
Chris@16
|
381 {
|
Chris@16
|
382 // increase the counter:
|
Chris@16
|
383 ++(*next_count);
|
Chris@16
|
384 pstate = rep->next.p;
|
Chris@16
|
385 return match_all_states();
|
Chris@16
|
386 }
|
Chris@16
|
387 }
|
Chris@16
|
388 return false;
|
Chris@16
|
389 #ifdef BOOST_MSVC
|
Chris@16
|
390 #pragma warning(pop)
|
Chris@16
|
391 #endif
|
Chris@16
|
392 }
|
Chris@16
|
393
|
Chris@16
|
394 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
395 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
|
Chris@16
|
396 {
|
Chris@16
|
397 #ifdef BOOST_MSVC
|
Chris@16
|
398 #pragma warning(push)
|
Chris@16
|
399 #pragma warning(disable:4127)
|
Chris@16
|
400 #endif
|
Chris@16
|
401 unsigned count = 0;
|
Chris@16
|
402 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
403 re_syntax_base* psingle = rep->next.p;
|
Chris@16
|
404 // match compulsary repeats first:
|
Chris@16
|
405 while(count < rep->min)
|
Chris@16
|
406 {
|
Chris@16
|
407 pstate = psingle;
|
Chris@16
|
408 if(!match_wild())
|
Chris@16
|
409 return false;
|
Chris@16
|
410 ++count;
|
Chris@16
|
411 }
|
Chris@16
|
412 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
413 if(greedy)
|
Chris@16
|
414 {
|
Chris@16
|
415 // normal repeat:
|
Chris@16
|
416 while(count < rep->max)
|
Chris@16
|
417 {
|
Chris@16
|
418 pstate = psingle;
|
Chris@16
|
419 if(!match_wild())
|
Chris@16
|
420 break;
|
Chris@16
|
421 ++count;
|
Chris@16
|
422 }
|
Chris@16
|
423 if((rep->leading) && (count < rep->max))
|
Chris@16
|
424 restart = position;
|
Chris@16
|
425 pstate = rep;
|
Chris@16
|
426 return backtrack_till_match(count - rep->min);
|
Chris@16
|
427 }
|
Chris@16
|
428 else
|
Chris@16
|
429 {
|
Chris@16
|
430 // non-greedy, keep trying till we get a match:
|
Chris@16
|
431 BidiIterator save_pos;
|
Chris@16
|
432 do
|
Chris@16
|
433 {
|
Chris@16
|
434 if((rep->leading) && (rep->max == UINT_MAX))
|
Chris@16
|
435 restart = position;
|
Chris@16
|
436 pstate = rep->alt.p;
|
Chris@16
|
437 save_pos = position;
|
Chris@16
|
438 ++state_count;
|
Chris@16
|
439 if(match_all_states())
|
Chris@16
|
440 return true;
|
Chris@16
|
441 if(count >= rep->max)
|
Chris@16
|
442 return false;
|
Chris@16
|
443 ++count;
|
Chris@16
|
444 pstate = psingle;
|
Chris@16
|
445 position = save_pos;
|
Chris@16
|
446 if(!match_wild())
|
Chris@16
|
447 return false;
|
Chris@16
|
448 }while(true);
|
Chris@16
|
449 }
|
Chris@16
|
450 #ifdef BOOST_MSVC
|
Chris@16
|
451 #pragma warning(pop)
|
Chris@16
|
452 #endif
|
Chris@16
|
453 }
|
Chris@16
|
454
|
Chris@16
|
455 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
456 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
|
Chris@16
|
457 {
|
Chris@16
|
458 #ifdef BOOST_MSVC
|
Chris@16
|
459 #pragma warning(push)
|
Chris@16
|
460 #pragma warning(disable:4127)
|
Chris@16
|
461 #endif
|
Chris@16
|
462 if(m_match_flags & match_not_dot_null)
|
Chris@16
|
463 return match_dot_repeat_slow();
|
Chris@16
|
464 if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
|
Chris@16
|
465 return match_dot_repeat_slow();
|
Chris@16
|
466 //
|
Chris@16
|
467 // start by working out how much we can skip:
|
Chris@16
|
468 //
|
Chris@16
|
469 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
470 #ifdef BOOST_MSVC
|
Chris@16
|
471 #pragma warning(push)
|
Chris@16
|
472 #pragma warning(disable:4267)
|
Chris@16
|
473 #endif
|
Chris@16
|
474 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
475 std::size_t count = (std::min)(static_cast<std::size_t>(::boost::re_detail::distance(position, last)), static_cast<std::size_t>(greedy ? rep->max : rep->min));
|
Chris@16
|
476 if(rep->min > count)
|
Chris@16
|
477 {
|
Chris@16
|
478 position = last;
|
Chris@16
|
479 return false; // not enough text left to match
|
Chris@16
|
480 }
|
Chris@16
|
481 std::advance(position, count);
|
Chris@16
|
482 #ifdef BOOST_MSVC
|
Chris@16
|
483 #pragma warning(pop)
|
Chris@16
|
484 #endif
|
Chris@16
|
485 if((rep->leading) && (count < rep->max) && greedy)
|
Chris@16
|
486 restart = position;
|
Chris@16
|
487 if(greedy)
|
Chris@16
|
488 return backtrack_till_match(count - rep->min);
|
Chris@16
|
489
|
Chris@16
|
490 // non-greedy, keep trying till we get a match:
|
Chris@16
|
491 BidiIterator save_pos;
|
Chris@16
|
492 do
|
Chris@16
|
493 {
|
Chris@16
|
494 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
495 {
|
Chris@16
|
496 ++position;
|
Chris@16
|
497 ++count;
|
Chris@16
|
498 }
|
Chris@16
|
499 if((rep->leading) && (rep->max == UINT_MAX))
|
Chris@16
|
500 restart = position;
|
Chris@16
|
501 pstate = rep->alt.p;
|
Chris@16
|
502 save_pos = position;
|
Chris@16
|
503 ++state_count;
|
Chris@16
|
504 if(match_all_states())
|
Chris@16
|
505 return true;
|
Chris@16
|
506 if(count >= rep->max)
|
Chris@16
|
507 return false;
|
Chris@16
|
508 if(save_pos == last)
|
Chris@16
|
509 return false;
|
Chris@16
|
510 position = ++save_pos;
|
Chris@16
|
511 ++count;
|
Chris@16
|
512 }while(true);
|
Chris@16
|
513 #ifdef BOOST_MSVC
|
Chris@16
|
514 #pragma warning(pop)
|
Chris@16
|
515 #endif
|
Chris@16
|
516 }
|
Chris@16
|
517
|
Chris@16
|
518 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
519 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
|
Chris@16
|
520 {
|
Chris@16
|
521 #ifdef BOOST_MSVC
|
Chris@16
|
522 #pragma warning(push)
|
Chris@16
|
523 #pragma warning(disable:4127)
|
Chris@16
|
524 #pragma warning(disable:4267)
|
Chris@16
|
525 #endif
|
Chris@16
|
526 #ifdef __BORLANDC__
|
Chris@16
|
527 #pragma option push -w-8008 -w-8066 -w-8004
|
Chris@16
|
528 #endif
|
Chris@16
|
529 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
530 BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
|
Chris@16
|
531 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
|
Chris@16
|
532 //
|
Chris@16
|
533 // start by working out how much we can skip:
|
Chris@16
|
534 //
|
Chris@16
|
535 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
536 std::size_t count, desired;
|
Chris@16
|
537 if(::boost::is_random_access_iterator<BidiIterator>::value)
|
Chris@16
|
538 {
|
Chris@16
|
539 desired =
|
Chris@16
|
540 (std::min)(
|
Chris@16
|
541 (std::size_t)(greedy ? rep->max : rep->min),
|
Chris@16
|
542 (std::size_t)::boost::re_detail::distance(position, last));
|
Chris@16
|
543 count = desired;
|
Chris@16
|
544 ++desired;
|
Chris@16
|
545 if(icase)
|
Chris@16
|
546 {
|
Chris@16
|
547 while(--desired && (traits_inst.translate_nocase(*position) == what))
|
Chris@16
|
548 {
|
Chris@16
|
549 ++position;
|
Chris@16
|
550 }
|
Chris@16
|
551 }
|
Chris@16
|
552 else
|
Chris@16
|
553 {
|
Chris@16
|
554 while(--desired && (traits_inst.translate(*position) == what))
|
Chris@16
|
555 {
|
Chris@16
|
556 ++position;
|
Chris@16
|
557 }
|
Chris@16
|
558 }
|
Chris@16
|
559 count = count - desired;
|
Chris@16
|
560 }
|
Chris@16
|
561 else
|
Chris@16
|
562 {
|
Chris@16
|
563 count = 0;
|
Chris@16
|
564 desired = greedy ? rep->max : rep->min;
|
Chris@16
|
565 while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
|
Chris@16
|
566 {
|
Chris@16
|
567 ++position;
|
Chris@16
|
568 ++count;
|
Chris@16
|
569 }
|
Chris@16
|
570 }
|
Chris@16
|
571 if((rep->leading) && (count < rep->max) && greedy)
|
Chris@16
|
572 restart = position;
|
Chris@16
|
573 if(count < rep->min)
|
Chris@16
|
574 return false;
|
Chris@16
|
575
|
Chris@16
|
576 if(greedy)
|
Chris@16
|
577 return backtrack_till_match(count - rep->min);
|
Chris@16
|
578
|
Chris@16
|
579 // non-greedy, keep trying till we get a match:
|
Chris@16
|
580 BidiIterator save_pos;
|
Chris@16
|
581 do
|
Chris@16
|
582 {
|
Chris@16
|
583 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
584 {
|
Chris@16
|
585 if((traits_inst.translate(*position, icase) == what))
|
Chris@16
|
586 {
|
Chris@16
|
587 ++position;
|
Chris@16
|
588 ++count;
|
Chris@16
|
589 }
|
Chris@16
|
590 else
|
Chris@16
|
591 return false; // counldn't repeat even though it was the only option
|
Chris@16
|
592 }
|
Chris@16
|
593 if((rep->leading) && (rep->max == UINT_MAX))
|
Chris@16
|
594 restart = position;
|
Chris@16
|
595 pstate = rep->alt.p;
|
Chris@16
|
596 save_pos = position;
|
Chris@16
|
597 ++state_count;
|
Chris@16
|
598 if(match_all_states())
|
Chris@16
|
599 return true;
|
Chris@16
|
600 if(count >= rep->max)
|
Chris@16
|
601 return false;
|
Chris@16
|
602 position = save_pos;
|
Chris@16
|
603 if(position == last)
|
Chris@16
|
604 return false;
|
Chris@16
|
605 if(traits_inst.translate(*position, icase) == what)
|
Chris@16
|
606 {
|
Chris@16
|
607 ++position;
|
Chris@16
|
608 ++count;
|
Chris@16
|
609 }
|
Chris@16
|
610 else
|
Chris@16
|
611 {
|
Chris@16
|
612 return false;
|
Chris@16
|
613 }
|
Chris@16
|
614 }while(true);
|
Chris@16
|
615 #ifdef __BORLANDC__
|
Chris@16
|
616 #pragma option pop
|
Chris@16
|
617 #endif
|
Chris@16
|
618 #ifdef BOOST_MSVC
|
Chris@16
|
619 #pragma warning(pop)
|
Chris@16
|
620 #endif
|
Chris@16
|
621 }
|
Chris@16
|
622
|
Chris@16
|
623 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
624 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
|
Chris@16
|
625 {
|
Chris@16
|
626 #ifdef BOOST_MSVC
|
Chris@16
|
627 #pragma warning(push)
|
Chris@16
|
628 #pragma warning(disable:4127)
|
Chris@16
|
629 #endif
|
Chris@16
|
630 #ifdef __BORLANDC__
|
Chris@16
|
631 #pragma option push -w-8008 -w-8066 -w-8004
|
Chris@16
|
632 #endif
|
Chris@16
|
633 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
634 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
|
Chris@16
|
635 unsigned count = 0;
|
Chris@16
|
636 //
|
Chris@16
|
637 // start by working out how much we can skip:
|
Chris@16
|
638 //
|
Chris@16
|
639 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
640 std::size_t desired = greedy ? rep->max : rep->min;
|
Chris@16
|
641 if(::boost::is_random_access_iterator<BidiIterator>::value)
|
Chris@16
|
642 {
|
Chris@16
|
643 BidiIterator end = position;
|
Chris@16
|
644 // Move end forward by "desired", preferably without using distance or advance if we can
|
Chris@16
|
645 // as these can be slow for some iterator types.
|
Chris@16
|
646 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
|
Chris@16
|
647 if(desired >= len)
|
Chris@16
|
648 end = last;
|
Chris@16
|
649 else
|
Chris@16
|
650 std::advance(end, desired);
|
Chris@16
|
651 BidiIterator origin(position);
|
Chris@16
|
652 while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
|
Chris@16
|
653 {
|
Chris@16
|
654 ++position;
|
Chris@16
|
655 }
|
Chris@16
|
656 count = (unsigned)::boost::re_detail::distance(origin, position);
|
Chris@16
|
657 }
|
Chris@16
|
658 else
|
Chris@16
|
659 {
|
Chris@16
|
660 while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
|
Chris@16
|
661 {
|
Chris@16
|
662 ++position;
|
Chris@16
|
663 ++count;
|
Chris@16
|
664 }
|
Chris@16
|
665 }
|
Chris@16
|
666 if((rep->leading) && (count < rep->max) && greedy)
|
Chris@16
|
667 restart = position;
|
Chris@16
|
668 if(count < rep->min)
|
Chris@16
|
669 return false;
|
Chris@16
|
670
|
Chris@16
|
671 if(greedy)
|
Chris@16
|
672 return backtrack_till_match(count - rep->min);
|
Chris@16
|
673
|
Chris@16
|
674 // non-greedy, keep trying till we get a match:
|
Chris@16
|
675 BidiIterator save_pos;
|
Chris@16
|
676 do
|
Chris@16
|
677 {
|
Chris@16
|
678 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
679 {
|
Chris@16
|
680 if(map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
|
Chris@16
|
681 {
|
Chris@16
|
682 ++position;
|
Chris@16
|
683 ++count;
|
Chris@16
|
684 }
|
Chris@16
|
685 else
|
Chris@16
|
686 return false; // counldn't repeat even though it was the only option
|
Chris@16
|
687 }
|
Chris@16
|
688 if((rep->leading) && (rep->max == UINT_MAX))
|
Chris@16
|
689 restart = position;
|
Chris@16
|
690 pstate = rep->alt.p;
|
Chris@16
|
691 save_pos = position;
|
Chris@16
|
692 ++state_count;
|
Chris@16
|
693 if(match_all_states())
|
Chris@16
|
694 return true;
|
Chris@16
|
695 if(count >= rep->max)
|
Chris@16
|
696 return false;
|
Chris@16
|
697 position = save_pos;
|
Chris@16
|
698 if(position == last)
|
Chris@16
|
699 return false;
|
Chris@16
|
700 if(map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
|
Chris@16
|
701 {
|
Chris@16
|
702 ++position;
|
Chris@16
|
703 ++count;
|
Chris@16
|
704 }
|
Chris@16
|
705 else
|
Chris@16
|
706 {
|
Chris@16
|
707 return false;
|
Chris@16
|
708 }
|
Chris@16
|
709 }while(true);
|
Chris@16
|
710 #ifdef __BORLANDC__
|
Chris@16
|
711 #pragma option pop
|
Chris@16
|
712 #endif
|
Chris@16
|
713 #ifdef BOOST_MSVC
|
Chris@16
|
714 #pragma warning(pop)
|
Chris@16
|
715 #endif
|
Chris@16
|
716 }
|
Chris@16
|
717
|
Chris@16
|
718 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
719 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
Chris@16
|
720 {
|
Chris@16
|
721 #ifdef BOOST_MSVC
|
Chris@16
|
722 #pragma warning(push)
|
Chris@16
|
723 #pragma warning(disable:4127)
|
Chris@16
|
724 #endif
|
Chris@16
|
725 #ifdef __BORLANDC__
|
Chris@16
|
726 #pragma option push -w-8008 -w-8066 -w-8004
|
Chris@16
|
727 #endif
|
Chris@16
|
728 typedef typename traits::char_class_type char_class_type;
|
Chris@16
|
729 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
730 const re_set_long<char_class_type>* set = static_cast<const re_set_long<char_class_type>*>(pstate->next.p);
|
Chris@16
|
731 unsigned count = 0;
|
Chris@16
|
732 //
|
Chris@16
|
733 // start by working out how much we can skip:
|
Chris@16
|
734 //
|
Chris@16
|
735 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
736 std::size_t desired = greedy ? rep->max : rep->min;
|
Chris@16
|
737 if(::boost::is_random_access_iterator<BidiIterator>::value)
|
Chris@16
|
738 {
|
Chris@16
|
739 BidiIterator end = position;
|
Chris@16
|
740 // Move end forward by "desired", preferably without using distance or advance if we can
|
Chris@16
|
741 // as these can be slow for some iterator types.
|
Chris@16
|
742 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
|
Chris@16
|
743 if(desired >= len)
|
Chris@16
|
744 end = last;
|
Chris@16
|
745 else
|
Chris@16
|
746 std::advance(end, desired);
|
Chris@16
|
747 BidiIterator origin(position);
|
Chris@16
|
748 while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
|
Chris@16
|
749 {
|
Chris@16
|
750 ++position;
|
Chris@16
|
751 }
|
Chris@16
|
752 count = (unsigned)::boost::re_detail::distance(origin, position);
|
Chris@16
|
753 }
|
Chris@16
|
754 else
|
Chris@16
|
755 {
|
Chris@16
|
756 while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
|
Chris@16
|
757 {
|
Chris@16
|
758 ++position;
|
Chris@16
|
759 ++count;
|
Chris@16
|
760 }
|
Chris@16
|
761 }
|
Chris@16
|
762 if((rep->leading) && (count < rep->max) && greedy)
|
Chris@16
|
763 restart = position;
|
Chris@16
|
764 if(count < rep->min)
|
Chris@16
|
765 return false;
|
Chris@16
|
766
|
Chris@16
|
767 if(greedy)
|
Chris@16
|
768 return backtrack_till_match(count - rep->min);
|
Chris@16
|
769
|
Chris@16
|
770 // non-greedy, keep trying till we get a match:
|
Chris@16
|
771 BidiIterator save_pos;
|
Chris@16
|
772 do
|
Chris@16
|
773 {
|
Chris@16
|
774 while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
775 {
|
Chris@16
|
776 if(position != re_is_set_member(position, last, set, re.get_data(), icase))
|
Chris@16
|
777 {
|
Chris@16
|
778 ++position;
|
Chris@16
|
779 ++count;
|
Chris@16
|
780 }
|
Chris@16
|
781 else
|
Chris@16
|
782 return false; // counldn't repeat even though it was the only option
|
Chris@16
|
783 }
|
Chris@16
|
784 if((rep->leading) && (rep->max == UINT_MAX))
|
Chris@16
|
785 restart = position;
|
Chris@16
|
786 pstate = rep->alt.p;
|
Chris@16
|
787 save_pos = position;
|
Chris@16
|
788 ++state_count;
|
Chris@16
|
789 if(match_all_states())
|
Chris@16
|
790 return true;
|
Chris@16
|
791 if(count >= rep->max)
|
Chris@16
|
792 return false;
|
Chris@16
|
793 position = save_pos;
|
Chris@16
|
794 if(position == last)
|
Chris@16
|
795 return false;
|
Chris@16
|
796 if(position != re_is_set_member(position, last, set, re.get_data(), icase))
|
Chris@16
|
797 {
|
Chris@16
|
798 ++position;
|
Chris@16
|
799 ++count;
|
Chris@16
|
800 }
|
Chris@16
|
801 else
|
Chris@16
|
802 {
|
Chris@16
|
803 return false;
|
Chris@16
|
804 }
|
Chris@16
|
805 }while(true);
|
Chris@16
|
806 #ifdef __BORLANDC__
|
Chris@16
|
807 #pragma option pop
|
Chris@16
|
808 #endif
|
Chris@16
|
809 #ifdef BOOST_MSVC
|
Chris@16
|
810 #pragma warning(pop)
|
Chris@16
|
811 #endif
|
Chris@16
|
812 }
|
Chris@16
|
813
|
Chris@16
|
814 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
815 bool perl_matcher<BidiIterator, Allocator, traits>::backtrack_till_match(std::size_t count)
|
Chris@16
|
816 {
|
Chris@16
|
817 #ifdef BOOST_MSVC
|
Chris@16
|
818 #pragma warning(push)
|
Chris@16
|
819 #pragma warning(disable:4127)
|
Chris@16
|
820 #endif
|
Chris@16
|
821 if((m_match_flags & match_partial) && (position == last))
|
Chris@16
|
822 m_has_partial_match = true;
|
Chris@16
|
823
|
Chris@16
|
824 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
825 BidiIterator backtrack = position;
|
Chris@16
|
826 if(position == last)
|
Chris@16
|
827 {
|
Chris@16
|
828 if(rep->can_be_null & mask_skip)
|
Chris@16
|
829 {
|
Chris@16
|
830 pstate = rep->alt.p;
|
Chris@16
|
831 if(match_all_states())
|
Chris@16
|
832 return true;
|
Chris@16
|
833 }
|
Chris@16
|
834 if(count)
|
Chris@16
|
835 {
|
Chris@16
|
836 position = --backtrack;
|
Chris@16
|
837 --count;
|
Chris@16
|
838 }
|
Chris@16
|
839 else
|
Chris@16
|
840 return false;
|
Chris@16
|
841 }
|
Chris@16
|
842 do
|
Chris@16
|
843 {
|
Chris@16
|
844 while(count && !can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
845 {
|
Chris@16
|
846 --position;
|
Chris@16
|
847 --count;
|
Chris@16
|
848 ++state_count;
|
Chris@16
|
849 }
|
Chris@16
|
850 pstate = rep->alt.p;
|
Chris@16
|
851 backtrack = position;
|
Chris@16
|
852 if(match_all_states())
|
Chris@16
|
853 return true;
|
Chris@16
|
854 if(count == 0)
|
Chris@16
|
855 return false;
|
Chris@16
|
856 position = --backtrack;
|
Chris@16
|
857 ++state_count;
|
Chris@16
|
858 --count;
|
Chris@16
|
859 }while(true);
|
Chris@16
|
860 #ifdef BOOST_MSVC
|
Chris@16
|
861 #pragma warning(pop)
|
Chris@16
|
862 #endif
|
Chris@16
|
863 }
|
Chris@16
|
864
|
Chris@16
|
865 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
866 bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
|
Chris@16
|
867 {
|
Chris@16
|
868 BOOST_ASSERT(pstate->type == syntax_element_recurse);
|
Chris@16
|
869 //
|
Chris@16
|
870 // Set new call stack:
|
Chris@16
|
871 //
|
Chris@16
|
872 if(recursion_stack.capacity() == 0)
|
Chris@16
|
873 {
|
Chris@16
|
874 recursion_stack.reserve(50);
|
Chris@16
|
875 }
|
Chris@16
|
876 recursion_stack.push_back(recursion_info<results_type>());
|
Chris@16
|
877 recursion_stack.back().preturn_address = pstate->next.p;
|
Chris@16
|
878 recursion_stack.back().results = *m_presult;
|
Chris@16
|
879 recursion_stack.back().repeater_stack = next_count;
|
Chris@16
|
880 pstate = static_cast<const re_jump*>(pstate)->alt.p;
|
Chris@16
|
881 recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
|
Chris@16
|
882
|
Chris@16
|
883 repeater_count<BidiIterator>* saved = next_count;
|
Chris@16
|
884 repeater_count<BidiIterator> r(&next_count); // resets all repeat counts since we're recursing and starting fresh on those
|
Chris@16
|
885 next_count = &r;
|
Chris@16
|
886 bool result = match_all_states();
|
Chris@16
|
887 next_count = saved;
|
Chris@16
|
888
|
Chris@16
|
889 if(!result)
|
Chris@16
|
890 {
|
Chris@16
|
891 next_count = recursion_stack.back().repeater_stack;
|
Chris@16
|
892 *m_presult = recursion_stack.back().results;
|
Chris@16
|
893 recursion_stack.pop_back();
|
Chris@16
|
894 return false;
|
Chris@16
|
895 }
|
Chris@16
|
896 return true;
|
Chris@16
|
897 }
|
Chris@16
|
898
|
Chris@16
|
899 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
900 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
|
Chris@16
|
901 {
|
Chris@16
|
902 int index = static_cast<const re_brace*>(pstate)->index;
|
Chris@16
|
903 icase = static_cast<const re_brace*>(pstate)->icase;
|
Chris@16
|
904 if(index > 0)
|
Chris@16
|
905 {
|
Chris@16
|
906 if((m_match_flags & match_nosubs) == 0)
|
Chris@16
|
907 {
|
Chris@16
|
908 m_presult->set_second(position, index);
|
Chris@16
|
909 }
|
Chris@16
|
910 if(!recursion_stack.empty())
|
Chris@16
|
911 {
|
Chris@16
|
912 if(index == recursion_stack.back().idx)
|
Chris@16
|
913 {
|
Chris@16
|
914 recursion_info<results_type> saved = recursion_stack.back();
|
Chris@16
|
915 recursion_stack.pop_back();
|
Chris@16
|
916 pstate = saved.preturn_address;
|
Chris@16
|
917 repeater_count<BidiIterator>* saved_count = next_count;
|
Chris@16
|
918 next_count = saved.repeater_stack;
|
Chris@16
|
919 *m_presult = saved.results;
|
Chris@16
|
920 if(!match_all_states())
|
Chris@16
|
921 {
|
Chris@16
|
922 recursion_stack.push_back(saved);
|
Chris@16
|
923 next_count = saved_count;
|
Chris@16
|
924 return false;
|
Chris@16
|
925 }
|
Chris@16
|
926 }
|
Chris@16
|
927 }
|
Chris@16
|
928 }
|
Chris@16
|
929 else if((index < 0) && (index != -4))
|
Chris@16
|
930 {
|
Chris@16
|
931 // matched forward lookahead:
|
Chris@16
|
932 pstate = 0;
|
Chris@16
|
933 return true;
|
Chris@16
|
934 }
|
Chris@16
|
935 pstate = pstate ? pstate->next.p : 0;
|
Chris@16
|
936 return true;
|
Chris@16
|
937 }
|
Chris@16
|
938
|
Chris@16
|
939 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
940 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
|
Chris@16
|
941 {
|
Chris@16
|
942 if(!recursion_stack.empty())
|
Chris@16
|
943 {
|
Chris@16
|
944 BOOST_ASSERT(0 == recursion_stack.back().idx);
|
Chris@16
|
945 const re_syntax_base* saved_state = pstate = recursion_stack.back().preturn_address;
|
Chris@16
|
946 *m_presult = recursion_stack.back().results;
|
Chris@16
|
947 recursion_stack.pop_back();
|
Chris@16
|
948 if(!match_all_states())
|
Chris@16
|
949 {
|
Chris@16
|
950 recursion_stack.push_back(recursion_info<results_type>());
|
Chris@16
|
951 recursion_stack.back().preturn_address = saved_state;
|
Chris@16
|
952 recursion_stack.back().results = *m_presult;
|
Chris@16
|
953 return false;
|
Chris@16
|
954 }
|
Chris@16
|
955 return true;
|
Chris@16
|
956 }
|
Chris@16
|
957 if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
|
Chris@16
|
958 return false;
|
Chris@16
|
959 if((m_match_flags & match_all) && (position != last))
|
Chris@16
|
960 return false;
|
Chris@16
|
961 if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
|
Chris@16
|
962 return false;
|
Chris@16
|
963 m_presult->set_second(position);
|
Chris@16
|
964 pstate = 0;
|
Chris@16
|
965 m_has_found_match = true;
|
Chris@16
|
966 if((m_match_flags & match_posix) == match_posix)
|
Chris@16
|
967 {
|
Chris@16
|
968 m_result.maybe_assign(*m_presult);
|
Chris@16
|
969 if((m_match_flags & match_any) == 0)
|
Chris@16
|
970 return false;
|
Chris@16
|
971 }
|
Chris@16
|
972 #ifdef BOOST_REGEX_MATCH_EXTRA
|
Chris@16
|
973 if(match_extra & m_match_flags)
|
Chris@16
|
974 {
|
Chris@16
|
975 for(unsigned i = 0; i < m_presult->size(); ++i)
|
Chris@16
|
976 if((*m_presult)[i].matched)
|
Chris@16
|
977 ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
|
Chris@16
|
978 }
|
Chris@16
|
979 #endif
|
Chris@16
|
980 return true;
|
Chris@16
|
981 }
|
Chris@16
|
982
|
Chris@16
|
983
|
Chris@16
|
984
|
Chris@16
|
985 } // namespace re_detail
|
Chris@16
|
986 } // namespace boost
|
Chris@16
|
987 #ifdef BOOST_MSVC
|
Chris@16
|
988 #pragma warning(pop)
|
Chris@16
|
989 #endif
|
Chris@16
|
990
|
Chris@16
|
991 #ifdef BOOST_MSVC
|
Chris@16
|
992 #pragma warning(push)
|
Chris@16
|
993 #pragma warning(disable: 4103)
|
Chris@16
|
994 #endif
|
Chris@16
|
995 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
996 # include BOOST_ABI_SUFFIX
|
Chris@16
|
997 #endif
|
Chris@16
|
998 #ifdef BOOST_MSVC
|
Chris@16
|
999 #pragma warning(pop)
|
Chris@16
|
1000 #endif
|
Chris@16
|
1001
|
Chris@16
|
1002 #endif
|
Chris@16
|
1003
|