1 // class template regex -*- C++ -*-
3 // Copyright (C) 2010 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
26 * @file bits/regex_compiler.h
27 * This is an internal header file, included by other library headers.
28 * Do not attempt to use it directly. @headername{regex}
31 _GLIBCXX_BEGIN_NAMESPACE(std
)
37 // FIXME: replace these constanst with constexpr
38 typedef unsigned int _StateT
;
40 static const _StateT _S_state_at_start
= 1 << 0;
41 static const _StateT _S_state_in_brace
= 1 << 2;
42 static const _StateT _S_state_in_bracket
= 1 << 3;
46 // @brief Scans an input range for regex tokens.
48 // The %_Scanner class interprets the regular expression pattern in the input
49 // range passed to its constructor as a sequence of parse tokens passed to
50 // the regular expression compiler. The sequence of tokens provided depends
51 // on the flag settings passed to the constructor: different regular
52 // expression gramars will interpret the same input pattern in syntactically
55 template<typename _InputIterator
>
56 class _Scanner
: public _Scanner_base
59 typedef _InputIterator _IteratorT
;
60 typedef typename
std::iterator_traits
<_IteratorT
>::value_type _CharT
;
61 typedef std::basic_string
<_CharT
> _StringT
;
62 typedef regex_constants::syntax_option_type _FlagT
;
63 typedef const std::ctype
<_CharT
> _CtypeT
;
65 // Token types returned from the scanner.
70 _S_token_bracket_begin
,
72 _S_token_inverse_class
,
73 _S_token_char_class_name
,
76 _S_token_collelem_multi
,
77 _S_token_collelem_single
,
83 _S_token_equiv_class_name
,
84 _S_token_interval_begin
,
85 _S_token_interval_end
,
92 _S_token_subexpr_begin
,
100 _Scanner(_IteratorT __begin
, _IteratorT __end
, _FlagT __flags
,
102 : _M_current(__begin
) , _M_end(__end
) , _M_flags(__flags
),
103 _M_ctype(std::use_facet
<_CtypeT
>(__loc
)), _M_state(_S_state_at_start
)
111 { return _M_curToken
; }
115 { return _M_curValue
; }
117 #ifdef _GLIBCXX_DEBUG
119 _M_print(std::ostream
&);
130 _M_scan_in_bracket();
142 _IteratorT _M_current
;
147 _StringT _M_curValue
;
151 template<typename _InputIterator
>
153 _Scanner
<_InputIterator
>::
156 if (_M_current
== _M_end
)
158 _M_curToken
= _S_token_eof
;
162 _CharT __c
= *_M_current
;
163 if (_M_state
& _S_state_in_bracket
)
165 _M_scan_in_bracket();
168 if (_M_state
& _S_state_in_brace
)
173 else if (_M_state
& _S_state_at_start
&& __c
== _M_ctype
.widen('^'))
175 _M_curToken
= _S_token_line_begin
;
179 else if (__c
== _M_ctype
.widen('$'))
181 _M_curToken
= _S_token_line_end
;
185 else if (__c
== _M_ctype
.widen('.'))
187 _M_curToken
= _S_token_anychar
;
191 else if (__c
== _M_ctype
.widen('*'))
193 _M_curToken
= _S_token_closure0
;
197 else if (__c
== _M_ctype
.widen('+'))
199 _M_curToken
= _S_token_closure1
;
203 else if (__c
== _M_ctype
.widen('|'))
205 _M_curToken
= _S_token_or
;
209 else if (__c
== _M_ctype
.widen('['))
211 _M_curToken
= _S_token_bracket_begin
;
212 _M_state
|= (_S_state_in_bracket
| _S_state_at_start
);
216 else if (__c
== _M_ctype
.widen('\\'))
221 else if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
223 if (__c
== _M_ctype
.widen('('))
225 _M_curToken
= _S_token_subexpr_begin
;
229 else if (__c
== _M_ctype
.widen(')'))
231 _M_curToken
= _S_token_subexpr_end
;
235 else if (__c
== _M_ctype
.widen('{'))
237 _M_curToken
= _S_token_interval_begin
;
238 _M_state
|= _S_state_in_brace
;
244 _M_curToken
= _S_token_ord_char
;
245 _M_curValue
.assign(1, __c
);
250 template<typename _InputIterator
>
252 _Scanner
<_InputIterator
>::
255 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
257 _M_curToken
= _S_token_dup_count
;
258 _M_curValue
.assign(1, *_M_current
);
260 while (_M_current
!= _M_end
261 && _M_ctype
.is(_CtypeT::digit
, *_M_current
))
263 _M_curValue
+= *_M_current
;
268 else if (*_M_current
== _M_ctype
.widen(','))
270 _M_curToken
= _S_token_comma
;
274 if (_M_flags
& (regex_constants::basic
| regex_constants::grep
))
276 if (*_M_current
== _M_ctype
.widen('\\'))
281 if (*_M_current
== _M_ctype
.widen('}'))
283 _M_curToken
= _S_token_interval_end
;
284 _M_state
&= ~_S_state_in_brace
;
291 template<typename _InputIterator
>
293 _Scanner
<_InputIterator
>::
296 if (_M_state
& _S_state_at_start
&& *_M_current
== _M_ctype
.widen('^'))
298 _M_curToken
= _S_token_inverse_class
;
299 _M_state
&= ~_S_state_at_start
;
303 else if (*_M_current
== _M_ctype
.widen('['))
306 if (_M_current
== _M_end
)
308 _M_curToken
= _S_token_eof
;
312 if (*_M_current
== _M_ctype
.widen('.'))
314 _M_curToken
= _S_token_collsymbol
;
318 else if (*_M_current
== _M_ctype
.widen(':'))
320 _M_curToken
= _S_token_char_class_name
;
324 else if (*_M_current
== _M_ctype
.widen('='))
326 _M_curToken
= _S_token_equiv_class_name
;
331 else if (*_M_current
== _M_ctype
.widen('-'))
333 _M_curToken
= _S_token_dash
;
337 else if (*_M_current
== _M_ctype
.widen(']'))
339 if (!(_M_flags
& regex_constants::ECMAScript
)
340 || !(_M_state
& _S_state_at_start
))
342 // special case: only if _not_ chr first after
343 // '[' or '[^' and if not ECMAscript
344 _M_curToken
= _S_token_bracket_end
;
349 _M_curToken
= _S_token_collelem_single
;
350 _M_curValue
.assign(1, *_M_current
);
354 template<typename _InputIterator
>
356 _Scanner
<_InputIterator
>::
360 if (_M_current
== _M_end
)
362 _M_curToken
= _S_token_eof
;
365 _CharT __c
= *_M_current
;
368 if (__c
== _M_ctype
.widen('('))
370 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
372 _M_curToken
= _S_token_ord_char
;
373 _M_curValue
.assign(1, __c
);
376 _M_curToken
= _S_token_subexpr_begin
;
378 else if (__c
== _M_ctype
.widen(')'))
380 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
382 _M_curToken
= _S_token_ord_char
;
383 _M_curValue
.assign(1, __c
);
386 _M_curToken
= _S_token_subexpr_end
;
388 else if (__c
== _M_ctype
.widen('{'))
390 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
392 _M_curToken
= _S_token_ord_char
;
393 _M_curValue
.assign(1, __c
);
397 _M_curToken
= _S_token_interval_begin
;
398 _M_state
|= _S_state_in_brace
;
401 else if (__c
== _M_ctype
.widen('}'))
403 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
405 _M_curToken
= _S_token_ord_char
;
406 _M_curValue
.assign(1, __c
);
410 if (!(_M_state
&& _S_state_in_brace
))
411 __throw_regex_error(regex_constants::error_badbrace
);
412 _M_state
&= ~_S_state_in_brace
;
413 _M_curToken
= _S_token_interval_end
;
416 else if (__c
== _M_ctype
.widen('x'))
419 if (_M_current
== _M_end
)
421 _M_curToken
= _S_token_eof
;
424 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
426 _M_curValue
.assign(1, *_M_current
);
428 if (_M_current
== _M_end
)
430 _M_curToken
= _S_token_eof
;
433 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
435 _M_curValue
+= *_M_current
;
441 else if (__c
== _M_ctype
.widen('^')
442 || __c
== _M_ctype
.widen('.')
443 || __c
== _M_ctype
.widen('*')
444 || __c
== _M_ctype
.widen('$')
445 || __c
== _M_ctype
.widen('\\'))
447 _M_curToken
= _S_token_ord_char
;
448 _M_curValue
.assign(1, __c
);
450 else if (_M_ctype
.is(_CtypeT::digit
, __c
))
452 _M_curToken
= _S_token_backref
;
453 _M_curValue
.assign(1, __c
);
456 __throw_regex_error(regex_constants::error_escape
);
460 // Eats a character class or throwns an exception.
461 // current point to ':' delimiter on entry, char after ']' on return
462 template<typename _InputIterator
>
464 _Scanner
<_InputIterator
>::
467 ++_M_current
; // skip ':'
468 if (_M_current
== _M_end
)
469 __throw_regex_error(regex_constants::error_ctype
);
470 for (_M_curValue
.clear();
471 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen(':');
473 _M_curValue
+= *_M_current
;
474 if (_M_current
== _M_end
)
475 __throw_regex_error(regex_constants::error_ctype
);
476 ++_M_current
; // skip ':'
477 if (*_M_current
!= _M_ctype
.widen(']'))
478 __throw_regex_error(regex_constants::error_ctype
);
479 ++_M_current
; // skip ']'
483 template<typename _InputIterator
>
485 _Scanner
<_InputIterator
>::
488 ++_M_current
; // skip '='
489 if (_M_current
== _M_end
)
490 __throw_regex_error(regex_constants::error_collate
);
491 for (_M_curValue
.clear();
492 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen('=');
494 _M_curValue
+= *_M_current
;
495 if (_M_current
== _M_end
)
496 __throw_regex_error(regex_constants::error_collate
);
497 ++_M_current
; // skip '='
498 if (*_M_current
!= _M_ctype
.widen(']'))
499 __throw_regex_error(regex_constants::error_collate
);
500 ++_M_current
; // skip ']'
504 template<typename _InputIterator
>
506 _Scanner
<_InputIterator
>::
509 ++_M_current
; // skip '.'
510 if (_M_current
== _M_end
)
511 __throw_regex_error(regex_constants::error_collate
);
512 for (_M_curValue
.clear();
513 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen('.');
515 _M_curValue
+= *_M_current
;
516 if (_M_current
== _M_end
)
517 __throw_regex_error(regex_constants::error_collate
);
518 ++_M_current
; // skip '.'
519 if (*_M_current
!= _M_ctype
.widen(']'))
520 __throw_regex_error(regex_constants::error_collate
);
521 ++_M_current
; // skip ']'
524 #ifdef _GLIBCXX_DEBUG
525 template<typename _InputIterator
>
527 _Scanner
<_InputIterator
>::
528 _M_print(std::ostream
& ostr
)
532 case _S_token_anychar
:
533 ostr
<< "any-character\n";
535 case _S_token_backref
:
538 case _S_token_bracket_begin
:
539 ostr
<< "bracket-begin\n";
541 case _S_token_bracket_end
:
542 ostr
<< "bracket-end\n";
544 case _S_token_char_class_name
:
545 ostr
<< "char-class-name \"" << _M_curValue
<< "\"\n";
547 case _S_token_closure0
:
548 ostr
<< "closure0\n";
550 case _S_token_closure1
:
551 ostr
<< "closure1\n";
553 case _S_token_collelem_multi
:
554 ostr
<< "coll-elem-multi \"" << _M_curValue
<< "\"\n";
556 case _S_token_collelem_single
:
557 ostr
<< "coll-elem-single \"" << _M_curValue
<< "\"\n";
559 case _S_token_collsymbol
:
560 ostr
<< "collsymbol \"" << _M_curValue
<< "\"\n";
568 case _S_token_dup_count
:
569 ostr
<< "dup count: " << _M_curValue
<< "\n";
574 case _S_token_equiv_class_name
:
575 ostr
<< "equiv-class-name \"" << _M_curValue
<< "\"\n";
577 case _S_token_interval_begin
:
578 ostr
<< "interval begin\n";
580 case _S_token_interval_end
:
581 ostr
<< "interval end\n";
583 case _S_token_line_begin
:
584 ostr
<< "line begin\n";
586 case _S_token_line_end
:
587 ostr
<< "line end\n";
595 case _S_token_ord_char
:
596 ostr
<< "ordinary character: \"" << _M_value() << "\"\n";
598 case _S_token_quoted_char
:
599 ostr
<< "quoted char\n";
601 case _S_token_subexpr_begin
:
602 ostr
<< "subexpr begin\n";
604 case _S_token_subexpr_end
:
605 ostr
<< "subexpr end\n";
607 case _S_token_word_begin
:
608 ostr
<< "word begin\n";
610 case _S_token_word_end
:
611 ostr
<< "word end\n";
613 case _S_token_unknown
:
614 ostr
<< "-- unknown token --\n";
621 // Builds an NFA from an input iterator interval.
622 template<typename _InIter
, typename _TraitsT
>
626 typedef _InIter _IterT
;
627 typedef typename
std::iterator_traits
<_InIter
>::value_type _CharT
;
628 typedef std::basic_string
<_CharT
> _StringT
;
629 typedef regex_constants::syntax_option_type _FlagT
;
632 _Compiler(const _InIter
& __b
, const _InIter
& __e
,
633 _TraitsT
& __traits
, _FlagT __flags
);
637 { return _M_state_store
; }
640 typedef _Scanner
<_InIter
> _ScannerT
;
641 typedef typename
_ScannerT::_TokenT _TokenT
;
642 typedef std::stack
<_StateSeq
, std::vector
<_StateSeq
> > _StackT
;
643 typedef _RangeMatcher
<_InIter
, _TraitsT
> _RMatcherT
;
645 // accepts a specific token or returns false.
647 _M_match_token(_TokenT __token
);
668 _M_bracket_expression();
671 _M_bracket_list(_RMatcherT
& __matcher
);
674 _M_follow_list(_RMatcherT
& __matcher
);
677 _M_follow_list2(_RMatcherT
& __matcher
);
680 _M_expression_term(_RMatcherT
& __matcher
);
683 _M_range_expression(_RMatcherT
& __matcher
);
686 _M_start_range(_RMatcherT
& __matcher
);
689 _M_collating_symbol(_RMatcherT
& __matcher
);
692 _M_equivalence_class(_RMatcherT
& __matcher
);
695 _M_character_class(_RMatcherT
& __matcher
);
698 _M_cur_int_value(int __radix
);
702 _ScannerT _M_scanner
;
703 _StringT _M_cur_value
;
708 template<typename _InIter
, typename _TraitsT
>
709 _Compiler
<_InIter
, _TraitsT
>::
710 _Compiler(const _InIter
& __b
, const _InIter
& __e
, _TraitsT
& __traits
,
711 _Compiler
<_InIter
, _TraitsT
>::_FlagT __flags
)
712 : _M_traits(__traits
), _M_scanner(__b
, __e
, __flags
, _M_traits
.getloc()),
713 _M_state_store(__flags
)
716 using std::placeholders::_1
;
717 using std::placeholders::_2
;
718 typedef _StartTagger
<_InIter
, _TraitsT
> _Start
;
719 typedef _EndTagger
<_InIter
, _TraitsT
> _End
;
721 _StateSeq
__r(_M_state_store
,
722 _M_state_store
._M_insert_subexpr_begin(
723 bind(_Start(0), _1
, _2
)));
725 if (!_M_stack
.empty())
727 __r
._M_append(_M_stack
.top());
730 __r
._M_append(_M_state_store
.
731 _M_insert_subexpr_end(0, bind(_End(0), _1
, _2
)));
732 __r
._M_append(_M_state_store
._M_insert_accept());
735 template<typename _InIter
, typename _TraitsT
>
737 _Compiler
<_InIter
, _TraitsT
>::
738 _M_match_token(_Compiler
<_InIter
, _TraitsT
>::_TokenT token
)
740 if (token
== _M_scanner
._M_token())
742 _M_cur_value
= _M_scanner
._M_value();
743 _M_scanner
._M_advance();
749 template<typename _InIter
, typename _TraitsT
>
751 _Compiler
<_InIter
, _TraitsT
>::
754 this->_M_alternative();
755 if (_M_match_token(_ScannerT::_S_token_or
))
757 _StateSeq __alt1
= _M_stack
.top(); _M_stack
.pop();
758 this->_M_disjunction();
759 _StateSeq __alt2
= _M_stack
.top(); _M_stack
.pop();
760 _M_stack
.push(_StateSeq(__alt1
, __alt2
));
764 template<typename _InIter
, typename _TraitsT
>
766 _Compiler
<_InIter
, _TraitsT
>::
771 _StateSeq __re
= _M_stack
.top(); _M_stack
.pop();
772 this->_M_alternative();
773 if (!_M_stack
.empty())
775 __re
._M_append(_M_stack
.top());
784 template<typename _InIter
, typename _TraitsT
>
786 _Compiler
<_InIter
, _TraitsT
>::
789 if (this->_M_assertion())
793 this->_M_quantifier();
799 template<typename _InIter
, typename _TraitsT
>
801 _Compiler
<_InIter
, _TraitsT
>::
804 if (_M_match_token(_ScannerT::_S_token_line_begin
))
806 // __m.push(_Matcher::_S_opcode_line_begin);
809 if (_M_match_token(_ScannerT::_S_token_line_end
))
811 // __m.push(_Matcher::_S_opcode_line_end);
814 if (_M_match_token(_ScannerT::_S_token_word_begin
))
816 // __m.push(_Matcher::_S_opcode_word_begin);
819 if (_M_match_token(_ScannerT::_S_token_word_end
))
821 // __m.push(_Matcher::_S_opcode_word_end);
827 template<typename _InIter
, typename _TraitsT
>
829 _Compiler
<_InIter
, _TraitsT
>::
832 if (_M_match_token(_ScannerT::_S_token_closure0
))
834 if (_M_stack
.empty())
835 __throw_regex_error(regex_constants::error_badrepeat
);
836 _StateSeq
__r(_M_stack
.top(), -1);
837 __r
._M_append(__r
._M_front());
842 if (_M_match_token(_ScannerT::_S_token_closure1
))
844 if (_M_stack
.empty())
845 __throw_regex_error(regex_constants::error_badrepeat
);
846 _StateSeq
__r(_M_state_store
,
848 _M_insert_alt(_S_invalid_state_id
,
849 _M_stack
.top()._M_front()));
850 _M_stack
.top()._M_append(__r
);
853 if (_M_match_token(_ScannerT::_S_token_opt
))
855 if (_M_stack
.empty())
856 __throw_regex_error(regex_constants::error_badrepeat
);
857 _StateSeq
__r(_M_stack
.top(), -1);
862 if (_M_match_token(_ScannerT::_S_token_interval_begin
))
864 if (_M_stack
.empty())
865 __throw_regex_error(regex_constants::error_badrepeat
);
866 if (!_M_match_token(_ScannerT::_S_token_dup_count
))
867 __throw_regex_error(regex_constants::error_badbrace
);
868 _StateSeq
__r(_M_stack
.top());
869 int __min_rep
= _M_cur_int_value(10);
870 for (int __i
= 1; __i
< __min_rep
; ++__i
)
871 _M_stack
.top()._M_append(__r
._M_clone());
872 if (_M_match_token(_ScannerT::_S_token_comma
))
873 if (_M_match_token(_ScannerT::_S_token_dup_count
))
875 int __n
= _M_cur_int_value(10) - __min_rep
;
877 __throw_regex_error(regex_constants::error_badbrace
);
878 for (int __i
= 0; __i
< __n
; ++__i
)
880 _StateSeq
__r(_M_state_store
,
882 _M_insert_alt(_S_invalid_state_id
,
883 _M_stack
.top()._M_front()));
884 _M_stack
.top()._M_append(__r
);
889 _StateSeq
__r(_M_stack
.top(), -1);
890 __r
._M_push_back(__r
._M_front());
894 if (!_M_match_token(_ScannerT::_S_token_interval_end
))
895 __throw_regex_error(regex_constants::error_brace
);
901 template<typename _InIter
, typename _TraitsT
>
903 _Compiler
<_InIter
, _TraitsT
>::
907 using std::placeholders::_1
;
908 using std::placeholders::_2
;
909 typedef _CharMatcher
<_InIter
, _TraitsT
> _CMatcher
;
910 typedef _StartTagger
<_InIter
, _TraitsT
> _Start
;
911 typedef _EndTagger
<_InIter
, _TraitsT
> _End
;
913 if (_M_match_token(_ScannerT::_S_token_anychar
))
915 _M_stack
.push(_StateSeq(_M_state_store
,
917 _M_insert_matcher(bind(_AnyMatcher
, _1
))));
920 if (_M_match_token(_ScannerT::_S_token_ord_char
))
922 _M_stack
.push(_StateSeq
923 (_M_state_store
, _M_state_store
.
925 (bind(_CMatcher(_M_cur_value
[0], _M_traits
), _1
))));
928 if (_M_match_token(_ScannerT::_S_token_quoted_char
))
930 // note that in the ECMA grammar, this case covers backrefs.
931 _M_stack
.push(_StateSeq(_M_state_store
,
934 (bind(_CMatcher(_M_cur_value
[0], _M_traits
),
938 if (_M_match_token(_ScannerT::_S_token_backref
))
940 // __m.push(_Matcher::_S_opcode_ordchar, _M_cur_value);
943 if (_M_match_token(_ScannerT::_S_token_subexpr_begin
))
945 int __mark
= _M_state_store
._M_sub_count();
946 _StateSeq
__r(_M_state_store
,
948 _M_insert_subexpr_begin(bind(_Start(__mark
), _1
, _2
)));
949 this->_M_disjunction();
950 if (!_M_match_token(_ScannerT::_S_token_subexpr_end
))
951 __throw_regex_error(regex_constants::error_paren
);
952 if (!_M_stack
.empty())
954 __r
._M_append(_M_stack
.top());
957 __r
._M_append(_M_state_store
._M_insert_subexpr_end
958 (__mark
, bind(_End(__mark
), _1
, _2
)));
962 return _M_bracket_expression();
965 template<typename _InIter
, typename _TraitsT
>
967 _Compiler
<_InIter
, _TraitsT
>::
968 _M_bracket_expression()
971 using std::placeholders::_1
;
972 if (_M_match_token(_ScannerT::_S_token_bracket_begin
))
974 _RMatcherT
__matcher(_M_match_token(_ScannerT::_S_token_line_begin
),
976 if (!_M_bracket_list(__matcher
)
977 || !_M_match_token(_ScannerT::_S_token_bracket_end
))
978 __throw_regex_error(regex_constants::error_brack
);
979 _M_stack
.push(_StateSeq(_M_state_store
,
980 _M_state_store
._M_insert_matcher
981 (bind(__matcher
, _1
))));
987 // If the dash is the last character in the bracket expression, it is not
989 template<typename _InIter
, typename _TraitsT
>
991 _Compiler
<_InIter
, _TraitsT
>::
992 _M_bracket_list(_RMatcherT
& __matcher
)
994 if (_M_follow_list(__matcher
))
996 if (_M_match_token(_ScannerT::_S_token_dash
))
997 __matcher
._M_add_char(_M_cur_value
[0]);
1003 template<typename _InIter
, typename _TraitsT
>
1005 _Compiler
<_InIter
, _TraitsT
>::
1006 _M_follow_list(_RMatcherT
& __matcher
)
1007 { return _M_expression_term(__matcher
) && _M_follow_list2(__matcher
); }
1009 template<typename _InIter
, typename _TraitsT
>
1011 _Compiler
<_InIter
, _TraitsT
>::
1012 _M_follow_list2(_RMatcherT
& __matcher
)
1014 if (_M_expression_term(__matcher
))
1015 return _M_follow_list2(__matcher
);
1019 template<typename _InIter
, typename _TraitsT
>
1021 _Compiler
<_InIter
, _TraitsT
>::
1022 _M_expression_term(_RMatcherT
& __matcher
)
1024 return (_M_collating_symbol(__matcher
)
1025 || _M_character_class(__matcher
)
1026 || _M_equivalence_class(__matcher
)
1027 || (_M_start_range(__matcher
)
1028 && _M_range_expression(__matcher
)));
1031 template<typename _InIter
, typename _TraitsT
>
1033 _Compiler
<_InIter
, _TraitsT
>::
1034 _M_range_expression(_RMatcherT
& __matcher
)
1036 if (!_M_collating_symbol(__matcher
))
1037 if (!_M_match_token(_ScannerT::_S_token_dash
))
1038 __throw_regex_error(regex_constants::error_range
);
1039 __matcher
._M_make_range();
1043 template<typename _InIter
, typename _TraitsT
>
1045 _Compiler
<_InIter
, _TraitsT
>::
1046 _M_start_range(_RMatcherT
& __matcher
)
1047 { return _M_match_token(_ScannerT::_S_token_dash
); }
1049 template<typename _InIter
, typename _TraitsT
>
1051 _Compiler
<_InIter
, _TraitsT
>::
1052 _M_collating_symbol(_RMatcherT
& __matcher
)
1054 if (_M_match_token(_ScannerT::_S_token_collelem_single
))
1056 __matcher
._M_add_char(_M_cur_value
[0]);
1059 if (_M_match_token(_ScannerT::_S_token_collsymbol
))
1061 __matcher
._M_add_collating_element(_M_cur_value
);
1067 template<typename _InIter
, typename _TraitsT
>
1069 _Compiler
<_InIter
, _TraitsT
>::
1070 _M_equivalence_class(_RMatcherT
& __matcher
)
1072 if (_M_match_token(_ScannerT::_S_token_equiv_class_name
))
1074 __matcher
._M_add_equivalence_class(_M_cur_value
);
1080 template<typename _InIter
, typename _TraitsT
>
1082 _Compiler
<_InIter
, _TraitsT
>::
1083 _M_character_class(_RMatcherT
& __matcher
)
1085 if (_M_match_token(_ScannerT::_S_token_char_class_name
))
1087 __matcher
._M_add_character_class(_M_cur_value
);
1093 template<typename _InIter
, typename _TraitsT
>
1095 _Compiler
<_InIter
, _TraitsT
>::
1096 _M_cur_int_value(int __radix
)
1099 for (typename
_StringT::size_type __i
= 0;
1100 __i
< _M_cur_value
.length(); ++__i
)
1101 __v
=__v
* __radix
+ _M_traits
.value(_M_cur_value
[__i
], __radix
);
1105 template<typename _InIter
, typename _TraitsT
>
1107 __compile(const _InIter
& __b
, const _InIter
& __e
, _TraitsT
& __t
,
1108 regex_constants::syntax_option_type __f
)
1109 { return _AutomatonPtr(new _Nfa(_Compiler
<_InIter
, _TraitsT
>(__b
, __e
, __t
,
1112 } // namespace __regex
1114 _GLIBCXX_END_NAMESPACE
1116 /* vim: set ts=8 sw=2 sts=2: */