6 * Use, modification and distribution are subject to the
7 * Boost Software License, Version 1.0. (See accompanying file
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13 * LOCATION: see http://www.boost.org for most recent version.
14 * FILE basic_regex_parser.cpp
15 * VERSION see <boost/version.hpp>
16 * DESCRIPTION: Declares template class basic_regex_parser.
19 #ifndef BOOST_REGEX_V4_BASIC_REGEX_PARSER_HPP
20 #define BOOST_REGEX_V4_BASIC_REGEX_PARSER_HPP
22 #ifdef BOOST_HAS_ABI_HEADERS
23 # include BOOST_ABI_PREFIX
31 #pragma warning(disable:4244)
34 template <class charT, class traits>
35 class basic_regex_parser : public basic_regex_creator<charT, traits>
38 basic_regex_parser(regex_data<charT, traits>* data);
39 void parse(const charT* p1, const charT* p2, unsigned flags);
40 void fail(regex_constants::error_type error_code, std::ptrdiff_t position);
44 bool parse_extended();
46 bool parse_open_paren();
47 bool parse_basic_escape();
48 bool parse_extended_escape();
49 bool parse_match_any();
50 bool parse_repeat(std::size_t low = 0, std::size_t high = (std::numeric_limits<std::size_t>::max)());
51 bool parse_repeat_range(bool isbasic);
55 void parse_set_literal(basic_char_set<charT, traits>& char_set);
56 bool parse_inner_set(basic_char_set<charT, traits>& char_set);
58 bool parse_perl_extension();
59 bool add_emacs_code(bool negate);
60 bool unwind_alts(std::ptrdiff_t last_paren_start);
61 digraph<charT> get_next_set_literal(basic_char_set<charT, traits>& char_set);
62 charT unescape_character();
63 regex_constants::syntax_option_type parse_options();
66 typedef bool (basic_regex_parser::*parser_proc_type)();
67 typedef typename traits::string_type string_type;
68 typedef typename traits::char_class_type char_class_type;
69 parser_proc_type m_parser_proc; // the main parser to use
70 const charT* m_base; // the start of the string being parsed
71 const charT* m_end; // the end of the string being parsed
72 const charT* m_position; // our current parser position
73 unsigned m_mark_count; // how many sub-expressions we have
74 std::ptrdiff_t m_paren_start; // where the last seen ')' began (where repeats are inserted).
75 std::ptrdiff_t m_alt_insert_point; // where to insert the next alternative
76 bool m_has_case_change; // true if somewhere in the current block the case has changed
77 #if defined(BOOST_MSVC) && defined(_M_IX86)
78 // This is an ugly warning suppression workaround (for warnings *inside* std::vector
79 // that can not otherwise be suppressed)...
80 BOOST_STATIC_ASSERT(sizeof(long) >= sizeof(void*));
81 std::vector<long> m_alt_jumps; // list of alternative in the current scope.
83 std::vector<std::ptrdiff_t> m_alt_jumps; // list of alternative in the current scope.
86 basic_regex_parser& operator=(const basic_regex_parser&);
87 basic_regex_parser(const basic_regex_parser&);
90 template <class charT, class traits>
91 basic_regex_parser<charT, traits>::basic_regex_parser(regex_data<charT, traits>* data)
92 : basic_regex_creator<charT, traits>(data), m_mark_count(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false)
96 template <class charT, class traits>
97 void basic_regex_parser<charT, traits>::parse(const charT* p1, const charT* p2, unsigned l_flags)
99 // pass l_flags on to base class:
102 m_position = m_base = p1;
104 // empty strings are errors:
107 fail(regex_constants::error_empty, 0);
110 // select which parser to use:
111 switch(l_flags & regbase::main_option_type)
113 case regbase::perl_syntax_group:
114 m_parser_proc = &basic_regex_parser<charT, traits>::parse_extended;
116 case regbase::basic_syntax_group:
117 m_parser_proc = &basic_regex_parser<charT, traits>::parse_basic;
119 case regbase::literal:
120 m_parser_proc = &basic_regex_parser<charT, traits>::parse_literal;
124 // parse all our characters:
125 bool result = parse_all();
127 // Unwind our alternatives:
130 // reset l_flags as a global scope (?imsx) may have altered them:
131 this->flags(l_flags);
132 // if we haven't gobbled up all the characters then we must
133 // have had an unexpected ')' :
136 fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_position));
139 // if an error has been set then give up now:
140 if(this->m_pdata->m_status)
142 // fill in our sub-expression count:
143 this->m_pdata->m_mark_count = 1 + m_mark_count;
144 this->finalize(p1, p2);
147 template <class charT, class traits>
148 void basic_regex_parser<charT, traits>::fail(regex_constants::error_type error_code, std::ptrdiff_t position)
150 if(0 == this->m_pdata->m_status) // update the error code if not already set
151 this->m_pdata->m_status = error_code;
152 m_position = m_end; // don't bother parsing anything else
153 // get the error message:
154 std::string message = this->m_pdata->m_ptraits->error_string(error_code);
155 // and raise the exception, this will do nothing if exceptions are disabled:
156 #ifndef BOOST_NO_EXCEPTIONS
157 if(0 == (this->flags() & regex_constants::no_except))
159 boost::regex_error e(message, error_code, position);
163 (void)position; // suppress warnings.
167 template <class charT, class traits>
168 bool basic_regex_parser<charT, traits>::parse_all()
171 while(result && (m_position != m_end))
173 result = (this->*m_parser_proc)();
179 #pragma warning(push)
180 #pragma warning(disable:4702)
182 template <class charT, class traits>
183 bool basic_regex_parser<charT, traits>::parse_basic()
185 switch(this->m_traits.syntax_type(*m_position))
187 case regex_constants::syntax_escape:
188 return parse_basic_escape();
189 case regex_constants::syntax_dot:
190 return parse_match_any();
191 case regex_constants::syntax_caret:
193 this->append_state(syntax_element_start_line);
195 case regex_constants::syntax_dollar:
197 this->append_state(syntax_element_end_line);
199 case regex_constants::syntax_star:
200 if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line))
201 return parse_literal();
205 return parse_repeat();
207 case regex_constants::syntax_plus:
208 if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex))
209 return parse_literal();
213 return parse_repeat(1);
215 case regex_constants::syntax_question:
216 if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex))
217 return parse_literal();
221 return parse_repeat(0, 1);
223 case regex_constants::syntax_open_set:
226 return parse_literal();
231 template <class charT, class traits>
232 bool basic_regex_parser<charT, traits>::parse_extended()
235 switch(this->m_traits.syntax_type(*m_position))
237 case regex_constants::syntax_open_mark:
238 return parse_open_paren();
239 case regex_constants::syntax_close_mark:
241 case regex_constants::syntax_escape:
242 return parse_extended_escape();
243 case regex_constants::syntax_dot:
244 return parse_match_any();
245 case regex_constants::syntax_caret:
248 (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_start : syntax_element_start_line));
250 case regex_constants::syntax_dollar:
253 (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_end : syntax_element_end_line));
255 case regex_constants::syntax_star:
256 if(m_position == this->m_base)
258 fail(regex_constants::error_badrepeat, 0);
262 return parse_repeat();
263 case regex_constants::syntax_question:
264 if(m_position == this->m_base)
266 fail(regex_constants::error_badrepeat, 0);
270 return parse_repeat(0,1);
271 case regex_constants::syntax_plus:
272 if(m_position == this->m_base)
274 fail(regex_constants::error_badrepeat, 0);
278 return parse_repeat(1);
279 case regex_constants::syntax_open_brace:
281 return parse_repeat_range(false);
282 case regex_constants::syntax_close_brace:
283 fail(regex_constants::error_brace, this->m_position - this->m_end);
285 case regex_constants::syntax_or:
287 case regex_constants::syntax_open_set:
289 case regex_constants::syntax_hash:
291 // If we have a mod_x flag set, then skip until
292 // we get to a newline character:
295 & (regbase::no_perl_ex|regbase::mod_x))
298 while((m_position != m_end) && !is_separator(*m_position++)){}
301 // Otherwise fall through:
303 result = parse_literal();
312 template <class charT, class traits>
313 bool basic_regex_parser<charT, traits>::parse_literal()
315 // append this as a literal provided it's not a space character
316 // or the perl option regbase::mod_x is not set:
319 & (regbase::main_option_type|regbase::mod_x|regbase::no_perl_ex))
321 || !this->m_traits.isctype(*m_position, this->m_mask_space))
322 this->append_literal(*m_position);
327 template <class charT, class traits>
328 bool basic_regex_parser<charT, traits>::parse_open_paren()
331 // skip the '(' and error check:
333 if(++m_position == m_end)
335 fail(regex_constants::error_paren, m_position - m_base);
339 // begin by checking for a perl-style (?...) extension:
342 ((this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) == 0)
343 || ((this->flags() & (regbase::main_option_type | regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex))
346 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question)
347 return parse_perl_extension();
350 // update our mark count, and append the required state:
353 if(0 == (this->flags() & regbase::nosubs))
354 markid = ++m_mark_count;
355 re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace)));
357 std::ptrdiff_t last_paren_start = this->getoffset(pb);
358 // back up insertion point for alternations, and set new point:
359 std::ptrdiff_t last_alt_point = m_alt_insert_point;
360 this->m_pdata->m_data.align();
361 m_alt_insert_point = this->m_pdata->m_data.size();
363 // back up the current flags in case we have a nested (?imsx) group:
365 regex_constants::syntax_option_type opts = this->flags();
366 bool old_case_change = m_has_case_change;
367 m_has_case_change = false; // no changes to this scope as yet...
369 // now recursively add more states, this will terminate when we get to a
374 // Unwind pushed alternatives:
376 if(0 == unwind_alts(last_paren_start))
381 if(m_has_case_change)
383 // the case has changed in one or more of the alternatives
384 // within the scoped (...) block: we have to add a state
385 // to reset the case sensitivity:
386 static_cast<re_case*>(
387 this->append_state(syntax_element_toggle_case, sizeof(re_case))
388 )->icase = opts & regbase::icase;
391 m_has_case_change = old_case_change;
393 // we either have a ')' or we have run out of characters prematurely:
395 if(m_position == m_end)
397 this->fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_end));
400 BOOST_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark);
403 // append closing parenthesis state:
405 pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace)));
407 this->m_paren_start = last_paren_start;
409 // restore the alternate insertion point:
411 this->m_alt_insert_point = last_alt_point;
413 // allow backrefs to this mark:
415 if((markid > 0) && (markid < sizeof(unsigned) * CHAR_BIT))
416 this->m_backrefs |= 1u << (markid - 1);
421 template <class charT, class traits>
422 bool basic_regex_parser<charT, traits>::parse_basic_escape()
426 switch(this->m_traits.escape_syntax_type(*m_position))
428 case regex_constants::syntax_open_mark:
429 return parse_open_paren();
430 case regex_constants::syntax_close_mark:
432 case regex_constants::syntax_plus:
433 if(this->flags() & regex_constants::bk_plus_qm)
436 return parse_repeat(1);
439 return parse_literal();
440 case regex_constants::syntax_question:
441 if(this->flags() & regex_constants::bk_plus_qm)
444 return parse_repeat(0, 1);
447 return parse_literal();
448 case regex_constants::syntax_open_brace:
449 if(this->flags() & regbase::no_intervals)
450 return parse_literal();
452 return parse_repeat_range(true);
453 case regex_constants::syntax_close_brace:
454 if(this->flags() & regbase::no_intervals)
455 return parse_literal();
456 fail(regex_constants::error_brace, this->m_position - this->m_base);
458 case regex_constants::syntax_or:
459 if(this->flags() & regbase::bk_vbar)
462 result = parse_literal();
464 case regex_constants::syntax_digit:
465 return parse_backref();
466 case regex_constants::escape_type_start_buffer:
467 if(this->flags() & regbase::emacs_ex)
470 this->append_state(syntax_element_buffer_start);
473 result = parse_literal();
475 case regex_constants::escape_type_end_buffer:
476 if(this->flags() & regbase::emacs_ex)
479 this->append_state(syntax_element_buffer_end);
482 result = parse_literal();
484 case regex_constants::escape_type_word_assert:
485 if(this->flags() & regbase::emacs_ex)
488 this->append_state(syntax_element_word_boundary);
491 result = parse_literal();
493 case regex_constants::escape_type_not_word_assert:
494 if(this->flags() & regbase::emacs_ex)
497 this->append_state(syntax_element_within_word);
500 result = parse_literal();
502 case regex_constants::escape_type_left_word:
503 if(this->flags() & regbase::emacs_ex)
506 this->append_state(syntax_element_word_start);
509 result = parse_literal();
511 case regex_constants::escape_type_right_word:
512 if(this->flags() & regbase::emacs_ex)
515 this->append_state(syntax_element_word_end);
518 result = parse_literal();
521 if(this->flags() & regbase::emacs_ex)
531 basic_char_set<charT, traits> char_set;
534 char_set.add_class(this->m_word_mask);
535 if(0 == this->append_set(char_set))
537 fail(regex_constants::error_ctype, m_position - m_base);
547 return add_emacs_code(negate);
550 // not supported yet:
551 fail(regex_constants::error_escape, m_position - m_base);
557 result = parse_literal();
563 template <class charT, class traits>
564 bool basic_regex_parser<charT, traits>::parse_extended_escape()
567 bool negate = false; // in case this is a character class escape: \w \d etc
568 switch(this->m_traits.escape_syntax_type(*m_position))
570 case regex_constants::escape_type_not_class:
573 case regex_constants::escape_type_class:
575 typedef typename traits::char_class_type mask_type;
576 mask_type m = this->m_traits.lookup_classname(m_position, m_position+1);
579 basic_char_set<charT, traits> char_set;
582 char_set.add_class(m);
583 if(0 == this->append_set(char_set))
585 fail(regex_constants::error_ctype, m_position - m_base);
592 // not a class, just a regular unknown escape:
594 this->append_literal(unescape_character());
597 case regex_constants::syntax_digit:
598 return parse_backref();
599 case regex_constants::escape_type_left_word:
601 this->append_state(syntax_element_word_start);
603 case regex_constants::escape_type_right_word:
605 this->append_state(syntax_element_word_end);
607 case regex_constants::escape_type_start_buffer:
609 this->append_state(syntax_element_buffer_start);
611 case regex_constants::escape_type_end_buffer:
613 this->append_state(syntax_element_buffer_end);
615 case regex_constants::escape_type_word_assert:
617 this->append_state(syntax_element_word_boundary);
619 case regex_constants::escape_type_not_word_assert:
621 this->append_state(syntax_element_within_word);
623 case regex_constants::escape_type_Z:
625 this->append_state(syntax_element_soft_buffer_end);
627 case regex_constants::escape_type_Q:
629 case regex_constants::escape_type_C:
630 return parse_match_any();
631 case regex_constants::escape_type_X:
633 this->append_state(syntax_element_combining);
635 case regex_constants::escape_type_G:
637 this->append_state(syntax_element_restart_continue);
639 case regex_constants::escape_type_not_property:
642 case regex_constants::escape_type_property:
646 if(m_position == m_end)
648 fail(regex_constants::error_escape, m_position - m_base);
651 // maybe have \p{ddd}
652 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace)
654 const charT* base = m_position;
655 // skip forward until we find enclosing brace:
656 while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
658 if(m_position == m_end)
660 fail(regex_constants::error_escape, m_position - m_base);
663 m = this->m_traits.lookup_classname(++base, m_position++);
667 m = this->m_traits.lookup_classname(m_position, m_position+1);
672 basic_char_set<charT, traits> char_set;
675 char_set.add_class(m);
676 if(0 == this->append_set(char_set))
678 fail(regex_constants::error_ctype, m_position - m_base);
683 fail(regex_constants::error_ctype, m_position - m_base);
686 this->append_literal(unescape_character());
692 template <class charT, class traits>
693 bool basic_regex_parser<charT, traits>::parse_match_any()
696 // we have a '.' that can match any character:
699 static_cast<re_dot*>(
700 this->append_state(syntax_element_wild, sizeof(re_dot))
701 )->mask = static_cast<unsigned char>(this->flags() & regbase::no_mod_s
702 ? re_detail::force_not_newline
703 : this->flags() & regbase::mod_s ?
704 re_detail::force_newline : re_detail::dont_care);
708 template <class charT, class traits>
709 bool basic_regex_parser<charT, traits>::parse_repeat(std::size_t low, std::size_t high)
712 std::size_t insert_point;
714 // when we get to here we may have a non-greedy ? mark still to come:
716 if((m_position != m_end)
718 (0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex)))
719 || ((regbase::basic_syntax_group|regbase::emacs_ex) == (this->flags() & (regbase::main_option_type | regbase::emacs_ex)))
723 // OK we have a perl regex, check for a '?':
724 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question)
730 if(0 == this->m_last_state)
732 fail(regex_constants::error_badrepeat, ::boost::re_detail::distance(m_base, m_position));
735 if(this->m_last_state->type == syntax_element_endmark)
737 // insert a repeat before the '(' matching the last ')':
738 insert_point = this->m_paren_start;
740 else if((this->m_last_state->type == syntax_element_literal) && (static_cast<re_literal*>(this->m_last_state)->length > 1))
742 // the last state was a literal with more than one character, split it in two:
743 re_literal* lit = static_cast<re_literal*>(this->m_last_state);
744 charT c = (static_cast<charT*>(static_cast<void*>(lit+1)))[lit->length - 1];
746 // now append new state:
747 lit = static_cast<re_literal*>(this->append_state(syntax_element_literal, sizeof(re_literal) + sizeof(charT)));
749 (static_cast<charT*>(static_cast<void*>(lit+1)))[0] = c;
750 insert_point = this->getoffset(this->m_last_state);
754 // repeat the last state whatever it was, need to add some error checking here:
755 switch(this->m_last_state->type)
757 case syntax_element_start_line:
758 case syntax_element_end_line:
759 case syntax_element_word_boundary:
760 case syntax_element_within_word:
761 case syntax_element_word_start:
762 case syntax_element_word_end:
763 case syntax_element_buffer_start:
764 case syntax_element_buffer_end:
765 case syntax_element_alt:
766 case syntax_element_soft_buffer_end:
767 case syntax_element_restart_continue:
768 case syntax_element_jump:
769 case syntax_element_startmark:
770 // can't legally repeat any of the above:
771 fail(regex_constants::error_badrepeat, m_position - m_base);
777 insert_point = this->getoffset(this->m_last_state);
780 // OK we now know what to repeat, so insert the repeat around it:
782 re_repeat* rep = static_cast<re_repeat*>(this->insert_state(insert_point, syntax_element_rep, re_repeater_size));
785 rep->greedy = greedy;
786 rep->leading = false;
787 // store our repeater position for later:
788 std::ptrdiff_t rep_off = this->getoffset(rep);
789 // and append a back jump to the repeat:
790 re_jump* jmp = static_cast<re_jump*>(this->append_state(syntax_element_jump, sizeof(re_jump)));
791 jmp->alt.i = rep_off - this->getoffset(jmp);
792 this->m_pdata->m_data.align();
793 // now fill in the alt jump for the repeat:
794 rep = static_cast<re_repeat*>(this->getaddress(rep_off));
795 rep->alt.i = this->m_pdata->m_data.size() - rep_off;
799 template <class charT, class traits>
800 bool basic_regex_parser<charT, traits>::parse_repeat_range(bool isbasic)
803 // parse a repeat-range:
805 std::size_t min, max;
808 while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
811 if(this->m_position == this->m_end)
813 fail(regex_constants::error_brace, this->m_position - this->m_base);
817 v = this->m_traits.toi(m_position, m_end, 10);
819 while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
823 fail(regex_constants::error_badbrace, this->m_position - this->m_base);
826 else if(this->m_position == this->m_end)
828 fail(regex_constants::error_brace, this->m_position - this->m_base);
832 // see if we have a comma:
833 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_comma)
835 // move on and error check:
838 while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
840 if(this->m_position == this->m_end)
842 fail(regex_constants::error_brace, this->m_position - this->m_base);
845 // get the value if any:
846 v = this->m_traits.toi(m_position, m_end, 10);
847 max = (v >= 0) ? v : (std::numeric_limits<std::size_t>::max)();
851 // no comma, max = min:
855 while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space))
857 // OK now check trailing }:
858 if(this->m_position == this->m_end)
860 fail(regex_constants::error_brace, this->m_position - this->m_base);
865 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_escape)
868 if(this->m_position == this->m_end)
870 fail(regex_constants::error_brace, this->m_position - this->m_base);
876 fail(regex_constants::error_badbrace, this->m_position - this->m_base);
880 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_brace)
884 fail(regex_constants::error_badbrace, this->m_position - this->m_base);
888 // finally go and add the repeat, unless error:
892 fail(regex_constants::error_badbrace, this->m_position - this->m_base);
895 return parse_repeat(min, max);
898 template <class charT, class traits>
899 bool basic_regex_parser<charT, traits>::parse_alt()
902 // error check: if there have been no previous states,
903 // or if the last state was a '(' then error:
905 if((this->m_last_state == 0) || (this->m_last_state->type == syntax_element_startmark))
907 fail(regex_constants::error_empty, this->m_position - this->m_base);
912 // we need to append a trailing jump:
914 re_syntax_base* pj = this->append_state(re_detail::syntax_element_jump, sizeof(re_jump));
915 std::ptrdiff_t jump_offset = this->getoffset(pj);
917 // now insert the alternative:
919 re_alt* palt = static_cast<re_alt*>(this->insert_state(this->m_alt_insert_point, syntax_element_alt, re_alt_size));
920 jump_offset += re_alt_size;
921 this->m_pdata->m_data.align();
922 palt->alt.i = this->m_pdata->m_data.size() - this->getoffset(palt);
924 // update m_alt_insert_point so that the next alternate gets
925 // inserted at the start of the second of the two we've just created:
927 this->m_alt_insert_point = this->m_pdata->m_data.size();
929 // the start of this alternative must have a case changes state
930 // if the current block has messed around with case changes:
932 if(m_has_case_change)
934 static_cast<re_case*>(
935 this->append_state(syntax_element_toggle_case, sizeof(re_case))
936 )->icase = this->m_icase;
939 // push the alternative onto our stack, a recursive
940 // implementation here is easier to understand (and faster
941 // as it happens), but causes all kinds of stack overflow problems
942 // on programs with small stacks (COM+).
944 m_alt_jumps.push_back(jump_offset);
948 template <class charT, class traits>
949 bool basic_regex_parser<charT, traits>::parse_set()
952 if(m_position == m_end)
954 fail(regex_constants::error_brack, m_position - m_base);
957 basic_char_set<charT, traits> char_set;
959 const charT* base = m_position; // where the '[' was
960 const charT* item_base = m_position; // where the '[' or '^' was
962 while(m_position != m_end)
964 switch(this->m_traits.syntax_type(*m_position))
966 case regex_constants::syntax_caret:
967 if(m_position == base)
971 item_base = m_position;
974 parse_set_literal(char_set);
976 case regex_constants::syntax_close_set:
977 if(m_position == item_base)
979 parse_set_literal(char_set);
985 if(0 == this->append_set(char_set))
987 fail(regex_constants::error_range, m_position - m_base);
992 case regex_constants::syntax_open_set:
993 if(parse_inner_set(char_set))
996 case regex_constants::syntax_escape:
999 // look ahead and see if this is a character class shortcut
1003 if(this->m_traits.escape_syntax_type(*m_position)
1004 == regex_constants::escape_type_class)
1006 char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1);
1009 char_set.add_class(m);
1014 else if(this->m_traits.escape_syntax_type(*m_position)
1015 == regex_constants::escape_type_not_class)
1017 // negated character class:
1018 char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1);
1021 char_set.add_negated_class(m);
1026 // not a character class, just a regular escape:
1028 parse_set_literal(char_set);
1032 parse_set_literal(char_set);
1036 return m_position != m_end;
1039 template <class charT, class traits>
1040 bool basic_regex_parser<charT, traits>::parse_inner_set(basic_char_set<charT, traits>& char_set)
1043 // we have either a character class [:name:]
1044 // a collating element [.name.]
1045 // or an equivalence class [=name=]
1047 if(m_end == ++m_position)
1049 fail(regex_constants::error_brack, m_position - m_base);
1052 switch(this->m_traits.syntax_type(*m_position))
1054 case regex_constants::syntax_dot:
1056 // a collating element is treated as a literal:
1059 parse_set_literal(char_set);
1061 case regex_constants::syntax_colon:
1063 // check that character classes are actually enabled:
1064 if((this->flags() & (regbase::main_option_type | regbase::no_char_classes))
1065 == (regbase::basic_syntax_group | regbase::no_char_classes))
1068 parse_set_literal(char_set);
1072 if(m_end == ++m_position)
1074 fail(regex_constants::error_brack, m_position - m_base);
1077 const charT* name_first = m_position;
1078 // skip at least one character, then find the matching ':]'
1079 if(m_end == ++m_position)
1081 fail(regex_constants::error_brack, m_position - m_base);
1084 while((m_position != m_end)
1085 && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_colon))
1087 const charT* name_last = m_position;
1088 if(m_end == m_position)
1090 fail(regex_constants::error_brack, m_position - m_base);
1093 if((m_end == ++m_position)
1094 || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
1096 fail(regex_constants::error_brack, m_position - m_base);
1100 // check for negated class:
1102 bool negated = false;
1103 if(this->m_traits.syntax_type(*name_first) == regex_constants::syntax_caret)
1108 typedef typename traits::char_class_type mask_type;
1109 mask_type m = this->m_traits.lookup_classname(name_first, name_last);
1112 if(char_set.empty() && (name_last - name_first == 1))
1114 // maybe a special case:
1116 if( (m_position != m_end)
1117 && (this->m_traits.syntax_type(*m_position)
1118 == regex_constants::syntax_close_set))
1120 if(this->m_traits.escape_syntax_type(*name_first)
1121 == regex_constants::escape_type_left_word)
1124 this->append_state(syntax_element_word_start);
1127 if(this->m_traits.escape_syntax_type(*name_first)
1128 == regex_constants::escape_type_right_word)
1131 this->append_state(syntax_element_word_end);
1136 fail(regex_constants::error_ctype, name_first - m_base);
1139 if(negated == false)
1140 char_set.add_class(m);
1142 char_set.add_negated_class(m);
1146 case regex_constants::syntax_equal:
1149 if(m_end == ++m_position)
1151 fail(regex_constants::error_brack, m_position - m_base);
1154 const charT* name_first = m_position;
1155 // skip at least one character, then find the matching '=]'
1156 if(m_end == ++m_position)
1158 fail(regex_constants::error_brack, m_position - m_base);
1161 while((m_position != m_end)
1162 && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal))
1164 const charT* name_last = m_position;
1165 if(m_end == m_position)
1167 fail(regex_constants::error_brack, m_position - m_base);
1170 if((m_end == ++m_position)
1171 || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
1173 fail(regex_constants::error_brack, m_position - m_base);
1176 string_type m = this->m_traits.lookup_collatename(name_first, name_last);
1177 if((0 == m.size()) || (m.size() > 2))
1179 fail(regex_constants::error_collate, name_first - m_base);
1188 char_set.add_equivalent(d);
1194 parse_set_literal(char_set);
1200 template <class charT, class traits>
1201 void basic_regex_parser<charT, traits>::parse_set_literal(basic_char_set<charT, traits>& char_set)
1203 digraph<charT> start_range(get_next_set_literal(char_set));
1204 if(m_end == m_position)
1206 fail(regex_constants::error_brack, m_position - m_base);
1209 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash)
1212 if(m_end == ++m_position)
1214 fail(regex_constants::error_brack, m_position - m_base);
1217 if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)
1219 digraph<charT> end_range = get_next_set_literal(char_set);
1220 char_set.add_range(start_range, end_range);
1221 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash)
1223 if(m_end == ++m_position)
1225 fail(regex_constants::error_brack, m_position - m_base);
1228 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_set)
1234 fail(regex_constants::error_range, m_position - m_base);
1241 char_set.add_single(start_range);
1244 template <class charT, class traits>
1245 digraph<charT> basic_regex_parser<charT, traits>::get_next_set_literal(basic_char_set<charT, traits>& char_set)
1247 digraph<charT> result;
1248 switch(this->m_traits.syntax_type(*m_position))
1250 case regex_constants::syntax_dash:
1251 if(!char_set.empty())
1253 // see if we are at the end of the set:
1254 if((++m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
1256 fail(regex_constants::error_range, m_position - m_base);
1261 result.first = *m_position++;
1263 case regex_constants::syntax_escape:
1264 // check to see if escapes are supported first:
1265 if(this->flags() & regex_constants::no_escape_in_lists)
1267 result = *m_position++;
1271 result = unescape_character();
1273 case regex_constants::syntax_open_set:
1275 if(m_end == ++m_position)
1277 fail(regex_constants::error_collate, m_position - m_base);
1280 if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot)
1283 result.first = *m_position;
1287 if(m_end == ++m_position)
1289 fail(regex_constants::error_collate, m_position - m_base);
1292 const charT* name_first = m_position;
1293 // skip at least one character, then find the matching ':]'
1294 if(m_end == ++m_position)
1296 fail(regex_constants::error_collate, name_first - m_base);
1299 while((m_position != m_end)
1300 && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot))
1302 const charT* name_last = m_position;
1303 if(m_end == m_position)
1305 fail(regex_constants::error_collate, name_first - m_base);
1308 if((m_end == ++m_position)
1309 || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set))
1311 fail(regex_constants::error_collate, name_first - m_base);
1315 string_type s = this->m_traits.lookup_collatename(name_first, name_last);
1316 if(s.empty() || (s.size() > 2))
1318 fail(regex_constants::error_collate, name_first - m_base);
1321 result.first = s[0];
1323 result.second = s[1];
1329 result = *m_position++;
1335 // does a value fit in the specified charT type?
1337 template <class charT>
1338 bool valid_value(charT, int v, const mpl::true_&)
1340 return (v >> (sizeof(charT) * CHAR_BIT)) == 0;
1342 template <class charT>
1343 bool valid_value(charT, int, const mpl::false_&)
1345 return true; // v will alsways fit in a charT
1347 template <class charT>
1348 bool valid_value(charT c, int v)
1350 return valid_value(c, v, mpl::bool_<(sizeof(charT) < sizeof(int))>());
1353 template <class charT, class traits>
1354 charT basic_regex_parser<charT, traits>::unescape_character()
1357 #pragma warning(push)
1358 #pragma warning(disable:4127)
1361 if(m_position == m_end)
1363 fail(regex_constants::error_escape, m_position - m_base);
1366 switch(this->m_traits.escape_syntax_type(*m_position))
1368 case regex_constants::escape_type_control_a:
1369 result = charT('\a');
1371 case regex_constants::escape_type_e:
1374 case regex_constants::escape_type_control_f:
1375 result = charT('\f');
1377 case regex_constants::escape_type_control_n:
1378 result = charT('\n');
1380 case regex_constants::escape_type_control_r:
1381 result = charT('\r');
1383 case regex_constants::escape_type_control_t:
1384 result = charT('\t');
1386 case regex_constants::escape_type_control_v:
1387 result = charT('\v');
1389 case regex_constants::escape_type_word_assert:
1390 result = charT('\b');
1392 case regex_constants::escape_type_ascii_control:
1394 if(m_position == m_end)
1396 fail(regex_constants::error_escape, m_position - m_base);
1400 if((*m_position < charT('@'))
1401 || (*m_position > charT(125)) )
1403 fail(regex_constants::error_escape, m_position - m_base);
1407 result = static_cast<charT>(*m_position % 32);
1409 case regex_constants::escape_type_hex:
1411 if(m_position == m_end)
1413 fail(regex_constants::error_escape, m_position - m_base);
1416 // maybe have \x{ddd}
1417 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace)
1420 if(m_position == m_end)
1422 fail(regex_constants::error_escape, m_position - m_base);
1425 int i = this->m_traits.toi(m_position, m_end, 16);
1426 if((m_position == m_end)
1428 || ((std::numeric_limits<charT>::is_specialized) && (charT(i) > (std::numeric_limits<charT>::max)()))
1429 || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
1431 fail(regex_constants::error_badbrace, m_position - m_base);
1439 std::ptrdiff_t len = (std::min)(static_cast<std::ptrdiff_t>(2), m_end - m_position);
1440 int i = this->m_traits.toi(m_position, m_position + len, 16);
1442 || !valid_value(charT(0), i))
1444 fail(regex_constants::error_escape, m_position - m_base);
1450 case regex_constants::syntax_digit:
1452 // an octal escape sequence, the first character must be a zero
1453 // followed by up to 3 octal digits:
1454 std::ptrdiff_t len = (std::min)(::boost::re_detail::distance(m_position, m_end), static_cast<std::ptrdiff_t>(4));
1455 const charT* bp = m_position;
1456 int val = this->m_traits.toi(bp, bp + 1, 8);
1459 // Oops not an octal escape after all:
1460 fail(regex_constants::error_escape, m_position - m_base);
1463 val = this->m_traits.toi(m_position, m_position + len, 8);
1466 fail(regex_constants::error_escape, m_position - m_base);
1469 return static_cast<charT>(val);
1471 case regex_constants::escape_type_named_char:
1474 if(m_position == m_end)
1476 fail(regex_constants::error_escape, m_position - m_base);
1479 // maybe have \N{name}
1480 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace)
1482 const charT* base = m_position;
1483 // skip forward until we find enclosing brace:
1484 while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace))
1486 if(m_position == m_end)
1488 fail(regex_constants::error_escape, m_position - m_base);
1491 string_type s = this->m_traits.lookup_collatename(++base, m_position++);
1494 fail(regex_constants::error_collate, m_position - m_base);
1502 // fall through is a failure:
1503 fail(regex_constants::error_escape, m_position - m_base);
1507 result = *m_position;
1513 #pragma warning(pop)
1517 template <class charT, class traits>
1518 bool basic_regex_parser<charT, traits>::parse_backref()
1520 BOOST_ASSERT(m_position != m_end);
1521 const charT* pc = m_position;
1522 int i = this->m_traits.toi(pc, pc + 1, 10);
1523 if((i == 0) || (((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) && (this->flags() & regbase::no_bk_refs)))
1525 // not a backref at all but an octal escape sequence:
1526 charT c = unescape_character();
1527 this->append_literal(c);
1529 else if((i > 0) && (this->m_backrefs & (1u << (i-1))))
1532 re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_backref, sizeof(re_brace)));
1537 fail(regex_constants::error_backref, m_position - m_end);
1543 template <class charT, class traits>
1544 bool basic_regex_parser<charT, traits>::parse_QE()
1547 #pragma warning(push)
1548 #pragma warning(disable:4127)
1551 // parse a \Q...\E sequence:
1553 ++m_position; // skip the Q
1554 const charT* start = m_position;
1558 while((m_position != m_end)
1559 && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape))
1561 if(m_position == m_end)
1563 // a \Q...\E sequence may terminate with the end of the expression:
1567 if(++m_position == m_end) // skip the escape
1569 fail(regex_constants::error_escape, m_position - m_base);
1572 // check to see if it's a \E:
1573 if(this->m_traits.escape_syntax_type(*m_position) == regex_constants::escape_type_E)
1576 end = m_position - 2;
1579 // otherwise go round again:
1582 // now add all the character between the two escapes as literals:
1586 this->append_literal(*start);
1591 #pragma warning(pop)
1595 template <class charT, class traits>
1596 bool basic_regex_parser<charT, traits>::parse_perl_extension()
1598 if(++m_position == m_end)
1600 fail(regex_constants::error_badrepeat, m_position - m_base);
1604 // treat comments as a special case, as these
1605 // are the only ones that don't start with a leading
1608 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_hash)
1610 while((m_position != m_end)
1611 && (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark))
1616 // backup some state, and prepare the way:
1619 std::ptrdiff_t jump_offset = 0;
1620 re_brace* pb = static_cast<re_brace*>(this->append_state(syntax_element_startmark, sizeof(re_brace)));
1621 std::ptrdiff_t last_paren_start = this->getoffset(pb);
1622 // back up insertion point for alternations, and set new point:
1623 std::ptrdiff_t last_alt_point = m_alt_insert_point;
1624 this->m_pdata->m_data.align();
1625 m_alt_insert_point = this->m_pdata->m_data.size();
1626 std::ptrdiff_t expected_alt_point = m_alt_insert_point;
1627 bool restore_flags = true;
1628 regex_constants::syntax_option_type old_flags = this->flags();
1629 bool old_case_change = m_has_case_change;
1630 m_has_case_change = false;
1632 // select the actual extension used:
1634 switch(this->m_traits.syntax_type(*m_position))
1636 case regex_constants::syntax_colon:
1638 // a non-capturing mark:
1640 pb->index = markid = 0;
1643 case regex_constants::syntax_equal:
1644 pb->index = markid = -1;
1646 jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump)));
1647 this->m_pdata->m_data.align();
1648 m_alt_insert_point = this->m_pdata->m_data.size();
1650 case regex_constants::syntax_not:
1651 pb->index = markid = -2;
1653 jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump)));
1654 this->m_pdata->m_data.align();
1655 m_alt_insert_point = this->m_pdata->m_data.size();
1657 case regex_constants::escape_type_left_word:
1659 // a lookbehind assertion:
1660 if(++m_position == m_end)
1662 fail(regex_constants::error_badrepeat, m_position - m_base);
1665 regex_constants::syntax_type t = this->m_traits.syntax_type(*m_position);
1666 if(t == regex_constants::syntax_not)
1667 pb->index = markid = -2;
1668 else if(t == regex_constants::syntax_equal)
1669 pb->index = markid = -1;
1672 fail(regex_constants::error_badrepeat, m_position - m_base);
1676 jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump)));
1677 this->append_state(syntax_element_backstep, sizeof(re_brace));
1678 this->m_pdata->m_data.align();
1679 m_alt_insert_point = this->m_pdata->m_data.size();
1682 case regex_constants::escape_type_right_word:
1684 // an independent sub-expression:
1686 pb->index = markid = -3;
1688 jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump)));
1689 this->m_pdata->m_data.align();
1690 m_alt_insert_point = this->m_pdata->m_data.size();
1692 case regex_constants::syntax_open_mark:
1694 // a conditional expression:
1695 pb->index = markid = -4;
1696 if(++m_position == m_end)
1698 fail(regex_constants::error_badrepeat, m_position - m_base);
1701 int v = this->m_traits.toi(m_position, m_end, 10);
1704 re_brace* br = static_cast<re_brace*>(this->append_state(syntax_element_assert_backref, sizeof(re_brace)));
1706 if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)
1708 fail(regex_constants::error_badrepeat, m_position - m_base);
1711 if(++m_position == m_end)
1713 fail(regex_constants::error_badrepeat, m_position - m_base);
1719 // verify that we have a lookahead or lookbehind assert:
1720 if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_question)
1722 fail(regex_constants::error_badrepeat, m_position - m_base);
1725 if(++m_position == m_end)
1727 fail(regex_constants::error_badrepeat, m_position - m_base);
1730 if(this->m_traits.syntax_type(*m_position) == regex_constants::escape_type_left_word)
1732 if(++m_position == m_end)
1734 fail(regex_constants::error_badrepeat, m_position - m_base);
1737 if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)
1738 && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not))
1740 fail(regex_constants::error_badrepeat, m_position - m_base);
1747 if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)
1748 && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not))
1750 fail(regex_constants::error_badrepeat, m_position - m_base);
1758 case regex_constants::syntax_close_mark:
1759 fail(regex_constants::error_badrepeat, m_position - m_base);
1763 // lets assume that we have a (?imsx) group and try and parse it:
1765 regex_constants::syntax_option_type opts = parse_options();
1766 if(m_position == m_end)
1768 // make a note of whether we have a case change:
1769 m_has_case_change = ((opts & regbase::icase) != (this->flags() & regbase::icase));
1770 pb->index = markid = 0;
1771 if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark)
1773 // update flags and carry on as normal:
1775 restore_flags = false;
1776 old_case_change |= m_has_case_change; // defer end of scope by one ')'
1778 else if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_colon)
1780 // update flags and carry on until the matching ')' is found:
1786 fail(regex_constants::error_badrepeat, m_position - m_base);
1790 // finally append a case change state if we need it:
1791 if(m_has_case_change)
1793 static_cast<re_case*>(
1794 this->append_state(syntax_element_toggle_case, sizeof(re_case))
1795 )->icase = opts & regbase::icase;
1800 // now recursively add more states, this will terminate when we get to a
1805 // Unwind alternatives:
1807 if(0 == unwind_alts(last_paren_start))
1810 // we either have a ')' or we have run out of characters prematurely:
1812 if(m_position == m_end)
1814 this->fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_end));
1817 BOOST_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark);
1820 // restore the flags:
1824 // append a case change state if we need it:
1825 if(m_has_case_change)
1827 static_cast<re_case*>(
1828 this->append_state(syntax_element_toggle_case, sizeof(re_case))
1829 )->icase = old_flags & regbase::icase;
1831 this->flags(old_flags);
1834 // set up the jump pointer if we have one:
1838 this->m_pdata->m_data.align();
1839 re_jump* jmp = static_cast<re_jump*>(this->getaddress(jump_offset));
1840 jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp);
1841 if(this->m_last_state == jmp)
1843 // Oops... we didn't have anything inside the assertion:
1844 fail(regex_constants::error_empty, m_position - m_base);
1849 // verify that if this is conditional expression, that we do have
1850 // an alternative, if not add one:
1854 re_syntax_base* b = this->getaddress(expected_alt_point);
1855 if(b->type != syntax_element_alt)
1857 re_alt* alt = static_cast<re_alt*>(this->insert_state(expected_alt_point, syntax_element_alt, sizeof(re_alt)));
1858 alt->alt.i = this->m_pdata->m_data.size() - this->getoffset(alt);
1860 else if(this->getaddress(static_cast<re_alt*>(b)->alt.i, b)->type == syntax_element_alt)
1862 fail(regex_constants::error_bad_pattern, m_position - m_base);
1867 // append closing parenthesis state:
1869 pb = static_cast<re_brace*>(this->append_state(syntax_element_endmark, sizeof(re_brace)));
1871 this->m_paren_start = last_paren_start;
1873 // restore the alternate insertion point:
1875 this->m_alt_insert_point = last_alt_point;
1877 // and the case change data:
1879 m_has_case_change = old_case_change;
1883 template <class charT, class traits>
1884 bool basic_regex_parser<charT, traits>::add_emacs_code(bool negate)
1887 // parses an emacs style \sx or \Sx construct.
1889 if(++m_position == m_end)
1891 fail(regex_constants::error_escape, m_position - m_base);
1894 basic_char_set<charT, traits> char_set;
1898 static const charT s_punct[5] = { 'p', 'u', 'n', 'c', 't', };
1904 char_set.add_class(this->m_mask_space);
1907 char_set.add_class(this->m_word_mask);
1910 char_set.add_single(digraph<charT>(charT('$')));
1911 char_set.add_single(digraph<charT>(charT('&')));
1912 char_set.add_single(digraph<charT>(charT('*')));
1913 char_set.add_single(digraph<charT>(charT('+')));
1914 char_set.add_single(digraph<charT>(charT('-')));
1915 char_set.add_single(digraph<charT>(charT('_')));
1916 char_set.add_single(digraph<charT>(charT('<')));
1917 char_set.add_single(digraph<charT>(charT('>')));
1920 char_set.add_class(this->m_traits.lookup_classname(s_punct, s_punct+5));
1923 char_set.add_single(digraph<charT>(charT('(')));
1924 char_set.add_single(digraph<charT>(charT('[')));
1925 char_set.add_single(digraph<charT>(charT('{')));
1928 char_set.add_single(digraph<charT>(charT(')')));
1929 char_set.add_single(digraph<charT>(charT(']')));
1930 char_set.add_single(digraph<charT>(charT('}')));
1933 char_set.add_single(digraph<charT>(charT('"')));
1934 char_set.add_single(digraph<charT>(charT('\'')));
1935 char_set.add_single(digraph<charT>(charT('`')));
1938 char_set.add_single(digraph<charT>(charT('\'')));
1939 char_set.add_single(digraph<charT>(charT(',')));
1940 char_set.add_single(digraph<charT>(charT('#')));
1943 char_set.add_single(digraph<charT>(charT(';')));
1946 char_set.add_single(digraph<charT>(charT('\n')));
1947 char_set.add_single(digraph<charT>(charT('\f')));
1950 fail(regex_constants::error_ctype, m_position - m_base);
1953 if(0 == this->append_set(char_set))
1955 fail(regex_constants::error_ctype, m_position - m_base);
1962 template <class charT, class traits>
1963 regex_constants::syntax_option_type basic_regex_parser<charT, traits>::parse_options()
1965 // we have a (?imsx-imsx) group, convert it into a set of flags:
1966 regex_constants::syntax_option_type f = this->flags();
1967 bool breakout = false;
1973 f |= regex_constants::mod_s;
1974 f &= ~regex_constants::no_mod_s;
1977 f &= ~regex_constants::no_mod_m;
1980 f |= regex_constants::icase;
1983 f |= regex_constants::mod_x;
1989 if(++m_position == m_end)
1991 fail(regex_constants::error_paren, m_position - m_base);
1997 if(*m_position == static_cast<charT>('-'))
1999 if(++m_position == m_end)
2001 fail(regex_constants::error_paren, m_position - m_base);
2009 f &= ~regex_constants::mod_s;
2010 f |= regex_constants::no_mod_s;
2013 f |= regex_constants::no_mod_m;
2016 f &= ~regex_constants::icase;
2019 f &= ~regex_constants::mod_x;
2025 if(++m_position == m_end)
2027 fail(regex_constants::error_paren, m_position - m_base);
2036 template <class charT, class traits>
2037 bool basic_regex_parser<charT, traits>::unwind_alts(std::ptrdiff_t last_paren_start)
2040 // If we didn't actually add any states after the last
2041 // alternative then that's an error:
2043 if((this->m_alt_insert_point == static_cast<std::ptrdiff_t>(this->m_pdata->m_data.size()))
2044 && m_alt_jumps.size() && (m_alt_jumps.back() > last_paren_start))
2046 fail(regex_constants::error_empty, this->m_position - this->m_base);
2050 // Fix up our alternatives:
2052 while(m_alt_jumps.size() && (m_alt_jumps.back() > last_paren_start))
2055 // fix up the jump to point to the end of the states
2056 // that we've just added:
2058 std::ptrdiff_t jump_offset = m_alt_jumps.back();
2059 m_alt_jumps.pop_back();
2060 this->m_pdata->m_data.align();
2061 re_jump* jmp = static_cast<re_jump*>(this->getaddress(jump_offset));
2062 BOOST_ASSERT(jmp->type == syntax_element_jump);
2063 jmp->alt.i = this->m_pdata->m_data.size() - jump_offset;
2069 #pragma warning(pop)
2072 } // namespace re_detail
2073 } // namespace boost
2075 #ifdef BOOST_HAS_ABI_HEADERS
2076 # include BOOST_ABI_SUFFIX