1 // class template regex -*- C++ -*-
3 // Copyright (C) 2010-2013 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 namespace std
_GLIBCXX_VISIBILITY(default)
35 _GLIBCXX_BEGIN_NAMESPACE_VERSION
38 * @addtogroup regex-detail
42 /// Base class for scanner.
45 typedef unsigned int _StateT
;
47 static constexpr _StateT _S_state_in_brace
= 1 << 0;
48 static constexpr _StateT _S_state_in_bracket
= 1 << 1;
50 virtual ~_Scanner_base() { };
54 * @brief struct _Scanner. Scans an input range for regex tokens.
56 * The %_Scanner class interprets the regular expression pattern in
57 * the input range passed to its constructor as a sequence of parse
58 * tokens passed to the regular expression compiler. The sequence
59 * of tokens provided depends on the flag settings passed to the
60 * constructor: different regular expression grammars will interpret
61 * the same input pattern in syntactically different ways.
63 template<typename _InputIterator
>
64 class _Scanner
: public _Scanner_base
67 typedef _InputIterator _IteratorT
;
68 typedef typename
std::iterator_traits
<_IteratorT
>::value_type _CharT
;
69 typedef std::basic_string
<_CharT
> _StringT
;
70 typedef regex_constants::syntax_option_type _FlagT
;
71 typedef const std::ctype
<_CharT
> _CtypeT
;
73 /// Token types returned from the scanner.
78 _S_token_bracket_begin
,
79 _S_token_bracket_inverse_begin
,
81 _S_token_char_class_name
,
84 _S_token_collelem_multi
,
85 _S_token_collelem_single
,
91 _S_token_equiv_class_name
,
92 _S_token_interval_begin
,
93 _S_token_interval_end
,
99 _S_token_subexpr_begin
,
100 _S_token_subexpr_end
,
106 _Scanner(_IteratorT __begin
, _IteratorT __end
, _FlagT __flags
,
108 : _M_current(__begin
) , _M_end(__end
) , _M_flags(__flags
),
109 _M_ctype(std::use_facet
<_CtypeT
>(__loc
)), _M_state(0)
117 { return _M_curToken
; }
121 { return _M_curValue
; }
123 #ifdef _GLIBCXX_DEBUG
125 _M_print(std::ostream
&);
136 _M_scan_in_bracket();
147 _IteratorT _M_current
;
152 _StringT _M_curValue
;
156 template<typename _InputIterator
>
158 _Scanner
<_InputIterator
>::
161 if (_M_current
== _M_end
)
163 _M_curToken
= _S_token_eof
;
167 _CharT __c
= *_M_current
;
168 if (_M_state
& _S_state_in_bracket
)
170 _M_scan_in_bracket();
173 if (_M_state
& _S_state_in_brace
)
179 // TODO: re-enable line anchors when _M_assertion is implemented.
180 // See PR libstdc++/47724
181 else if (_M_state
& _S_state_at_start
&& __c
== _M_ctype
.widen('^'))
183 _M_curToken
= _S_token_line_begin
;
187 else if (__c
== _M_ctype
.widen('$'))
189 _M_curToken
= _S_token_line_end
;
194 else if (__c
== _M_ctype
.widen('.'))
196 _M_curToken
= _S_token_anychar
;
200 else if (__c
== _M_ctype
.widen('*'))
202 _M_curToken
= _S_token_closure0
;
206 else if (__c
== _M_ctype
.widen('+'))
208 _M_curToken
= _S_token_closure1
;
212 else if (__c
== _M_ctype
.widen('|'))
214 _M_curToken
= _S_token_or
;
218 else if (__c
== _M_ctype
.widen('['))
220 if (*++_M_current
== _M_ctype
.widen('^'))
222 _M_curToken
= _S_token_bracket_inverse_begin
;
226 _M_curToken
= _S_token_bracket_begin
;
227 _M_state
|= _S_state_in_bracket
;
230 else if (__c
== _M_ctype
.widen('\\'))
235 else if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
237 if (__c
== _M_ctype
.widen('('))
239 _M_curToken
= _S_token_subexpr_begin
;
243 else if (__c
== _M_ctype
.widen(')'))
245 _M_curToken
= _S_token_subexpr_end
;
249 else if (__c
== _M_ctype
.widen('{'))
251 _M_curToken
= _S_token_interval_begin
;
252 _M_state
|= _S_state_in_brace
;
258 _M_curToken
= _S_token_ord_char
;
259 _M_curValue
.assign(1, __c
);
264 template<typename _InputIterator
>
266 _Scanner
<_InputIterator
>::
269 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
271 _M_curToken
= _S_token_dup_count
;
272 _M_curValue
.assign(1, *_M_current
);
274 while (_M_current
!= _M_end
275 && _M_ctype
.is(_CtypeT::digit
, *_M_current
))
277 _M_curValue
+= *_M_current
;
282 else if (*_M_current
== _M_ctype
.widen(','))
284 _M_curToken
= _S_token_comma
;
288 if (_M_flags
& (regex_constants::basic
| regex_constants::grep
))
290 if (*_M_current
== _M_ctype
.widen('\\'))
295 if (*_M_current
== _M_ctype
.widen('}'))
297 _M_curToken
= _S_token_interval_end
;
298 _M_state
&= ~_S_state_in_brace
;
305 template<typename _InputIterator
>
307 _Scanner
<_InputIterator
>::
310 if (*_M_current
== _M_ctype
.widen('['))
313 if (_M_current
== _M_end
)
315 _M_curToken
= _S_token_eof
;
319 if (*_M_current
== _M_ctype
.widen('.'))
321 _M_curToken
= _S_token_collsymbol
;
325 else if (*_M_current
== _M_ctype
.widen(':'))
327 _M_curToken
= _S_token_char_class_name
;
331 else if (*_M_current
== _M_ctype
.widen('='))
333 _M_curToken
= _S_token_equiv_class_name
;
338 else if (*_M_current
== _M_ctype
.widen('-'))
340 _M_curToken
= _S_token_dash
;
344 else if (*_M_current
== _M_ctype
.widen(']'))
346 _M_curToken
= _S_token_bracket_end
;
347 _M_state
&= ~_S_state_in_bracket
;
351 else if (*_M_current
== _M_ctype
.widen('\\'))
356 _M_curToken
= _S_token_collelem_single
;
357 _M_curValue
.assign(1, *_M_current
);
361 // TODO implement it.
362 template<typename _InputIterator
>
364 _Scanner
<_InputIterator
>::
368 if (_M_current
== _M_end
)
370 _M_curToken
= _S_token_eof
;
373 _CharT __c
= *_M_current
;
376 if (__c
== _M_ctype
.widen('('))
378 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
380 _M_curToken
= _S_token_ord_char
;
381 _M_curValue
.assign(1, __c
);
384 _M_curToken
= _S_token_subexpr_begin
;
386 else if (__c
== _M_ctype
.widen(')'))
388 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
390 _M_curToken
= _S_token_ord_char
;
391 _M_curValue
.assign(1, __c
);
394 _M_curToken
= _S_token_subexpr_end
;
396 else if (__c
== _M_ctype
.widen('{'))
398 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
400 _M_curToken
= _S_token_ord_char
;
401 _M_curValue
.assign(1, __c
);
405 _M_curToken
= _S_token_interval_begin
;
406 _M_state
|= _S_state_in_brace
;
409 else if (__c
== _M_ctype
.widen('}'))
411 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
413 _M_curToken
= _S_token_ord_char
;
414 _M_curValue
.assign(1, __c
);
418 if (!(_M_state
&& _S_state_in_brace
))
419 __throw_regex_error(regex_constants::error_badbrace
);
420 _M_state
&= ~_S_state_in_brace
;
421 _M_curToken
= _S_token_interval_end
;
424 else if (__c
== _M_ctype
.widen('x'))
427 if (_M_current
== _M_end
)
429 _M_curToken
= _S_token_eof
;
432 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
434 _M_curValue
.assign(1, *_M_current
);
436 if (_M_current
== _M_end
)
438 _M_curToken
= _S_token_eof
;
441 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
443 _M_curValue
+= *_M_current
;
449 else if (__c
== _M_ctype
.widen('^')
450 || __c
== _M_ctype
.widen('.')
451 || __c
== _M_ctype
.widen('*')
452 || __c
== _M_ctype
.widen('$')
453 || __c
== _M_ctype
.widen('\\'))
455 _M_curToken
= _S_token_ord_char
;
456 _M_curValue
.assign(1, __c
);
458 else if (_M_ctype
.is(_CtypeT::digit
, __c
))
460 _M_curToken
= _S_token_backref
;
461 _M_curValue
.assign(1, __c
);
463 else if (_M_state
& _S_state_in_bracket
)
465 if (__c
== _M_ctype
.widen('-')
466 || __c
== _M_ctype
.widen('[')
467 || __c
== _M_ctype
.widen(']'))
469 _M_curToken
= _S_token_ord_char
;
470 _M_curValue
.assign(1, __c
);
472 else if ((_M_flags
& regex_constants::ECMAScript
)
473 && __c
== _M_ctype
.widen('b'))
475 _M_curToken
= _S_token_ord_char
;
476 _M_curValue
.assign(1, _M_ctype
.widen(' '));
479 __throw_regex_error(regex_constants::error_escape
);
482 __throw_regex_error(regex_constants::error_escape
);
485 // Eats a character class or throwns an exception.
486 // current point to ':' delimiter on entry, char after ']' on return
487 template<typename _InputIterator
>
489 _Scanner
<_InputIterator
>::
492 ++_M_current
; // skip ':'
493 if (_M_current
== _M_end
)
494 __throw_regex_error(regex_constants::error_ctype
);
495 for (_M_curValue
.clear();
496 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen(':');
498 _M_curValue
+= *_M_current
;
499 if (_M_current
== _M_end
)
500 __throw_regex_error(regex_constants::error_ctype
);
501 ++_M_current
; // skip ':'
502 if (*_M_current
!= _M_ctype
.widen(']'))
503 __throw_regex_error(regex_constants::error_ctype
);
504 ++_M_current
; // skip ']'
508 template<typename _InputIterator
>
510 _Scanner
<_InputIterator
>::
513 ++_M_current
; // skip '='
514 if (_M_current
== _M_end
)
515 __throw_regex_error(regex_constants::error_collate
);
516 for (_M_curValue
.clear();
517 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen('=');
519 _M_curValue
+= *_M_current
;
520 if (_M_current
== _M_end
)
521 __throw_regex_error(regex_constants::error_collate
);
522 ++_M_current
; // skip '='
523 if (*_M_current
!= _M_ctype
.widen(']'))
524 __throw_regex_error(regex_constants::error_collate
);
525 ++_M_current
; // skip ']'
529 template<typename _InputIterator
>
531 _Scanner
<_InputIterator
>::
534 ++_M_current
; // skip '.'
535 if (_M_current
== _M_end
)
536 __throw_regex_error(regex_constants::error_collate
);
537 for (_M_curValue
.clear();
538 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen('.');
540 _M_curValue
+= *_M_current
;
541 if (_M_current
== _M_end
)
542 __throw_regex_error(regex_constants::error_collate
);
543 ++_M_current
; // skip '.'
544 if (*_M_current
!= _M_ctype
.widen(']'))
545 __throw_regex_error(regex_constants::error_collate
);
546 ++_M_current
; // skip ']'
549 #ifdef _GLIBCXX_DEBUG
550 template<typename _InputIterator
>
552 _Scanner
<_InputIterator
>::
553 _M_print(std::ostream
& ostr
)
557 case _S_token_anychar
:
558 ostr
<< "any-character\n";
560 case _S_token_backref
:
563 case _S_token_bracket_begin
:
564 ostr
<< "bracket-begin\n";
566 case _S_token_bracket_inverse_begin
:
567 ostr
<< "bracket-inverse-begin\n";
569 case _S_token_bracket_end
:
570 ostr
<< "bracket-end\n";
572 case _S_token_char_class_name
:
573 ostr
<< "char-class-name \"" << _M_curValue
<< "\"\n";
575 case _S_token_closure0
:
576 ostr
<< "closure0\n";
578 case _S_token_closure1
:
579 ostr
<< "closure1\n";
581 case _S_token_collelem_multi
:
582 ostr
<< "coll-elem-multi \"" << _M_curValue
<< "\"\n";
584 case _S_token_collelem_single
:
585 ostr
<< "coll-elem-single \"" << _M_curValue
<< "\"\n";
587 case _S_token_collsymbol
:
588 ostr
<< "collsymbol \"" << _M_curValue
<< "\"\n";
596 case _S_token_dup_count
:
597 ostr
<< "dup count: " << _M_curValue
<< "\n";
602 case _S_token_equiv_class_name
:
603 ostr
<< "equiv-class-name \"" << _M_curValue
<< "\"\n";
605 case _S_token_interval_begin
:
606 ostr
<< "interval begin\n";
608 case _S_token_interval_end
:
609 ostr
<< "interval end\n";
611 case _S_token_line_begin
:
612 ostr
<< "line begin\n";
614 case _S_token_line_end
:
615 ostr
<< "line end\n";
623 case _S_token_ord_char
:
624 ostr
<< "ordinary character: \"" << _M_value() << "\"\n";
626 case _S_token_subexpr_begin
:
627 ostr
<< "subexpr begin\n";
629 case _S_token_subexpr_end
:
630 ostr
<< "subexpr end\n";
632 case _S_token_word_begin
:
633 ostr
<< "word begin\n";
635 case _S_token_word_end
:
636 ostr
<< "word end\n";
638 case _S_token_unknown
:
639 ostr
<< "-- unknown token --\n";
642 _GLIBCXX_DEBUG_ASSERT(false);
648 /// Builds an NFA from an input iterator interval.
649 template<typename _InIter
, typename _TraitsT
>
653 typedef _InIter _IterT
;
654 typedef typename
std::iterator_traits
<_InIter
>::value_type _CharT
;
655 typedef std::basic_string
<_CharT
> _StringT
;
656 typedef regex_constants::syntax_option_type _FlagT
;
658 _Compiler(const _InIter
& __b
, const _InIter
& __e
,
659 _TraitsT
& __traits
, _FlagT __flags
);
663 { return _M_state_store
; }
666 typedef _Scanner
<_InIter
> _ScannerT
;
667 typedef typename
_ScannerT::_TokenT _TokenT
;
668 typedef std::stack
<_StateSeq
, std::vector
<_StateSeq
> > _StackT
;
669 typedef _BracketMatcher
<_InIter
, _TraitsT
> _BMatcherT
;
671 // accepts a specific token or returns false.
673 _M_match_token(_TokenT __token
);
694 _M_bracket_expression();
697 _M_bracket_list(_BMatcherT
& __matcher
);
700 _M_follow_list(_BMatcherT
& __matcher
);
703 _M_expression_term(_BMatcherT
& __matcher
);
706 _M_range_expression(_BMatcherT
& __matcher
);
709 _M_start_range(_BMatcherT
& __matcher
);
712 _M_collating_symbol(_BMatcherT
& __matcher
);
715 _M_equivalence_class(_BMatcherT
& __matcher
);
718 _M_character_class(_BMatcherT
& __matcher
);
721 _M_cur_int_value(int __radix
);
724 _ScannerT _M_scanner
;
725 _StringT _M_cur_value
;
731 template<typename _InIter
, typename _TraitsT
>
732 _Compiler
<_InIter
, _TraitsT
>::
733 _Compiler(const _InIter
& __b
, const _InIter
& __e
, _TraitsT
& __traits
,
734 _Compiler
<_InIter
, _TraitsT
>::_FlagT __flags
)
735 : _M_traits(__traits
), _M_scanner(__b
, __e
, __flags
, _M_traits
.getloc()),
736 _M_state_store(__flags
), _M_flags(__flags
)
738 typedef _StartTagger
<_InIter
, _TraitsT
> _Start
;
739 typedef _EndTagger
<_InIter
, _TraitsT
> _End
;
741 _StateSeq
__r(_M_state_store
,
742 _M_state_store
._M_insert_subexpr_begin(_Start(0)));
744 if (!_M_stack
.empty())
746 __r
._M_append(_M_stack
.top());
749 __r
._M_append(_M_state_store
._M_insert_subexpr_end(0, _End(0)));
750 __r
._M_append(_M_state_store
._M_insert_accept());
753 template<typename _InIter
, typename _TraitsT
>
755 _Compiler
<_InIter
, _TraitsT
>::
756 _M_match_token(_Compiler
<_InIter
, _TraitsT
>::_TokenT token
)
758 if (token
== _M_scanner
._M_token())
760 _M_cur_value
= _M_scanner
._M_value();
761 _M_scanner
._M_advance();
767 template<typename _InIter
, typename _TraitsT
>
769 _Compiler
<_InIter
, _TraitsT
>::
772 this->_M_alternative();
773 if (_M_match_token(_ScannerT::_S_token_or
))
775 _StateSeq __alt1
= _M_stack
.top(); _M_stack
.pop();
776 this->_M_disjunction();
777 _StateSeq __alt2
= _M_stack
.top(); _M_stack
.pop();
778 _M_stack
.push(_StateSeq(__alt1
, __alt2
));
782 template<typename _InIter
, typename _TraitsT
>
784 _Compiler
<_InIter
, _TraitsT
>::
789 _StateSeq __re
= _M_stack
.top(); _M_stack
.pop();
790 this->_M_alternative();
791 if (!_M_stack
.empty())
793 __re
._M_append(_M_stack
.top());
800 template<typename _InIter
, typename _TraitsT
>
802 _Compiler
<_InIter
, _TraitsT
>::
805 if (this->_M_assertion())
809 this->_M_quantifier();
815 template<typename _InIter
, typename _TraitsT
>
817 _Compiler
<_InIter
, _TraitsT
>::
820 if (_M_match_token(_ScannerT::_S_token_line_begin
))
822 // __m.push(_Matcher::_S_opcode_line_begin);
825 if (_M_match_token(_ScannerT::_S_token_line_end
))
827 // __m.push(_Matcher::_S_opcode_line_end);
830 if (_M_match_token(_ScannerT::_S_token_word_begin
))
832 // __m.push(_Matcher::_S_opcode_word_begin);
835 if (_M_match_token(_ScannerT::_S_token_word_end
))
837 // __m.push(_Matcher::_S_opcode_word_end);
843 template<typename _InIter
, typename _TraitsT
>
845 _Compiler
<_InIter
, _TraitsT
>::
848 if (_M_match_token(_ScannerT::_S_token_closure0
))
850 if (_M_stack
.empty())
851 __throw_regex_error(regex_constants::error_badrepeat
);
852 _StateSeq
__r(_M_stack
.top(), -1);
853 __r
._M_append(__r
._M_front());
858 if (_M_match_token(_ScannerT::_S_token_closure1
))
860 if (_M_stack
.empty())
861 __throw_regex_error(regex_constants::error_badrepeat
);
862 _StateSeq
__r(_M_state_store
,
864 _M_insert_alt(_S_invalid_state_id
,
865 _M_stack
.top()._M_front()));
866 _M_stack
.top()._M_append(__r
);
869 if (_M_match_token(_ScannerT::_S_token_opt
))
871 if (_M_stack
.empty())
872 __throw_regex_error(regex_constants::error_badrepeat
);
873 _StateSeq
__r(_M_stack
.top(), -1);
878 if (_M_match_token(_ScannerT::_S_token_interval_begin
))
880 if (_M_stack
.empty())
881 __throw_regex_error(regex_constants::error_badrepeat
);
882 if (!_M_match_token(_ScannerT::_S_token_dup_count
))
883 __throw_regex_error(regex_constants::error_badbrace
);
884 _StateSeq
__r(_M_stack
.top());
885 int __min_rep
= _M_cur_int_value(10);
886 for (int __i
= 1; __i
< __min_rep
; ++__i
)
887 _M_stack
.top()._M_append(__r
._M_clone());
888 if (_M_match_token(_ScannerT::_S_token_comma
))
889 if (_M_match_token(_ScannerT::_S_token_dup_count
))
891 int __n
= _M_cur_int_value(10) - __min_rep
;
893 __throw_regex_error(regex_constants::error_badbrace
);
894 for (int __i
= 0; __i
< __n
; ++__i
)
896 _StateSeq
__r(_M_state_store
,
898 _M_insert_alt(_S_invalid_state_id
,
899 _M_stack
.top()._M_front()));
900 _M_stack
.top()._M_append(__r
);
905 _StateSeq
__r(_M_stack
.top(), -1);
906 __r
._M_push_back(__r
._M_front());
910 if (!_M_match_token(_ScannerT::_S_token_interval_end
))
911 __throw_regex_error(regex_constants::error_brace
);
916 template<typename _InIter
, typename _TraitsT
>
918 _Compiler
<_InIter
, _TraitsT
>::
921 typedef _CharMatcher
<_InIter
, _TraitsT
> _CMatcher
;
922 typedef _StartTagger
<_InIter
, _TraitsT
> _Start
;
923 typedef _EndTagger
<_InIter
, _TraitsT
> _End
;
925 if (_M_match_token(_ScannerT::_S_token_anychar
))
927 _M_stack
.push(_StateSeq(_M_state_store
,
928 _M_state_store
._M_insert_matcher
932 if (_M_match_token(_ScannerT::_S_token_ord_char
))
934 _M_stack
.push(_StateSeq(_M_state_store
,
935 _M_state_store
._M_insert_matcher
936 (_CMatcher(_M_cur_value
[0], _M_flags
, _M_traits
))));
939 if (_M_match_token(_ScannerT::_S_token_backref
))
941 // __m.push(_Matcher::_S_opcode_ordchar, _M_cur_value);
942 _M_state_store
._M_set_back_ref(true);
945 if (_M_match_token(_ScannerT::_S_token_subexpr_begin
))
947 int __mark
= _M_state_store
._M_sub_count();
948 _StateSeq
__r(_M_state_store
,
950 _M_insert_subexpr_begin(_Start(__mark
)));
951 this->_M_disjunction();
952 if (!_M_match_token(_ScannerT::_S_token_subexpr_end
))
953 __throw_regex_error(regex_constants::error_paren
);
954 if (!_M_stack
.empty())
956 __r
._M_append(_M_stack
.top());
959 __r
._M_append(_M_state_store
._M_insert_subexpr_end
960 (__mark
, _End(__mark
)));
964 return _M_bracket_expression();
967 template<typename _InIter
, typename _TraitsT
>
969 _Compiler
<_InIter
, _TraitsT
>::
970 _M_bracket_expression()
973 _M_match_token(_ScannerT::_S_token_bracket_inverse_begin
);
974 if (!(__inverse
|| _M_match_token(_ScannerT::_S_token_bracket_begin
)))
976 _BMatcherT
__matcher( __inverse
, _M_flags
, _M_traits
);
977 // special case: only if _not_ chr first after
978 // '[' or '[^' or if ECMAscript
979 if (!_M_bracket_list(__matcher
) // list is empty
980 && !(_M_flags
& regex_constants::ECMAScript
))
981 __throw_regex_error(regex_constants::error_brack
);
982 _M_stack
.push(_StateSeq(_M_state_store
,
983 _M_state_store
._M_insert_matcher(__matcher
)));
987 template<typename _InIter
, typename _TraitsT
>
988 bool // list is non-empty
989 _Compiler
<_InIter
, _TraitsT
>::
990 _M_bracket_list(_BMatcherT
& __matcher
)
992 if (_M_match_token(_ScannerT::_S_token_bracket_end
))
994 _M_expression_term(__matcher
);
995 _M_bracket_list(__matcher
);
999 template<typename _InIter
, typename _TraitsT
>
1001 _Compiler
<_InIter
, _TraitsT
>::
1002 _M_expression_term(_BMatcherT
& __matcher
)
1004 if (_M_match_token(_ScannerT::_S_token_collsymbol
))
1006 __matcher
._M_add_collating_element(_M_cur_value
);
1009 if (_M_match_token(_ScannerT::_S_token_equiv_class_name
))
1011 __matcher
._M_add_equivalence_class(_M_cur_value
);
1014 if (_M_match_token(_ScannerT::_S_token_char_class_name
))
1016 __matcher
._M_add_character_class(_M_cur_value
);
1019 if (_M_match_token(_ScannerT::_S_token_collelem_single
)) // [a
1021 auto __ch
= _M_cur_value
[0];
1022 if (_M_match_token(_ScannerT::_S_token_dash
)) // [a-
1024 // If the dash is the last character in the bracket expression,
1025 // it is not special.
1026 if (_M_scanner
._M_token() == _ScannerT::_S_token_bracket_end
)
1027 __matcher
._M_add_char(_M_cur_value
[0]); // [a-] <=> [a\-]
1030 if (!_M_match_token(_ScannerT::_S_token_collelem_single
))
1031 __throw_regex_error(regex_constants::error_range
);
1032 __matcher
._M_make_range(__ch
, _M_cur_value
[0]);
1036 __matcher
._M_add_char(__ch
);
1039 __throw_regex_error(regex_constants::error_brack
);
1042 template<typename _InIter
, typename _TraitsT
>
1044 _Compiler
<_InIter
, _TraitsT
>::
1045 _M_cur_int_value(int __radix
)
1048 for (typename
_StringT::size_type __i
= 0;
1049 __i
< _M_cur_value
.length(); ++__i
)
1050 __v
=__v
* __radix
+ _M_traits
.value(_M_cur_value
[__i
], __radix
);
1054 template<typename _InIter
, typename _TraitsT
>
1056 __compile(const _InIter
& __b
, const _InIter
& __e
, _TraitsT
& __t
,
1057 regex_constants::syntax_option_type __f
)
1058 { return _AutomatonPtr(new _Nfa(_Compiler
<_InIter
, _TraitsT
>(__b
, __e
, __t
,
1062 _GLIBCXX_END_NAMESPACE_VERSION
1063 } // namespace __detail