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 non-recursive implementation.
|
Chris@16
|
18 */
|
Chris@16
|
19
|
Chris@16
|
20 #ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
|
Chris@16
|
21 #define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
|
Chris@16
|
22
|
Chris@16
|
23 #include <new>
|
Chris@16
|
24
|
Chris@16
|
25 #ifdef BOOST_MSVC
|
Chris@16
|
26 #pragma warning(push)
|
Chris@16
|
27 #pragma warning(disable: 4103)
|
Chris@16
|
28 #endif
|
Chris@16
|
29 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
30 # include BOOST_ABI_PREFIX
|
Chris@16
|
31 #endif
|
Chris@16
|
32 #ifdef BOOST_MSVC
|
Chris@16
|
33 #pragma warning(pop)
|
Chris@16
|
34 #endif
|
Chris@16
|
35 #ifdef BOOST_MSVC
|
Chris@16
|
36 # pragma warning(push)
|
Chris@16
|
37 # pragma warning(disable: 4800)
|
Chris@16
|
38 #endif
|
Chris@16
|
39
|
Chris@16
|
40 namespace boost{
|
Chris@16
|
41 namespace re_detail{
|
Chris@16
|
42
|
Chris@16
|
43 template <class T>
|
Chris@16
|
44 inline void inplace_destroy(T* p)
|
Chris@16
|
45 {
|
Chris@16
|
46 (void)p; // warning suppression
|
Chris@16
|
47 p->~T();
|
Chris@16
|
48 }
|
Chris@16
|
49
|
Chris@16
|
50 struct saved_state
|
Chris@16
|
51 {
|
Chris@16
|
52 union{
|
Chris@16
|
53 unsigned int state_id;
|
Chris@16
|
54 // this padding ensures correct alignment on 64-bit platforms:
|
Chris@16
|
55 std::size_t padding1;
|
Chris@16
|
56 std::ptrdiff_t padding2;
|
Chris@16
|
57 void* padding3;
|
Chris@16
|
58 };
|
Chris@16
|
59 saved_state(unsigned i) : state_id(i) {}
|
Chris@16
|
60 };
|
Chris@16
|
61
|
Chris@16
|
62 template <class BidiIterator>
|
Chris@16
|
63 struct saved_matched_paren : public saved_state
|
Chris@16
|
64 {
|
Chris@16
|
65 int index;
|
Chris@16
|
66 sub_match<BidiIterator> sub;
|
Chris@16
|
67 saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){};
|
Chris@16
|
68 };
|
Chris@16
|
69
|
Chris@16
|
70 template <class BidiIterator>
|
Chris@16
|
71 struct saved_position : public saved_state
|
Chris@16
|
72 {
|
Chris@16
|
73 const re_syntax_base* pstate;
|
Chris@16
|
74 BidiIterator position;
|
Chris@16
|
75 saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){};
|
Chris@16
|
76 };
|
Chris@16
|
77
|
Chris@16
|
78 template <class BidiIterator>
|
Chris@16
|
79 struct saved_assertion : public saved_position<BidiIterator>
|
Chris@16
|
80 {
|
Chris@16
|
81 bool positive;
|
Chris@16
|
82 saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos)
|
Chris@16
|
83 : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){};
|
Chris@16
|
84 };
|
Chris@16
|
85
|
Chris@16
|
86 template <class BidiIterator>
|
Chris@16
|
87 struct saved_repeater : public saved_state
|
Chris@16
|
88 {
|
Chris@16
|
89 repeater_count<BidiIterator> count;
|
Chris@16
|
90 saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start)
|
Chris@16
|
91 : saved_state(saved_state_repeater_count), count(i,s,start){}
|
Chris@16
|
92 };
|
Chris@16
|
93
|
Chris@16
|
94 struct saved_extra_block : public saved_state
|
Chris@16
|
95 {
|
Chris@16
|
96 saved_state *base, *end;
|
Chris@16
|
97 saved_extra_block(saved_state* b, saved_state* e)
|
Chris@16
|
98 : saved_state(saved_state_extra_block), base(b), end(e) {}
|
Chris@16
|
99 };
|
Chris@16
|
100
|
Chris@16
|
101 struct save_state_init
|
Chris@16
|
102 {
|
Chris@16
|
103 saved_state** stack;
|
Chris@16
|
104 save_state_init(saved_state** base, saved_state** end)
|
Chris@16
|
105 : stack(base)
|
Chris@16
|
106 {
|
Chris@16
|
107 *base = static_cast<saved_state*>(get_mem_block());
|
Chris@16
|
108 *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE);
|
Chris@16
|
109 --(*end);
|
Chris@16
|
110 (void) new (*end)saved_state(0);
|
Chris@16
|
111 BOOST_ASSERT(*end > *base);
|
Chris@16
|
112 }
|
Chris@16
|
113 ~save_state_init()
|
Chris@16
|
114 {
|
Chris@16
|
115 put_mem_block(*stack);
|
Chris@16
|
116 *stack = 0;
|
Chris@16
|
117 }
|
Chris@16
|
118 };
|
Chris@16
|
119
|
Chris@16
|
120 template <class BidiIterator>
|
Chris@16
|
121 struct saved_single_repeat : public saved_state
|
Chris@16
|
122 {
|
Chris@16
|
123 std::size_t count;
|
Chris@16
|
124 const re_repeat* rep;
|
Chris@16
|
125 BidiIterator last_position;
|
Chris@16
|
126 saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id)
|
Chris@16
|
127 : saved_state(arg_id), count(c), rep(r), last_position(lp){}
|
Chris@16
|
128 };
|
Chris@16
|
129
|
Chris@16
|
130 template <class Results>
|
Chris@16
|
131 struct saved_recursion : public saved_state
|
Chris@16
|
132 {
|
Chris@16
|
133 saved_recursion(int idx, const re_syntax_base* p, Results* pr)
|
Chris@16
|
134 : saved_state(14), recursion_id(idx), preturn_address(p), results(*pr)
|
Chris@16
|
135 {}
|
Chris@16
|
136 int recursion_id;
|
Chris@16
|
137 const re_syntax_base* preturn_address;
|
Chris@16
|
138 Results results;
|
Chris@16
|
139 };
|
Chris@16
|
140
|
Chris@16
|
141 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
142 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
|
Chris@16
|
143 {
|
Chris@16
|
144 static matcher_proc_type const s_match_vtable[30] =
|
Chris@16
|
145 {
|
Chris@16
|
146 (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
|
Chris@16
|
147 &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
|
Chris@16
|
148 &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
|
Chris@16
|
149 &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
|
Chris@16
|
150 &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
|
Chris@16
|
151 &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
|
Chris@16
|
152 &perl_matcher<BidiIterator, Allocator, traits>::match_match,
|
Chris@16
|
153 &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
|
Chris@16
|
154 &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
|
Chris@16
|
155 &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
|
Chris@16
|
156 &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
|
Chris@16
|
157 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
|
Chris@16
|
158 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
|
Chris@16
|
159 &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
|
Chris@16
|
160 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
|
Chris@16
|
161 &perl_matcher<BidiIterator, Allocator, traits>::match_set,
|
Chris@16
|
162 &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
|
Chris@16
|
163 &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
|
Chris@16
|
164 &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
|
Chris@16
|
165 &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
|
Chris@16
|
166 &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
|
Chris@16
|
167 &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
|
Chris@16
|
168 // Although this next line *should* be evaluated at compile time, in practice
|
Chris@16
|
169 // some compilers (VC++) emit run-time initialisation which breaks thread
|
Chris@16
|
170 // safety, so use a dispatch function instead:
|
Chris@16
|
171 //(::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
|
172 &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
|
Chris@16
|
173 &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
|
Chris@16
|
174 &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
|
Chris@16
|
175 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
|
Chris@16
|
176 &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
|
Chris@16
|
177 &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
|
Chris@16
|
178 &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
|
Chris@16
|
179 &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
|
Chris@16
|
180 };
|
Chris@16
|
181
|
Chris@16
|
182 push_recursion_stopper();
|
Chris@16
|
183 do{
|
Chris@16
|
184 while(pstate)
|
Chris@16
|
185 {
|
Chris@16
|
186 matcher_proc_type proc = s_match_vtable[pstate->type];
|
Chris@16
|
187 ++state_count;
|
Chris@16
|
188 if(!(this->*proc)())
|
Chris@16
|
189 {
|
Chris@16
|
190 if(state_count > max_state_count)
|
Chris@16
|
191 raise_error(traits_inst, regex_constants::error_complexity);
|
Chris@16
|
192 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
|
Chris@16
|
193 m_has_partial_match = true;
|
Chris@16
|
194 bool successful_unwind = unwind(false);
|
Chris@16
|
195 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
|
Chris@16
|
196 m_has_partial_match = true;
|
Chris@16
|
197 if(false == successful_unwind)
|
Chris@16
|
198 return m_recursive_result;
|
Chris@16
|
199 }
|
Chris@16
|
200 }
|
Chris@16
|
201 }while(unwind(true));
|
Chris@16
|
202 return m_recursive_result;
|
Chris@16
|
203 }
|
Chris@16
|
204
|
Chris@16
|
205 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
206 void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
|
Chris@16
|
207 {
|
Chris@16
|
208 if(used_block_count)
|
Chris@16
|
209 {
|
Chris@16
|
210 --used_block_count;
|
Chris@16
|
211 saved_state* stack_base;
|
Chris@16
|
212 saved_state* backup_state;
|
Chris@16
|
213 stack_base = static_cast<saved_state*>(get_mem_block());
|
Chris@16
|
214 backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE);
|
Chris@16
|
215 saved_extra_block* block = static_cast<saved_extra_block*>(backup_state);
|
Chris@16
|
216 --block;
|
Chris@16
|
217 (void) new (block) saved_extra_block(m_stack_base, m_backup_state);
|
Chris@16
|
218 m_stack_base = stack_base;
|
Chris@16
|
219 m_backup_state = block;
|
Chris@16
|
220 }
|
Chris@16
|
221 else
|
Chris@16
|
222 raise_error(traits_inst, regex_constants::error_stack);
|
Chris@16
|
223 }
|
Chris@16
|
224
|
Chris@16
|
225 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
226 inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub)
|
Chris@16
|
227 {
|
Chris@16
|
228 //BOOST_ASSERT(index);
|
Chris@16
|
229 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
|
Chris@16
|
230 --pmp;
|
Chris@16
|
231 if(pmp < m_stack_base)
|
Chris@16
|
232 {
|
Chris@16
|
233 extend_stack();
|
Chris@16
|
234 pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
|
Chris@16
|
235 --pmp;
|
Chris@16
|
236 }
|
Chris@16
|
237 (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub);
|
Chris@16
|
238 m_backup_state = pmp;
|
Chris@16
|
239 }
|
Chris@16
|
240
|
Chris@16
|
241 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
242 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper()
|
Chris@16
|
243 {
|
Chris@16
|
244 saved_state* pmp = m_backup_state;
|
Chris@16
|
245 --pmp;
|
Chris@16
|
246 if(pmp < m_stack_base)
|
Chris@16
|
247 {
|
Chris@16
|
248 extend_stack();
|
Chris@16
|
249 pmp = m_backup_state;
|
Chris@16
|
250 --pmp;
|
Chris@16
|
251 }
|
Chris@16
|
252 (void) new (pmp)saved_state(saved_type_recurse);
|
Chris@16
|
253 m_backup_state = pmp;
|
Chris@16
|
254 }
|
Chris@16
|
255
|
Chris@16
|
256 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
257 inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive)
|
Chris@16
|
258 {
|
Chris@16
|
259 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
|
Chris@16
|
260 --pmp;
|
Chris@16
|
261 if(pmp < m_stack_base)
|
Chris@16
|
262 {
|
Chris@16
|
263 extend_stack();
|
Chris@16
|
264 pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
|
Chris@16
|
265 --pmp;
|
Chris@16
|
266 }
|
Chris@16
|
267 (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position);
|
Chris@16
|
268 m_backup_state = pmp;
|
Chris@16
|
269 }
|
Chris@16
|
270
|
Chris@16
|
271 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
272 inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps)
|
Chris@16
|
273 {
|
Chris@16
|
274 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
275 --pmp;
|
Chris@16
|
276 if(pmp < m_stack_base)
|
Chris@16
|
277 {
|
Chris@16
|
278 extend_stack();
|
Chris@16
|
279 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
280 --pmp;
|
Chris@16
|
281 }
|
Chris@16
|
282 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt);
|
Chris@16
|
283 m_backup_state = pmp;
|
Chris@16
|
284 }
|
Chris@16
|
285
|
Chris@16
|
286 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
287 inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps)
|
Chris@16
|
288 {
|
Chris@16
|
289 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
290 --pmp;
|
Chris@16
|
291 if(pmp < m_stack_base)
|
Chris@16
|
292 {
|
Chris@16
|
293 extend_stack();
|
Chris@16
|
294 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
295 --pmp;
|
Chris@16
|
296 }
|
Chris@16
|
297 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);
|
Chris@16
|
298 m_backup_state = pmp;
|
Chris@16
|
299 }
|
Chris@16
|
300
|
Chris@16
|
301 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
302 inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s)
|
Chris@16
|
303 {
|
Chris@16
|
304 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
|
Chris@16
|
305 --pmp;
|
Chris@16
|
306 if(pmp < m_stack_base)
|
Chris@16
|
307 {
|
Chris@16
|
308 extend_stack();
|
Chris@16
|
309 pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
|
Chris@16
|
310 --pmp;
|
Chris@16
|
311 }
|
Chris@16
|
312 (void) new (pmp)saved_repeater<BidiIterator>(i, s, position);
|
Chris@16
|
313 m_backup_state = pmp;
|
Chris@16
|
314 }
|
Chris@16
|
315
|
Chris@16
|
316 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
317 inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id)
|
Chris@16
|
318 {
|
Chris@16
|
319 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
320 --pmp;
|
Chris@16
|
321 if(pmp < m_stack_base)
|
Chris@16
|
322 {
|
Chris@16
|
323 extend_stack();
|
Chris@16
|
324 pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
325 --pmp;
|
Chris@16
|
326 }
|
Chris@16
|
327 (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id);
|
Chris@16
|
328 m_backup_state = pmp;
|
Chris@16
|
329 }
|
Chris@16
|
330
|
Chris@16
|
331 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
332 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int idx, const re_syntax_base* p, results_type* presults)
|
Chris@16
|
333 {
|
Chris@16
|
334 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
|
Chris@16
|
335 --pmp;
|
Chris@16
|
336 if(pmp < m_stack_base)
|
Chris@16
|
337 {
|
Chris@16
|
338 extend_stack();
|
Chris@16
|
339 pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
|
Chris@16
|
340 --pmp;
|
Chris@16
|
341 }
|
Chris@16
|
342 (void) new (pmp)saved_recursion<results_type>(idx, p, presults);
|
Chris@16
|
343 m_backup_state = pmp;
|
Chris@16
|
344 }
|
Chris@16
|
345
|
Chris@16
|
346 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
347 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
|
Chris@16
|
348 {
|
Chris@16
|
349 int index = static_cast<const re_brace*>(pstate)->index;
|
Chris@16
|
350 icase = static_cast<const re_brace*>(pstate)->icase;
|
Chris@16
|
351 switch(index)
|
Chris@16
|
352 {
|
Chris@16
|
353 case 0:
|
Chris@16
|
354 pstate = pstate->next.p;
|
Chris@16
|
355 break;
|
Chris@16
|
356 case -1:
|
Chris@16
|
357 case -2:
|
Chris@16
|
358 {
|
Chris@16
|
359 // forward lookahead assert:
|
Chris@16
|
360 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
|
Chris@16
|
361 pstate = pstate->next.p->next.p;
|
Chris@16
|
362 push_assertion(next_pstate, index == -1);
|
Chris@16
|
363 break;
|
Chris@16
|
364 }
|
Chris@16
|
365 case -3:
|
Chris@16
|
366 {
|
Chris@16
|
367 // independent sub-expression, currently this is always recursive:
|
Chris@16
|
368 bool old_independent = m_independent;
|
Chris@16
|
369 m_independent = true;
|
Chris@16
|
370 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
|
Chris@16
|
371 pstate = pstate->next.p->next.p;
|
Chris@16
|
372 bool r = match_all_states();
|
Chris@16
|
373 pstate = next_pstate;
|
Chris@16
|
374 m_independent = old_independent;
|
Chris@16
|
375 #ifdef BOOST_REGEX_MATCH_EXTRA
|
Chris@16
|
376 if(r && (m_match_flags & match_extra))
|
Chris@16
|
377 {
|
Chris@16
|
378 //
|
Chris@16
|
379 // our captures have been stored in *m_presult
|
Chris@16
|
380 // we need to unpack them, and insert them
|
Chris@16
|
381 // back in the right order when we unwind the stack:
|
Chris@16
|
382 //
|
Chris@16
|
383 match_results<BidiIterator, Allocator> temp_match(*m_presult);
|
Chris@16
|
384 unsigned i;
|
Chris@16
|
385 for(i = 0; i < temp_match.size(); ++i)
|
Chris@16
|
386 (*m_presult)[i].get_captures().clear();
|
Chris@16
|
387 // match everything else:
|
Chris@16
|
388 r = match_all_states();
|
Chris@16
|
389 // now place the stored captures back:
|
Chris@16
|
390 for(i = 0; i < temp_match.size(); ++i)
|
Chris@16
|
391 {
|
Chris@16
|
392 typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
|
Chris@16
|
393 seq& s1 = (*m_presult)[i].get_captures();
|
Chris@16
|
394 const seq& s2 = temp_match[i].captures();
|
Chris@16
|
395 s1.insert(
|
Chris@16
|
396 s1.end(),
|
Chris@16
|
397 s2.begin(),
|
Chris@16
|
398 s2.end());
|
Chris@16
|
399 }
|
Chris@16
|
400 }
|
Chris@16
|
401 #endif
|
Chris@16
|
402 return r;
|
Chris@16
|
403 }
|
Chris@16
|
404 case -4:
|
Chris@16
|
405 {
|
Chris@16
|
406 // conditional expression:
|
Chris@16
|
407 const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
|
Chris@16
|
408 BOOST_ASSERT(alt->type == syntax_element_alt);
|
Chris@16
|
409 pstate = alt->next.p;
|
Chris@16
|
410 if(pstate->type == syntax_element_assert_backref)
|
Chris@16
|
411 {
|
Chris@16
|
412 if(!match_assert_backref())
|
Chris@16
|
413 pstate = alt->alt.p;
|
Chris@16
|
414 break;
|
Chris@16
|
415 }
|
Chris@16
|
416 else
|
Chris@16
|
417 {
|
Chris@16
|
418 // zero width assertion, have to match this recursively:
|
Chris@16
|
419 BOOST_ASSERT(pstate->type == syntax_element_startmark);
|
Chris@16
|
420 bool negated = static_cast<const re_brace*>(pstate)->index == -2;
|
Chris@16
|
421 BidiIterator saved_position = position;
|
Chris@16
|
422 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
|
Chris@16
|
423 pstate = pstate->next.p->next.p;
|
Chris@16
|
424 bool r = match_all_states();
|
Chris@16
|
425 position = saved_position;
|
Chris@16
|
426 if(negated)
|
Chris@16
|
427 r = !r;
|
Chris@16
|
428 if(r)
|
Chris@16
|
429 pstate = next_pstate;
|
Chris@16
|
430 else
|
Chris@16
|
431 pstate = alt->alt.p;
|
Chris@16
|
432 break;
|
Chris@16
|
433 }
|
Chris@16
|
434 }
|
Chris@16
|
435 case -5:
|
Chris@16
|
436 {
|
Chris@16
|
437 push_matched_paren(0, (*m_presult)[0]);
|
Chris@16
|
438 m_presult->set_first(position, 0, true);
|
Chris@16
|
439 pstate = pstate->next.p;
|
Chris@16
|
440 break;
|
Chris@16
|
441 }
|
Chris@16
|
442 default:
|
Chris@16
|
443 {
|
Chris@16
|
444 BOOST_ASSERT(index > 0);
|
Chris@16
|
445 if((m_match_flags & match_nosubs) == 0)
|
Chris@16
|
446 {
|
Chris@16
|
447 push_matched_paren(index, (*m_presult)[index]);
|
Chris@16
|
448 m_presult->set_first(position, index);
|
Chris@16
|
449 }
|
Chris@16
|
450 pstate = pstate->next.p;
|
Chris@16
|
451 break;
|
Chris@16
|
452 }
|
Chris@16
|
453 }
|
Chris@16
|
454 return true;
|
Chris@16
|
455 }
|
Chris@16
|
456
|
Chris@16
|
457 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
458 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
|
Chris@16
|
459 {
|
Chris@16
|
460 bool take_first, take_second;
|
Chris@16
|
461 const re_alt* jmp = static_cast<const re_alt*>(pstate);
|
Chris@16
|
462
|
Chris@16
|
463 // find out which of these two alternatives we need to take:
|
Chris@16
|
464 if(position == last)
|
Chris@16
|
465 {
|
Chris@16
|
466 take_first = jmp->can_be_null & mask_take;
|
Chris@16
|
467 take_second = jmp->can_be_null & mask_skip;
|
Chris@16
|
468 }
|
Chris@16
|
469 else
|
Chris@16
|
470 {
|
Chris@16
|
471 take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
|
Chris@16
|
472 take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
|
Chris@16
|
473 }
|
Chris@16
|
474
|
Chris@16
|
475 if(take_first)
|
Chris@16
|
476 {
|
Chris@16
|
477 // we can take the first alternative,
|
Chris@16
|
478 // see if we need to push next alternative:
|
Chris@16
|
479 if(take_second)
|
Chris@16
|
480 {
|
Chris@16
|
481 push_alt(jmp->alt.p);
|
Chris@16
|
482 }
|
Chris@16
|
483 pstate = pstate->next.p;
|
Chris@16
|
484 return true;
|
Chris@16
|
485 }
|
Chris@16
|
486 if(take_second)
|
Chris@16
|
487 {
|
Chris@16
|
488 pstate = jmp->alt.p;
|
Chris@16
|
489 return true;
|
Chris@16
|
490 }
|
Chris@16
|
491 return false; // neither option is possible
|
Chris@16
|
492 }
|
Chris@16
|
493
|
Chris@16
|
494 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
495 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
|
Chris@16
|
496 {
|
Chris@16
|
497 #ifdef BOOST_MSVC
|
Chris@16
|
498 #pragma warning(push)
|
Chris@16
|
499 #pragma warning(disable:4127 4244)
|
Chris@16
|
500 #endif
|
Chris@16
|
501 #ifdef __BORLANDC__
|
Chris@16
|
502 #pragma option push -w-8008 -w-8066 -w-8004
|
Chris@16
|
503 #endif
|
Chris@16
|
504 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
505
|
Chris@16
|
506 // find out which of these two alternatives we need to take:
|
Chris@16
|
507 bool take_first, take_second;
|
Chris@16
|
508 if(position == last)
|
Chris@16
|
509 {
|
Chris@16
|
510 take_first = rep->can_be_null & mask_take;
|
Chris@16
|
511 take_second = rep->can_be_null & mask_skip;
|
Chris@16
|
512 }
|
Chris@16
|
513 else
|
Chris@16
|
514 {
|
Chris@16
|
515 take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
|
Chris@16
|
516 take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
|
Chris@16
|
517 }
|
Chris@16
|
518
|
Chris@16
|
519 if((m_backup_state->state_id != saved_state_repeater_count)
|
Chris@16
|
520 || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id)
|
Chris@16
|
521 || (next_count->get_id() != rep->state_id))
|
Chris@16
|
522 {
|
Chris@16
|
523 // we're moving to a different repeat from the last
|
Chris@16
|
524 // one, so set up a counter object:
|
Chris@16
|
525 push_repeater_count(rep->state_id, &next_count);
|
Chris@16
|
526 }
|
Chris@16
|
527 //
|
Chris@16
|
528 // If we've had at least one repeat already, and the last one
|
Chris@16
|
529 // matched the NULL string then set the repeat count to
|
Chris@16
|
530 // maximum:
|
Chris@16
|
531 //
|
Chris@16
|
532 next_count->check_null_repeat(position, rep->max);
|
Chris@16
|
533
|
Chris@16
|
534 if(next_count->get_count() < rep->min)
|
Chris@16
|
535 {
|
Chris@16
|
536 // we must take the repeat:
|
Chris@16
|
537 if(take_first)
|
Chris@16
|
538 {
|
Chris@16
|
539 // increase the counter:
|
Chris@16
|
540 ++(*next_count);
|
Chris@16
|
541 pstate = rep->next.p;
|
Chris@16
|
542 return true;
|
Chris@16
|
543 }
|
Chris@16
|
544 return false;
|
Chris@16
|
545 }
|
Chris@16
|
546
|
Chris@16
|
547 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
548 if(greedy)
|
Chris@16
|
549 {
|
Chris@16
|
550 // try and take the repeat if we can:
|
Chris@16
|
551 if((next_count->get_count() < rep->max) && take_first)
|
Chris@16
|
552 {
|
Chris@16
|
553 if(take_second)
|
Chris@16
|
554 {
|
Chris@16
|
555 // store position in case we fail:
|
Chris@16
|
556 push_alt(rep->alt.p);
|
Chris@16
|
557 }
|
Chris@16
|
558 // increase the counter:
|
Chris@16
|
559 ++(*next_count);
|
Chris@16
|
560 pstate = rep->next.p;
|
Chris@16
|
561 return true;
|
Chris@16
|
562 }
|
Chris@16
|
563 else if(take_second)
|
Chris@16
|
564 {
|
Chris@16
|
565 pstate = rep->alt.p;
|
Chris@16
|
566 return true;
|
Chris@16
|
567 }
|
Chris@16
|
568 return false; // can't take anything, fail...
|
Chris@16
|
569 }
|
Chris@16
|
570 else // non-greedy
|
Chris@16
|
571 {
|
Chris@16
|
572 // try and skip the repeat if we can:
|
Chris@16
|
573 if(take_second)
|
Chris@16
|
574 {
|
Chris@16
|
575 if((next_count->get_count() < rep->max) && take_first)
|
Chris@16
|
576 {
|
Chris@16
|
577 // store position in case we fail:
|
Chris@16
|
578 push_non_greedy_repeat(rep->next.p);
|
Chris@16
|
579 }
|
Chris@16
|
580 pstate = rep->alt.p;
|
Chris@16
|
581 return true;
|
Chris@16
|
582 }
|
Chris@16
|
583 if((next_count->get_count() < rep->max) && take_first)
|
Chris@16
|
584 {
|
Chris@16
|
585 // increase the counter:
|
Chris@16
|
586 ++(*next_count);
|
Chris@16
|
587 pstate = rep->next.p;
|
Chris@16
|
588 return true;
|
Chris@16
|
589 }
|
Chris@16
|
590 }
|
Chris@16
|
591 return false;
|
Chris@16
|
592 #ifdef __BORLANDC__
|
Chris@16
|
593 #pragma option pop
|
Chris@16
|
594 #endif
|
Chris@16
|
595 #ifdef BOOST_MSVC
|
Chris@16
|
596 #pragma warning(pop)
|
Chris@16
|
597 #endif
|
Chris@16
|
598 }
|
Chris@16
|
599
|
Chris@16
|
600 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
601 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
|
Chris@16
|
602 {
|
Chris@16
|
603 unsigned count = 0;
|
Chris@16
|
604 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
605 re_syntax_base* psingle = rep->next.p;
|
Chris@16
|
606 // match compulsary repeats first:
|
Chris@16
|
607 while(count < rep->min)
|
Chris@16
|
608 {
|
Chris@16
|
609 pstate = psingle;
|
Chris@16
|
610 if(!match_wild())
|
Chris@16
|
611 return false;
|
Chris@16
|
612 ++count;
|
Chris@16
|
613 }
|
Chris@16
|
614 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
615 if(greedy)
|
Chris@16
|
616 {
|
Chris@16
|
617 // repeat for as long as we can:
|
Chris@16
|
618 while(count < rep->max)
|
Chris@16
|
619 {
|
Chris@16
|
620 pstate = psingle;
|
Chris@16
|
621 if(!match_wild())
|
Chris@16
|
622 break;
|
Chris@16
|
623 ++count;
|
Chris@16
|
624 }
|
Chris@16
|
625 // remember where we got to if this is a leading repeat:
|
Chris@16
|
626 if((rep->leading) && (count < rep->max))
|
Chris@16
|
627 restart = position;
|
Chris@16
|
628 // push backtrack info if available:
|
Chris@16
|
629 if(count - rep->min)
|
Chris@16
|
630 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
|
Chris@16
|
631 // jump to next state:
|
Chris@16
|
632 pstate = rep->alt.p;
|
Chris@16
|
633 return true;
|
Chris@16
|
634 }
|
Chris@16
|
635 else
|
Chris@16
|
636 {
|
Chris@16
|
637 // non-greedy, push state and return true if we can skip:
|
Chris@16
|
638 if(count < rep->max)
|
Chris@16
|
639 push_single_repeat(count, rep, position, saved_state_rep_slow_dot);
|
Chris@16
|
640 pstate = rep->alt.p;
|
Chris@16
|
641 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
|
Chris@16
|
642 }
|
Chris@16
|
643 }
|
Chris@16
|
644
|
Chris@16
|
645 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
646 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
|
Chris@16
|
647 {
|
Chris@16
|
648 if(m_match_flags & match_not_dot_null)
|
Chris@16
|
649 return match_dot_repeat_slow();
|
Chris@16
|
650 if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
|
Chris@16
|
651 return match_dot_repeat_slow();
|
Chris@16
|
652
|
Chris@16
|
653 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
654 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
655 unsigned count = static_cast<unsigned>((std::min)(static_cast<unsigned>(::boost::re_detail::distance(position, last)), static_cast<unsigned>(greedy ? rep->max : rep->min)));
|
Chris@16
|
656 if(rep->min > count)
|
Chris@16
|
657 {
|
Chris@16
|
658 position = last;
|
Chris@16
|
659 return false; // not enough text left to match
|
Chris@16
|
660 }
|
Chris@16
|
661 std::advance(position, count);
|
Chris@16
|
662
|
Chris@16
|
663 if(greedy)
|
Chris@16
|
664 {
|
Chris@16
|
665 if((rep->leading) && (count < rep->max))
|
Chris@16
|
666 restart = position;
|
Chris@16
|
667 // push backtrack info if available:
|
Chris@16
|
668 if(count - rep->min)
|
Chris@16
|
669 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
|
Chris@16
|
670 // jump to next state:
|
Chris@16
|
671 pstate = rep->alt.p;
|
Chris@16
|
672 return true;
|
Chris@16
|
673 }
|
Chris@16
|
674 else
|
Chris@16
|
675 {
|
Chris@16
|
676 // non-greedy, push state and return true if we can skip:
|
Chris@16
|
677 if(count < rep->max)
|
Chris@16
|
678 push_single_repeat(count, rep, position, saved_state_rep_fast_dot);
|
Chris@16
|
679 pstate = rep->alt.p;
|
Chris@16
|
680 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
|
Chris@16
|
681 }
|
Chris@16
|
682 }
|
Chris@16
|
683
|
Chris@16
|
684 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
685 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
|
Chris@16
|
686 {
|
Chris@16
|
687 #ifdef BOOST_MSVC
|
Chris@16
|
688 #pragma warning(push)
|
Chris@16
|
689 #pragma warning(disable:4127)
|
Chris@16
|
690 #endif
|
Chris@16
|
691 #ifdef __BORLANDC__
|
Chris@16
|
692 #pragma option push -w-8008 -w-8066 -w-8004
|
Chris@16
|
693 #endif
|
Chris@16
|
694 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
695 BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
|
Chris@16
|
696 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
|
Chris@16
|
697 std::size_t count = 0;
|
Chris@16
|
698 //
|
Chris@16
|
699 // start by working out how much we can skip:
|
Chris@16
|
700 //
|
Chris@16
|
701 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
702 std::size_t desired = greedy ? rep->max : rep->min;
|
Chris@16
|
703 if(::boost::is_random_access_iterator<BidiIterator>::value)
|
Chris@16
|
704 {
|
Chris@16
|
705 BidiIterator end = position;
|
Chris@16
|
706 // Move end forward by "desired", preferably without using distance or advance if we can
|
Chris@16
|
707 // as these can be slow for some iterator types.
|
Chris@16
|
708 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
|
Chris@16
|
709 if(desired >= len)
|
Chris@16
|
710 end = last;
|
Chris@16
|
711 else
|
Chris@16
|
712 std::advance(end, desired);
|
Chris@16
|
713 BidiIterator origin(position);
|
Chris@16
|
714 while((position != end) && (traits_inst.translate(*position, icase) == what))
|
Chris@16
|
715 {
|
Chris@16
|
716 ++position;
|
Chris@16
|
717 }
|
Chris@16
|
718 count = (unsigned)::boost::re_detail::distance(origin, position);
|
Chris@16
|
719 }
|
Chris@16
|
720 else
|
Chris@16
|
721 {
|
Chris@16
|
722 while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
|
Chris@16
|
723 {
|
Chris@16
|
724 ++position;
|
Chris@16
|
725 ++count;
|
Chris@16
|
726 }
|
Chris@16
|
727 }
|
Chris@16
|
728
|
Chris@16
|
729 if(count < rep->min)
|
Chris@16
|
730 return false;
|
Chris@16
|
731
|
Chris@16
|
732 if(greedy)
|
Chris@16
|
733 {
|
Chris@16
|
734 if((rep->leading) && (count < rep->max))
|
Chris@16
|
735 restart = position;
|
Chris@16
|
736 // push backtrack info if available:
|
Chris@16
|
737 if(count - rep->min)
|
Chris@16
|
738 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
|
Chris@16
|
739 // jump to next state:
|
Chris@16
|
740 pstate = rep->alt.p;
|
Chris@16
|
741 return true;
|
Chris@16
|
742 }
|
Chris@16
|
743 else
|
Chris@16
|
744 {
|
Chris@16
|
745 // non-greedy, push state and return true if we can skip:
|
Chris@16
|
746 if(count < rep->max)
|
Chris@16
|
747 push_single_repeat(count, rep, position, saved_state_rep_char);
|
Chris@16
|
748 pstate = rep->alt.p;
|
Chris@16
|
749 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
|
Chris@16
|
750 }
|
Chris@16
|
751 #ifdef __BORLANDC__
|
Chris@16
|
752 #pragma option pop
|
Chris@16
|
753 #endif
|
Chris@16
|
754 #ifdef BOOST_MSVC
|
Chris@16
|
755 #pragma warning(pop)
|
Chris@16
|
756 #endif
|
Chris@16
|
757 }
|
Chris@16
|
758
|
Chris@16
|
759 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
760 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
|
Chris@16
|
761 {
|
Chris@16
|
762 #ifdef BOOST_MSVC
|
Chris@16
|
763 #pragma warning(push)
|
Chris@16
|
764 #pragma warning(disable:4127)
|
Chris@16
|
765 #endif
|
Chris@16
|
766 #ifdef __BORLANDC__
|
Chris@16
|
767 #pragma option push -w-8008 -w-8066 -w-8004
|
Chris@16
|
768 #endif
|
Chris@16
|
769 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
770 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
|
Chris@16
|
771 std::size_t count = 0;
|
Chris@16
|
772 //
|
Chris@16
|
773 // start by working out how much we can skip:
|
Chris@16
|
774 //
|
Chris@16
|
775 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
776 std::size_t desired = greedy ? rep->max : rep->min;
|
Chris@16
|
777 if(::boost::is_random_access_iterator<BidiIterator>::value)
|
Chris@16
|
778 {
|
Chris@16
|
779 BidiIterator end = position;
|
Chris@16
|
780 // Move end forward by "desired", preferably without using distance or advance if we can
|
Chris@16
|
781 // as these can be slow for some iterator types.
|
Chris@16
|
782 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
|
Chris@16
|
783 if(desired >= len)
|
Chris@16
|
784 end = last;
|
Chris@16
|
785 else
|
Chris@16
|
786 std::advance(end, desired);
|
Chris@16
|
787 BidiIterator origin(position);
|
Chris@16
|
788 while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
|
Chris@16
|
789 {
|
Chris@16
|
790 ++position;
|
Chris@16
|
791 }
|
Chris@16
|
792 count = (unsigned)::boost::re_detail::distance(origin, position);
|
Chris@16
|
793 }
|
Chris@16
|
794 else
|
Chris@16
|
795 {
|
Chris@16
|
796 while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
|
Chris@16
|
797 {
|
Chris@16
|
798 ++position;
|
Chris@16
|
799 ++count;
|
Chris@16
|
800 }
|
Chris@16
|
801 }
|
Chris@16
|
802
|
Chris@16
|
803 if(count < rep->min)
|
Chris@16
|
804 return false;
|
Chris@16
|
805
|
Chris@16
|
806 if(greedy)
|
Chris@16
|
807 {
|
Chris@16
|
808 if((rep->leading) && (count < rep->max))
|
Chris@16
|
809 restart = position;
|
Chris@16
|
810 // push backtrack info if available:
|
Chris@16
|
811 if(count - rep->min)
|
Chris@16
|
812 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
|
Chris@16
|
813 // jump to next state:
|
Chris@16
|
814 pstate = rep->alt.p;
|
Chris@16
|
815 return true;
|
Chris@16
|
816 }
|
Chris@16
|
817 else
|
Chris@16
|
818 {
|
Chris@16
|
819 // non-greedy, push state and return true if we can skip:
|
Chris@16
|
820 if(count < rep->max)
|
Chris@16
|
821 push_single_repeat(count, rep, position, saved_state_rep_short_set);
|
Chris@16
|
822 pstate = rep->alt.p;
|
Chris@16
|
823 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
|
Chris@16
|
824 }
|
Chris@16
|
825 #ifdef __BORLANDC__
|
Chris@16
|
826 #pragma option pop
|
Chris@16
|
827 #endif
|
Chris@16
|
828 #ifdef BOOST_MSVC
|
Chris@16
|
829 #pragma warning(pop)
|
Chris@16
|
830 #endif
|
Chris@16
|
831 }
|
Chris@16
|
832
|
Chris@16
|
833 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
834 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
|
Chris@16
|
835 {
|
Chris@16
|
836 #ifdef BOOST_MSVC
|
Chris@16
|
837 #pragma warning(push)
|
Chris@16
|
838 #pragma warning(disable:4127)
|
Chris@16
|
839 #endif
|
Chris@16
|
840 #ifdef __BORLANDC__
|
Chris@16
|
841 #pragma option push -w-8008 -w-8066 -w-8004
|
Chris@16
|
842 #endif
|
Chris@16
|
843 typedef typename traits::char_class_type m_type;
|
Chris@16
|
844 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
|
Chris@16
|
845 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate->next.p);
|
Chris@16
|
846 std::size_t count = 0;
|
Chris@16
|
847 //
|
Chris@16
|
848 // start by working out how much we can skip:
|
Chris@16
|
849 //
|
Chris@16
|
850 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
|
Chris@16
|
851 std::size_t desired = greedy ? rep->max : rep->min;
|
Chris@16
|
852 if(::boost::is_random_access_iterator<BidiIterator>::value)
|
Chris@16
|
853 {
|
Chris@16
|
854 BidiIterator end = position;
|
Chris@16
|
855 // Move end forward by "desired", preferably without using distance or advance if we can
|
Chris@16
|
856 // as these can be slow for some iterator types.
|
Chris@16
|
857 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::re_detail::distance(position, last);
|
Chris@16
|
858 if(desired >= len)
|
Chris@16
|
859 end = last;
|
Chris@16
|
860 else
|
Chris@16
|
861 std::advance(end, desired);
|
Chris@16
|
862 BidiIterator origin(position);
|
Chris@16
|
863 while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
|
Chris@16
|
864 {
|
Chris@16
|
865 ++position;
|
Chris@16
|
866 }
|
Chris@16
|
867 count = (unsigned)::boost::re_detail::distance(origin, position);
|
Chris@16
|
868 }
|
Chris@16
|
869 else
|
Chris@16
|
870 {
|
Chris@16
|
871 while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
|
Chris@16
|
872 {
|
Chris@16
|
873 ++position;
|
Chris@16
|
874 ++count;
|
Chris@16
|
875 }
|
Chris@16
|
876 }
|
Chris@16
|
877
|
Chris@16
|
878 if(count < rep->min)
|
Chris@16
|
879 return false;
|
Chris@16
|
880
|
Chris@16
|
881 if(greedy)
|
Chris@16
|
882 {
|
Chris@16
|
883 if((rep->leading) && (count < rep->max))
|
Chris@16
|
884 restart = position;
|
Chris@16
|
885 // push backtrack info if available:
|
Chris@16
|
886 if(count - rep->min)
|
Chris@16
|
887 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
|
Chris@16
|
888 // jump to next state:
|
Chris@16
|
889 pstate = rep->alt.p;
|
Chris@16
|
890 return true;
|
Chris@16
|
891 }
|
Chris@16
|
892 else
|
Chris@16
|
893 {
|
Chris@16
|
894 // non-greedy, push state and return true if we can skip:
|
Chris@16
|
895 if(count < rep->max)
|
Chris@16
|
896 push_single_repeat(count, rep, position, saved_state_rep_long_set);
|
Chris@16
|
897 pstate = rep->alt.p;
|
Chris@16
|
898 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
|
Chris@16
|
899 }
|
Chris@16
|
900 #ifdef __BORLANDC__
|
Chris@16
|
901 #pragma option pop
|
Chris@16
|
902 #endif
|
Chris@16
|
903 #ifdef BOOST_MSVC
|
Chris@16
|
904 #pragma warning(pop)
|
Chris@16
|
905 #endif
|
Chris@16
|
906 }
|
Chris@16
|
907
|
Chris@16
|
908 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
909 bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
|
Chris@16
|
910 {
|
Chris@16
|
911 BOOST_ASSERT(pstate->type == syntax_element_recurse);
|
Chris@16
|
912 //
|
Chris@16
|
913 // Backup call stack:
|
Chris@16
|
914 //
|
Chris@16
|
915 push_recursion_pop();
|
Chris@16
|
916 //
|
Chris@16
|
917 // Set new call stack:
|
Chris@16
|
918 //
|
Chris@16
|
919 if(recursion_stack.capacity() == 0)
|
Chris@16
|
920 {
|
Chris@16
|
921 recursion_stack.reserve(50);
|
Chris@16
|
922 }
|
Chris@16
|
923 recursion_stack.push_back(recursion_info<results_type>());
|
Chris@16
|
924 recursion_stack.back().preturn_address = pstate->next.p;
|
Chris@16
|
925 recursion_stack.back().results = *m_presult;
|
Chris@16
|
926 if(static_cast<const re_recurse*>(pstate)->state_id > 0)
|
Chris@16
|
927 {
|
Chris@16
|
928 push_repeater_count(static_cast<const re_recurse*>(pstate)->state_id, &next_count);
|
Chris@16
|
929 }
|
Chris@16
|
930 pstate = static_cast<const re_jump*>(pstate)->alt.p;
|
Chris@16
|
931 recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
|
Chris@16
|
932
|
Chris@16
|
933 return true;
|
Chris@16
|
934 }
|
Chris@16
|
935
|
Chris@16
|
936 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
937 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
|
Chris@16
|
938 {
|
Chris@16
|
939 int index = static_cast<const re_brace*>(pstate)->index;
|
Chris@16
|
940 icase = static_cast<const re_brace*>(pstate)->icase;
|
Chris@16
|
941 if(index > 0)
|
Chris@16
|
942 {
|
Chris@16
|
943 if((m_match_flags & match_nosubs) == 0)
|
Chris@16
|
944 {
|
Chris@16
|
945 m_presult->set_second(position, index);
|
Chris@16
|
946 }
|
Chris@16
|
947 if(!recursion_stack.empty())
|
Chris@16
|
948 {
|
Chris@16
|
949 if(index == recursion_stack.back().idx)
|
Chris@16
|
950 {
|
Chris@16
|
951 pstate = recursion_stack.back().preturn_address;
|
Chris@16
|
952 *m_presult = recursion_stack.back().results;
|
Chris@16
|
953 push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results);
|
Chris@16
|
954 recursion_stack.pop_back();
|
Chris@16
|
955 }
|
Chris@16
|
956 }
|
Chris@16
|
957 }
|
Chris@16
|
958 else if((index < 0) && (index != -4))
|
Chris@16
|
959 {
|
Chris@16
|
960 // matched forward lookahead:
|
Chris@16
|
961 pstate = 0;
|
Chris@16
|
962 return true;
|
Chris@16
|
963 }
|
Chris@16
|
964 pstate = pstate->next.p;
|
Chris@16
|
965 return true;
|
Chris@16
|
966 }
|
Chris@16
|
967
|
Chris@16
|
968 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
969 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
|
Chris@16
|
970 {
|
Chris@16
|
971 if(!recursion_stack.empty())
|
Chris@16
|
972 {
|
Chris@16
|
973 BOOST_ASSERT(0 == recursion_stack.back().idx);
|
Chris@16
|
974 pstate = recursion_stack.back().preturn_address;
|
Chris@16
|
975 *m_presult = recursion_stack.back().results;
|
Chris@16
|
976 push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results);
|
Chris@16
|
977 recursion_stack.pop_back();
|
Chris@16
|
978 return true;
|
Chris@16
|
979 }
|
Chris@16
|
980 if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
|
Chris@16
|
981 return false;
|
Chris@16
|
982 if((m_match_flags & match_all) && (position != last))
|
Chris@16
|
983 return false;
|
Chris@16
|
984 if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
|
Chris@16
|
985 return false;
|
Chris@16
|
986 m_presult->set_second(position);
|
Chris@16
|
987 pstate = 0;
|
Chris@16
|
988 m_has_found_match = true;
|
Chris@16
|
989 if((m_match_flags & match_posix) == match_posix)
|
Chris@16
|
990 {
|
Chris@16
|
991 m_result.maybe_assign(*m_presult);
|
Chris@16
|
992 if((m_match_flags & match_any) == 0)
|
Chris@16
|
993 return false;
|
Chris@16
|
994 }
|
Chris@16
|
995 #ifdef BOOST_REGEX_MATCH_EXTRA
|
Chris@16
|
996 if(match_extra & m_match_flags)
|
Chris@16
|
997 {
|
Chris@16
|
998 for(unsigned i = 0; i < m_presult->size(); ++i)
|
Chris@16
|
999 if((*m_presult)[i].matched)
|
Chris@16
|
1000 ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
|
Chris@16
|
1001 }
|
Chris@16
|
1002 #endif
|
Chris@16
|
1003 return true;
|
Chris@16
|
1004 }
|
Chris@16
|
1005
|
Chris@16
|
1006 /****************************************************************************
|
Chris@16
|
1007
|
Chris@16
|
1008 Unwind and associated proceedures follow, these perform what normal stack
|
Chris@16
|
1009 unwinding does in the recursive implementation.
|
Chris@16
|
1010
|
Chris@16
|
1011 ****************************************************************************/
|
Chris@16
|
1012
|
Chris@16
|
1013 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1014 bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
|
Chris@16
|
1015 {
|
Chris@16
|
1016 static unwind_proc_type const s_unwind_table[18] =
|
Chris@16
|
1017 {
|
Chris@16
|
1018 &perl_matcher<BidiIterator, Allocator, traits>::unwind_end,
|
Chris@16
|
1019 &perl_matcher<BidiIterator, Allocator, traits>::unwind_paren,
|
Chris@16
|
1020 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper,
|
Chris@16
|
1021 &perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion,
|
Chris@16
|
1022 &perl_matcher<BidiIterator, Allocator, traits>::unwind_alt,
|
Chris@16
|
1023 &perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter,
|
Chris@16
|
1024 &perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block,
|
Chris@16
|
1025 &perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat,
|
Chris@16
|
1026 &perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat,
|
Chris@16
|
1027 &perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat,
|
Chris@16
|
1028 &perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat,
|
Chris@16
|
1029 &perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat,
|
Chris@16
|
1030 &perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat,
|
Chris@16
|
1031 &perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat,
|
Chris@16
|
1032 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion,
|
Chris@16
|
1033 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop,
|
Chris@16
|
1034 };
|
Chris@16
|
1035
|
Chris@16
|
1036 m_recursive_result = have_match;
|
Chris@16
|
1037 unwind_proc_type unwinder;
|
Chris@16
|
1038 bool cont;
|
Chris@16
|
1039 //
|
Chris@16
|
1040 // keep unwinding our stack until we have something to do:
|
Chris@16
|
1041 //
|
Chris@16
|
1042 do
|
Chris@16
|
1043 {
|
Chris@16
|
1044 unwinder = s_unwind_table[m_backup_state->state_id];
|
Chris@16
|
1045 cont = (this->*unwinder)(m_recursive_result);
|
Chris@16
|
1046 }while(cont);
|
Chris@16
|
1047 //
|
Chris@16
|
1048 // return true if we have more states to try:
|
Chris@16
|
1049 //
|
Chris@16
|
1050 return pstate ? true : false;
|
Chris@16
|
1051 }
|
Chris@16
|
1052
|
Chris@16
|
1053 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1054 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool)
|
Chris@16
|
1055 {
|
Chris@16
|
1056 pstate = 0; // nothing left to search
|
Chris@16
|
1057 return false; // end of stack nothing more to search
|
Chris@16
|
1058 }
|
Chris@16
|
1059
|
Chris@16
|
1060 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1061 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match)
|
Chris@16
|
1062 {
|
Chris@16
|
1063 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1064 // restore previous values if no match was found:
|
Chris@16
|
1065 if(have_match == false)
|
Chris@16
|
1066 {
|
Chris@16
|
1067 m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0);
|
Chris@16
|
1068 m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0);
|
Chris@16
|
1069 }
|
Chris@16
|
1070 #ifdef BOOST_REGEX_MATCH_EXTRA
|
Chris@16
|
1071 //
|
Chris@16
|
1072 // we have a match, push the capture information onto the stack:
|
Chris@16
|
1073 //
|
Chris@16
|
1074 else if(pmp->sub.matched && (match_extra & m_match_flags))
|
Chris@16
|
1075 ((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub);
|
Chris@16
|
1076 #endif
|
Chris@16
|
1077 // unwind stack:
|
Chris@16
|
1078 m_backup_state = pmp+1;
|
Chris@16
|
1079 boost::re_detail::inplace_destroy(pmp);
|
Chris@16
|
1080 return true; // keep looking
|
Chris@16
|
1081 }
|
Chris@16
|
1082
|
Chris@16
|
1083 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1084 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper(bool)
|
Chris@16
|
1085 {
|
Chris@16
|
1086 boost::re_detail::inplace_destroy(m_backup_state++);
|
Chris@16
|
1087 pstate = 0; // nothing left to search
|
Chris@16
|
1088 return false; // end of stack nothing more to search
|
Chris@16
|
1089 }
|
Chris@16
|
1090
|
Chris@16
|
1091 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1092 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion(bool r)
|
Chris@16
|
1093 {
|
Chris@16
|
1094 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1095 pstate = pmp->pstate;
|
Chris@16
|
1096 position = pmp->position;
|
Chris@16
|
1097 bool result = (r == pmp->positive);
|
Chris@16
|
1098 m_recursive_result = pmp->positive ? r : !r;
|
Chris@16
|
1099 boost::re_detail::inplace_destroy(pmp++);
|
Chris@16
|
1100 m_backup_state = pmp;
|
Chris@16
|
1101 return !result; // return false if the assertion was matched to stop search.
|
Chris@16
|
1102 }
|
Chris@16
|
1103
|
Chris@16
|
1104 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1105 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_alt(bool r)
|
Chris@16
|
1106 {
|
Chris@16
|
1107 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1108 if(!r)
|
Chris@16
|
1109 {
|
Chris@16
|
1110 pstate = pmp->pstate;
|
Chris@16
|
1111 position = pmp->position;
|
Chris@16
|
1112 }
|
Chris@16
|
1113 boost::re_detail::inplace_destroy(pmp++);
|
Chris@16
|
1114 m_backup_state = pmp;
|
Chris@16
|
1115 return r;
|
Chris@16
|
1116 }
|
Chris@16
|
1117
|
Chris@16
|
1118 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1119 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter(bool)
|
Chris@16
|
1120 {
|
Chris@16
|
1121 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1122 boost::re_detail::inplace_destroy(pmp++);
|
Chris@16
|
1123 m_backup_state = pmp;
|
Chris@16
|
1124 return true; // keep looking
|
Chris@16
|
1125 }
|
Chris@16
|
1126
|
Chris@16
|
1127 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1128 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block(bool)
|
Chris@16
|
1129 {
|
Chris@16
|
1130 saved_extra_block* pmp = static_cast<saved_extra_block*>(m_backup_state);
|
Chris@16
|
1131 void* condemmed = m_stack_base;
|
Chris@16
|
1132 m_stack_base = pmp->base;
|
Chris@16
|
1133 m_backup_state = pmp->end;
|
Chris@16
|
1134 boost::re_detail::inplace_destroy(pmp);
|
Chris@16
|
1135 put_mem_block(condemmed);
|
Chris@16
|
1136 return true; // keep looking
|
Chris@16
|
1137 }
|
Chris@16
|
1138
|
Chris@16
|
1139 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1140 inline void perl_matcher<BidiIterator, Allocator, traits>::destroy_single_repeat()
|
Chris@16
|
1141 {
|
Chris@16
|
1142 saved_single_repeat<BidiIterator>* p = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1143 boost::re_detail::inplace_destroy(p++);
|
Chris@16
|
1144 m_backup_state = p;
|
Chris@16
|
1145 }
|
Chris@16
|
1146
|
Chris@16
|
1147 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1148 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(bool r)
|
Chris@16
|
1149 {
|
Chris@16
|
1150 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1151
|
Chris@16
|
1152 // if we have a match, just discard this state:
|
Chris@16
|
1153 if(r)
|
Chris@16
|
1154 {
|
Chris@16
|
1155 destroy_single_repeat();
|
Chris@16
|
1156 return true;
|
Chris@16
|
1157 }
|
Chris@16
|
1158
|
Chris@16
|
1159 const re_repeat* rep = pmp->rep;
|
Chris@16
|
1160 std::size_t count = pmp->count;
|
Chris@16
|
1161 BOOST_ASSERT(rep->next.p != 0);
|
Chris@16
|
1162 BOOST_ASSERT(rep->alt.p != 0);
|
Chris@16
|
1163
|
Chris@16
|
1164 count -= rep->min;
|
Chris@16
|
1165
|
Chris@16
|
1166 if((m_match_flags & match_partial) && (position == last))
|
Chris@16
|
1167 m_has_partial_match = true;
|
Chris@16
|
1168
|
Chris@16
|
1169 BOOST_ASSERT(count);
|
Chris@16
|
1170 position = pmp->last_position;
|
Chris@16
|
1171
|
Chris@16
|
1172 // backtrack till we can skip out:
|
Chris@16
|
1173 do
|
Chris@16
|
1174 {
|
Chris@16
|
1175 --position;
|
Chris@16
|
1176 --count;
|
Chris@16
|
1177 ++state_count;
|
Chris@16
|
1178 }while(count && !can_start(*position, rep->_map, mask_skip));
|
Chris@16
|
1179
|
Chris@16
|
1180 // if we've hit base, destroy this state:
|
Chris@16
|
1181 if(count == 0)
|
Chris@16
|
1182 {
|
Chris@16
|
1183 destroy_single_repeat();
|
Chris@16
|
1184 if(!can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
1185 return true;
|
Chris@16
|
1186 }
|
Chris@16
|
1187 else
|
Chris@16
|
1188 {
|
Chris@16
|
1189 pmp->count = count + rep->min;
|
Chris@16
|
1190 pmp->last_position = position;
|
Chris@16
|
1191 }
|
Chris@16
|
1192 pstate = rep->alt.p;
|
Chris@16
|
1193 return false;
|
Chris@16
|
1194 }
|
Chris@16
|
1195
|
Chris@16
|
1196 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1197 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool r)
|
Chris@16
|
1198 {
|
Chris@16
|
1199 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1200
|
Chris@16
|
1201 // if we have a match, just discard this state:
|
Chris@16
|
1202 if(r)
|
Chris@16
|
1203 {
|
Chris@16
|
1204 destroy_single_repeat();
|
Chris@16
|
1205 return true;
|
Chris@16
|
1206 }
|
Chris@16
|
1207
|
Chris@16
|
1208 const re_repeat* rep = pmp->rep;
|
Chris@16
|
1209 std::size_t count = pmp->count;
|
Chris@16
|
1210 BOOST_ASSERT(rep->type == syntax_element_dot_rep);
|
Chris@16
|
1211 BOOST_ASSERT(rep->next.p != 0);
|
Chris@16
|
1212 BOOST_ASSERT(rep->alt.p != 0);
|
Chris@16
|
1213 BOOST_ASSERT(rep->next.p->type == syntax_element_wild);
|
Chris@16
|
1214
|
Chris@16
|
1215 BOOST_ASSERT(count < rep->max);
|
Chris@16
|
1216 pstate = rep->next.p;
|
Chris@16
|
1217 position = pmp->last_position;
|
Chris@16
|
1218
|
Chris@16
|
1219 if(position != last)
|
Chris@16
|
1220 {
|
Chris@16
|
1221 // wind forward until we can skip out of the repeat:
|
Chris@16
|
1222 do
|
Chris@16
|
1223 {
|
Chris@16
|
1224 if(!match_wild())
|
Chris@16
|
1225 {
|
Chris@16
|
1226 // failed repeat match, discard this state and look for another:
|
Chris@16
|
1227 destroy_single_repeat();
|
Chris@16
|
1228 return true;
|
Chris@16
|
1229 }
|
Chris@16
|
1230 ++count;
|
Chris@16
|
1231 ++state_count;
|
Chris@16
|
1232 pstate = rep->next.p;
|
Chris@16
|
1233 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
|
Chris@16
|
1234 }
|
Chris@16
|
1235 if(position == last)
|
Chris@16
|
1236 {
|
Chris@16
|
1237 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1238 destroy_single_repeat();
|
Chris@16
|
1239 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
|
Chris@16
|
1240 m_has_partial_match = true;
|
Chris@16
|
1241 if(0 == (rep->can_be_null & mask_skip))
|
Chris@16
|
1242 return true;
|
Chris@16
|
1243 }
|
Chris@16
|
1244 else if(count == rep->max)
|
Chris@16
|
1245 {
|
Chris@16
|
1246 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1247 destroy_single_repeat();
|
Chris@16
|
1248 if(!can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
1249 return true;
|
Chris@16
|
1250 }
|
Chris@16
|
1251 else
|
Chris@16
|
1252 {
|
Chris@16
|
1253 pmp->count = count;
|
Chris@16
|
1254 pmp->last_position = position;
|
Chris@16
|
1255 }
|
Chris@16
|
1256 pstate = rep->alt.p;
|
Chris@16
|
1257 return false;
|
Chris@16
|
1258 }
|
Chris@16
|
1259
|
Chris@16
|
1260 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1261 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat(bool r)
|
Chris@16
|
1262 {
|
Chris@16
|
1263 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1264
|
Chris@16
|
1265 // if we have a match, just discard this state:
|
Chris@16
|
1266 if(r)
|
Chris@16
|
1267 {
|
Chris@16
|
1268 destroy_single_repeat();
|
Chris@16
|
1269 return true;
|
Chris@16
|
1270 }
|
Chris@16
|
1271
|
Chris@16
|
1272 const re_repeat* rep = pmp->rep;
|
Chris@16
|
1273 std::size_t count = pmp->count;
|
Chris@16
|
1274
|
Chris@16
|
1275 BOOST_ASSERT(count < rep->max);
|
Chris@16
|
1276 position = pmp->last_position;
|
Chris@16
|
1277 if(position != last)
|
Chris@16
|
1278 {
|
Chris@16
|
1279
|
Chris@16
|
1280 // wind forward until we can skip out of the repeat:
|
Chris@16
|
1281 do
|
Chris@16
|
1282 {
|
Chris@16
|
1283 ++position;
|
Chris@16
|
1284 ++count;
|
Chris@16
|
1285 ++state_count;
|
Chris@16
|
1286 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
|
Chris@16
|
1287 }
|
Chris@16
|
1288
|
Chris@16
|
1289 // remember where we got to if this is a leading repeat:
|
Chris@16
|
1290 if((rep->leading) && (count < rep->max))
|
Chris@16
|
1291 restart = position;
|
Chris@16
|
1292 if(position == last)
|
Chris@16
|
1293 {
|
Chris@16
|
1294 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1295 destroy_single_repeat();
|
Chris@16
|
1296 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
|
Chris@16
|
1297 m_has_partial_match = true;
|
Chris@16
|
1298 if(0 == (rep->can_be_null & mask_skip))
|
Chris@16
|
1299 return true;
|
Chris@16
|
1300 }
|
Chris@16
|
1301 else if(count == rep->max)
|
Chris@16
|
1302 {
|
Chris@16
|
1303 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1304 destroy_single_repeat();
|
Chris@16
|
1305 if(!can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
1306 return true;
|
Chris@16
|
1307 }
|
Chris@16
|
1308 else
|
Chris@16
|
1309 {
|
Chris@16
|
1310 pmp->count = count;
|
Chris@16
|
1311 pmp->last_position = position;
|
Chris@16
|
1312 }
|
Chris@16
|
1313 pstate = rep->alt.p;
|
Chris@16
|
1314 return false;
|
Chris@16
|
1315 }
|
Chris@16
|
1316
|
Chris@16
|
1317 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1318 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r)
|
Chris@16
|
1319 {
|
Chris@16
|
1320 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1321
|
Chris@16
|
1322 // if we have a match, just discard this state:
|
Chris@16
|
1323 if(r)
|
Chris@16
|
1324 {
|
Chris@16
|
1325 destroy_single_repeat();
|
Chris@16
|
1326 return true;
|
Chris@16
|
1327 }
|
Chris@16
|
1328
|
Chris@16
|
1329 const re_repeat* rep = pmp->rep;
|
Chris@16
|
1330 std::size_t count = pmp->count;
|
Chris@16
|
1331 pstate = rep->next.p;
|
Chris@16
|
1332 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
|
Chris@16
|
1333 position = pmp->last_position;
|
Chris@16
|
1334
|
Chris@16
|
1335 BOOST_ASSERT(rep->type == syntax_element_char_rep);
|
Chris@16
|
1336 BOOST_ASSERT(rep->next.p != 0);
|
Chris@16
|
1337 BOOST_ASSERT(rep->alt.p != 0);
|
Chris@16
|
1338 BOOST_ASSERT(rep->next.p->type == syntax_element_literal);
|
Chris@16
|
1339 BOOST_ASSERT(count < rep->max);
|
Chris@16
|
1340
|
Chris@16
|
1341 if(position != last)
|
Chris@16
|
1342 {
|
Chris@16
|
1343 // wind forward until we can skip out of the repeat:
|
Chris@16
|
1344 do
|
Chris@16
|
1345 {
|
Chris@16
|
1346 if(traits_inst.translate(*position, icase) != what)
|
Chris@16
|
1347 {
|
Chris@16
|
1348 // failed repeat match, discard this state and look for another:
|
Chris@16
|
1349 destroy_single_repeat();
|
Chris@16
|
1350 return true;
|
Chris@16
|
1351 }
|
Chris@16
|
1352 ++count;
|
Chris@16
|
1353 ++ position;
|
Chris@16
|
1354 ++state_count;
|
Chris@16
|
1355 pstate = rep->next.p;
|
Chris@16
|
1356 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
|
Chris@16
|
1357 }
|
Chris@16
|
1358 // remember where we got to if this is a leading repeat:
|
Chris@16
|
1359 if((rep->leading) && (count < rep->max))
|
Chris@16
|
1360 restart = position;
|
Chris@16
|
1361 if(position == last)
|
Chris@16
|
1362 {
|
Chris@16
|
1363 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1364 destroy_single_repeat();
|
Chris@16
|
1365 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
|
Chris@16
|
1366 m_has_partial_match = true;
|
Chris@16
|
1367 if(0 == (rep->can_be_null & mask_skip))
|
Chris@16
|
1368 return true;
|
Chris@16
|
1369 }
|
Chris@16
|
1370 else if(count == rep->max)
|
Chris@16
|
1371 {
|
Chris@16
|
1372 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1373 destroy_single_repeat();
|
Chris@16
|
1374 if(!can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
1375 return true;
|
Chris@16
|
1376 }
|
Chris@16
|
1377 else
|
Chris@16
|
1378 {
|
Chris@16
|
1379 pmp->count = count;
|
Chris@16
|
1380 pmp->last_position = position;
|
Chris@16
|
1381 }
|
Chris@16
|
1382 pstate = rep->alt.p;
|
Chris@16
|
1383 return false;
|
Chris@16
|
1384 }
|
Chris@16
|
1385
|
Chris@16
|
1386 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1387 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool r)
|
Chris@16
|
1388 {
|
Chris@16
|
1389 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1390
|
Chris@16
|
1391 // if we have a match, just discard this state:
|
Chris@16
|
1392 if(r)
|
Chris@16
|
1393 {
|
Chris@16
|
1394 destroy_single_repeat();
|
Chris@16
|
1395 return true;
|
Chris@16
|
1396 }
|
Chris@16
|
1397
|
Chris@16
|
1398 const re_repeat* rep = pmp->rep;
|
Chris@16
|
1399 std::size_t count = pmp->count;
|
Chris@16
|
1400 pstate = rep->next.p;
|
Chris@16
|
1401 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
|
Chris@16
|
1402 position = pmp->last_position;
|
Chris@16
|
1403
|
Chris@16
|
1404 BOOST_ASSERT(rep->type == syntax_element_short_set_rep);
|
Chris@16
|
1405 BOOST_ASSERT(rep->next.p != 0);
|
Chris@16
|
1406 BOOST_ASSERT(rep->alt.p != 0);
|
Chris@16
|
1407 BOOST_ASSERT(rep->next.p->type == syntax_element_set);
|
Chris@16
|
1408 BOOST_ASSERT(count < rep->max);
|
Chris@16
|
1409
|
Chris@16
|
1410 if(position != last)
|
Chris@16
|
1411 {
|
Chris@16
|
1412 // wind forward until we can skip out of the repeat:
|
Chris@16
|
1413 do
|
Chris@16
|
1414 {
|
Chris@16
|
1415 if(!map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
|
Chris@16
|
1416 {
|
Chris@16
|
1417 // failed repeat match, discard this state and look for another:
|
Chris@16
|
1418 destroy_single_repeat();
|
Chris@16
|
1419 return true;
|
Chris@16
|
1420 }
|
Chris@16
|
1421 ++count;
|
Chris@16
|
1422 ++ position;
|
Chris@16
|
1423 ++state_count;
|
Chris@16
|
1424 pstate = rep->next.p;
|
Chris@16
|
1425 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
|
Chris@16
|
1426 }
|
Chris@16
|
1427 // remember where we got to if this is a leading repeat:
|
Chris@16
|
1428 if((rep->leading) && (count < rep->max))
|
Chris@16
|
1429 restart = position;
|
Chris@16
|
1430 if(position == last)
|
Chris@16
|
1431 {
|
Chris@16
|
1432 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1433 destroy_single_repeat();
|
Chris@16
|
1434 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
|
Chris@16
|
1435 m_has_partial_match = true;
|
Chris@16
|
1436 if(0 == (rep->can_be_null & mask_skip))
|
Chris@16
|
1437 return true;
|
Chris@16
|
1438 }
|
Chris@16
|
1439 else if(count == rep->max)
|
Chris@16
|
1440 {
|
Chris@16
|
1441 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1442 destroy_single_repeat();
|
Chris@16
|
1443 if(!can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
1444 return true;
|
Chris@16
|
1445 }
|
Chris@16
|
1446 else
|
Chris@16
|
1447 {
|
Chris@16
|
1448 pmp->count = count;
|
Chris@16
|
1449 pmp->last_position = position;
|
Chris@16
|
1450 }
|
Chris@16
|
1451 pstate = rep->alt.p;
|
Chris@16
|
1452 return false;
|
Chris@16
|
1453 }
|
Chris@16
|
1454
|
Chris@16
|
1455 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1456 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool r)
|
Chris@16
|
1457 {
|
Chris@16
|
1458 typedef typename traits::char_class_type m_type;
|
Chris@16
|
1459 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1460
|
Chris@16
|
1461 // if we have a match, just discard this state:
|
Chris@16
|
1462 if(r)
|
Chris@16
|
1463 {
|
Chris@16
|
1464 destroy_single_repeat();
|
Chris@16
|
1465 return true;
|
Chris@16
|
1466 }
|
Chris@16
|
1467
|
Chris@16
|
1468 const re_repeat* rep = pmp->rep;
|
Chris@16
|
1469 std::size_t count = pmp->count;
|
Chris@16
|
1470 pstate = rep->next.p;
|
Chris@16
|
1471 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate);
|
Chris@16
|
1472 position = pmp->last_position;
|
Chris@16
|
1473
|
Chris@16
|
1474 BOOST_ASSERT(rep->type == syntax_element_long_set_rep);
|
Chris@16
|
1475 BOOST_ASSERT(rep->next.p != 0);
|
Chris@16
|
1476 BOOST_ASSERT(rep->alt.p != 0);
|
Chris@16
|
1477 BOOST_ASSERT(rep->next.p->type == syntax_element_long_set);
|
Chris@16
|
1478 BOOST_ASSERT(count < rep->max);
|
Chris@16
|
1479
|
Chris@16
|
1480 if(position != last)
|
Chris@16
|
1481 {
|
Chris@16
|
1482 // wind forward until we can skip out of the repeat:
|
Chris@16
|
1483 do
|
Chris@16
|
1484 {
|
Chris@16
|
1485 if(position == re_is_set_member(position, last, set, re.get_data(), icase))
|
Chris@16
|
1486 {
|
Chris@16
|
1487 // failed repeat match, discard this state and look for another:
|
Chris@16
|
1488 destroy_single_repeat();
|
Chris@16
|
1489 return true;
|
Chris@16
|
1490 }
|
Chris@16
|
1491 ++position;
|
Chris@16
|
1492 ++count;
|
Chris@16
|
1493 ++state_count;
|
Chris@16
|
1494 pstate = rep->next.p;
|
Chris@16
|
1495 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
|
Chris@16
|
1496 }
|
Chris@16
|
1497 // remember where we got to if this is a leading repeat:
|
Chris@16
|
1498 if((rep->leading) && (count < rep->max))
|
Chris@16
|
1499 restart = position;
|
Chris@16
|
1500 if(position == last)
|
Chris@16
|
1501 {
|
Chris@16
|
1502 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1503 destroy_single_repeat();
|
Chris@16
|
1504 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
|
Chris@16
|
1505 m_has_partial_match = true;
|
Chris@16
|
1506 if(0 == (rep->can_be_null & mask_skip))
|
Chris@16
|
1507 return true;
|
Chris@16
|
1508 }
|
Chris@16
|
1509 else if(count == rep->max)
|
Chris@16
|
1510 {
|
Chris@16
|
1511 // can't repeat any more, remove the pushed state:
|
Chris@16
|
1512 destroy_single_repeat();
|
Chris@16
|
1513 if(!can_start(*position, rep->_map, mask_skip))
|
Chris@16
|
1514 return true;
|
Chris@16
|
1515 }
|
Chris@16
|
1516 else
|
Chris@16
|
1517 {
|
Chris@16
|
1518 pmp->count = count;
|
Chris@16
|
1519 pmp->last_position = position;
|
Chris@16
|
1520 }
|
Chris@16
|
1521 pstate = rep->alt.p;
|
Chris@16
|
1522 return false;
|
Chris@16
|
1523 }
|
Chris@16
|
1524
|
Chris@16
|
1525 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1526 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat(bool r)
|
Chris@16
|
1527 {
|
Chris@16
|
1528 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1529 if(!r)
|
Chris@16
|
1530 {
|
Chris@16
|
1531 position = pmp->position;
|
Chris@16
|
1532 pstate = pmp->pstate;
|
Chris@16
|
1533 ++(*next_count);
|
Chris@16
|
1534 }
|
Chris@16
|
1535 boost::re_detail::inplace_destroy(pmp++);
|
Chris@16
|
1536 m_backup_state = pmp;
|
Chris@16
|
1537 return r;
|
Chris@16
|
1538 }
|
Chris@16
|
1539
|
Chris@16
|
1540 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1541 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
|
Chris@16
|
1542 {
|
Chris@16
|
1543 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
|
Chris@16
|
1544 if(!r)
|
Chris@16
|
1545 {
|
Chris@16
|
1546 recursion_stack.push_back(recursion_info<results_type>());
|
Chris@16
|
1547 recursion_stack.back().idx = pmp->recursion_id;
|
Chris@16
|
1548 recursion_stack.back().preturn_address = pmp->preturn_address;
|
Chris@16
|
1549 recursion_stack.back().results = pmp->results;
|
Chris@16
|
1550 }
|
Chris@16
|
1551 boost::re_detail::inplace_destroy(pmp++);
|
Chris@16
|
1552 m_backup_state = pmp;
|
Chris@16
|
1553 return true;
|
Chris@16
|
1554 }
|
Chris@16
|
1555
|
Chris@16
|
1556 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1557 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r)
|
Chris@16
|
1558 {
|
Chris@16
|
1559 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
|
Chris@16
|
1560 if(!r)
|
Chris@16
|
1561 {
|
Chris@16
|
1562 recursion_stack.pop_back();
|
Chris@16
|
1563 }
|
Chris@16
|
1564 boost::re_detail::inplace_destroy(pmp++);
|
Chris@16
|
1565 m_backup_state = pmp;
|
Chris@16
|
1566 return true;
|
Chris@16
|
1567 }
|
Chris@16
|
1568
|
Chris@16
|
1569 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1570 void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_pop()
|
Chris@16
|
1571 {
|
Chris@16
|
1572 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
|
Chris@16
|
1573 --pmp;
|
Chris@16
|
1574 if(pmp < m_stack_base)
|
Chris@16
|
1575 {
|
Chris@16
|
1576 extend_stack();
|
Chris@16
|
1577 pmp = static_cast<saved_state*>(m_backup_state);
|
Chris@16
|
1578 --pmp;
|
Chris@16
|
1579 }
|
Chris@16
|
1580 (void) new (pmp)saved_state(15);
|
Chris@16
|
1581 m_backup_state = pmp;
|
Chris@16
|
1582 }
|
Chris@16
|
1583 /*
|
Chris@16
|
1584 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1585 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_pop(bool r)
|
Chris@16
|
1586 {
|
Chris@16
|
1587 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
|
Chris@16
|
1588 if(!r)
|
Chris@16
|
1589 {
|
Chris@16
|
1590 --parenthesis_stack_position;
|
Chris@16
|
1591 }
|
Chris@16
|
1592 boost::re_detail::inplace_destroy(pmp++);
|
Chris@16
|
1593 m_backup_state = pmp;
|
Chris@16
|
1594 return true;
|
Chris@16
|
1595 }
|
Chris@16
|
1596
|
Chris@16
|
1597 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1598 void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_pop()
|
Chris@16
|
1599 {
|
Chris@16
|
1600 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
|
Chris@16
|
1601 --pmp;
|
Chris@16
|
1602 if(pmp < m_stack_base)
|
Chris@16
|
1603 {
|
Chris@16
|
1604 extend_stack();
|
Chris@16
|
1605 pmp = static_cast<saved_state*>(m_backup_state);
|
Chris@16
|
1606 --pmp;
|
Chris@16
|
1607 }
|
Chris@16
|
1608 (void) new (pmp)saved_state(16);
|
Chris@16
|
1609 m_backup_state = pmp;
|
Chris@16
|
1610 }
|
Chris@16
|
1611
|
Chris@16
|
1612 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1613 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_push(bool r)
|
Chris@16
|
1614 {
|
Chris@16
|
1615 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1616 if(!r)
|
Chris@16
|
1617 {
|
Chris@16
|
1618 parenthesis_stack[parenthesis_stack_position++] = pmp->position;
|
Chris@16
|
1619 }
|
Chris@16
|
1620 boost::re_detail::inplace_destroy(pmp++);
|
Chris@16
|
1621 m_backup_state = pmp;
|
Chris@16
|
1622 return true;
|
Chris@16
|
1623 }
|
Chris@16
|
1624
|
Chris@16
|
1625 template <class BidiIterator, class Allocator, class traits>
|
Chris@16
|
1626 inline void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_push(BidiIterator p)
|
Chris@16
|
1627 {
|
Chris@16
|
1628 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1629 --pmp;
|
Chris@16
|
1630 if(pmp < m_stack_base)
|
Chris@16
|
1631 {
|
Chris@16
|
1632 extend_stack();
|
Chris@16
|
1633 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
|
Chris@16
|
1634 --pmp;
|
Chris@16
|
1635 }
|
Chris@16
|
1636 (void) new (pmp)saved_position<BidiIterator>(0, p, 17);
|
Chris@16
|
1637 m_backup_state = pmp;
|
Chris@16
|
1638 }
|
Chris@16
|
1639 */
|
Chris@16
|
1640 } // namespace re_detail
|
Chris@16
|
1641 } // namespace boost
|
Chris@16
|
1642
|
Chris@16
|
1643 #ifdef BOOST_MSVC
|
Chris@16
|
1644 # pragma warning(pop)
|
Chris@16
|
1645 #endif
|
Chris@16
|
1646
|
Chris@16
|
1647 #ifdef BOOST_MSVC
|
Chris@16
|
1648 #pragma warning(push)
|
Chris@16
|
1649 #pragma warning(disable: 4103)
|
Chris@16
|
1650 #endif
|
Chris@16
|
1651 #ifdef BOOST_HAS_ABI_HEADERS
|
Chris@16
|
1652 # include BOOST_ABI_SUFFIX
|
Chris@16
|
1653 #endif
|
Chris@16
|
1654 #ifdef BOOST_MSVC
|
Chris@16
|
1655 #pragma warning(pop)
|
Chris@16
|
1656 #endif
|
Chris@16
|
1657
|
Chris@16
|
1658 #endif
|
Chris@16
|
1659
|
Chris@16
|
1660
|