1 // class template regex -*- C++ -*-
3 // Copyright (C) 2010, 2011 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
39 typedef unsigned int _StateT
;
41 static constexpr _StateT _S_state_at_start
= 1 << 0;
42 static constexpr _StateT _S_state_in_brace
= 1 << 2;
43 static constexpr _StateT _S_state_in_bracket
= 1 << 3;
45 virtual ~_Scanner_base() { };
49 // @brief Scans an input range for regex tokens.
51 // The %_Scanner class interprets the regular expression pattern in the input
52 // range passed to its constructor as a sequence of parse tokens passed to
53 // the regular expression compiler. The sequence of tokens provided depends
54 // on the flag settings passed to the constructor: different regular
55 // expression grammars will interpret the same input pattern in
56 // syntactically different ways.
58 template<typename _InputIterator
>
59 class _Scanner
: public _Scanner_base
62 typedef _InputIterator _IteratorT
;
63 typedef typename
std::iterator_traits
<_IteratorT
>::value_type _CharT
;
64 typedef std::basic_string
<_CharT
> _StringT
;
65 typedef regex_constants::syntax_option_type _FlagT
;
66 typedef const std::ctype
<_CharT
> _CtypeT
;
68 // Token types returned from the scanner.
73 _S_token_bracket_begin
,
75 _S_token_inverse_class
,
76 _S_token_char_class_name
,
79 _S_token_collelem_multi
,
80 _S_token_collelem_single
,
86 _S_token_equiv_class_name
,
87 _S_token_interval_begin
,
88 _S_token_interval_end
,
95 _S_token_subexpr_begin
,
103 _Scanner(_IteratorT __begin
, _IteratorT __end
, _FlagT __flags
,
105 : _M_current(__begin
) , _M_end(__end
) , _M_flags(__flags
),
106 _M_ctype(std::use_facet
<_CtypeT
>(__loc
)), _M_state(_S_state_at_start
)
114 { return _M_curToken
; }
118 { return _M_curValue
; }
120 #ifdef _GLIBCXX_DEBUG
122 _M_print(std::ostream
&);
133 _M_scan_in_bracket();
145 _IteratorT _M_current
;
150 _StringT _M_curValue
;
154 template<typename _InputIterator
>
156 _Scanner
<_InputIterator
>::
159 if (_M_current
== _M_end
)
161 _M_curToken
= _S_token_eof
;
165 _CharT __c
= *_M_current
;
166 if (_M_state
& _S_state_in_bracket
)
168 _M_scan_in_bracket();
171 if (_M_state
& _S_state_in_brace
)
177 // TODO: re-enable line anchors when _M_assertion is implemented.
178 // See PR libstdc++/47724
179 else if (_M_state
& _S_state_at_start
&& __c
== _M_ctype
.widen('^'))
181 _M_curToken
= _S_token_line_begin
;
185 else if (__c
== _M_ctype
.widen('$'))
187 _M_curToken
= _S_token_line_end
;
192 else if (__c
== _M_ctype
.widen('.'))
194 _M_curToken
= _S_token_anychar
;
198 else if (__c
== _M_ctype
.widen('*'))
200 _M_curToken
= _S_token_closure0
;
204 else if (__c
== _M_ctype
.widen('+'))
206 _M_curToken
= _S_token_closure1
;
210 else if (__c
== _M_ctype
.widen('|'))
212 _M_curToken
= _S_token_or
;
216 else if (__c
== _M_ctype
.widen('['))
218 _M_curToken
= _S_token_bracket_begin
;
219 _M_state
|= (_S_state_in_bracket
| _S_state_at_start
);
223 else if (__c
== _M_ctype
.widen('\\'))
228 else if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
230 if (__c
== _M_ctype
.widen('('))
232 _M_curToken
= _S_token_subexpr_begin
;
236 else if (__c
== _M_ctype
.widen(')'))
238 _M_curToken
= _S_token_subexpr_end
;
242 else if (__c
== _M_ctype
.widen('{'))
244 _M_curToken
= _S_token_interval_begin
;
245 _M_state
|= _S_state_in_brace
;
251 _M_curToken
= _S_token_ord_char
;
252 _M_curValue
.assign(1, __c
);
257 template<typename _InputIterator
>
259 _Scanner
<_InputIterator
>::
262 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
264 _M_curToken
= _S_token_dup_count
;
265 _M_curValue
.assign(1, *_M_current
);
267 while (_M_current
!= _M_end
268 && _M_ctype
.is(_CtypeT::digit
, *_M_current
))
270 _M_curValue
+= *_M_current
;
275 else if (*_M_current
== _M_ctype
.widen(','))
277 _M_curToken
= _S_token_comma
;
281 if (_M_flags
& (regex_constants::basic
| regex_constants::grep
))
283 if (*_M_current
== _M_ctype
.widen('\\'))
288 if (*_M_current
== _M_ctype
.widen('}'))
290 _M_curToken
= _S_token_interval_end
;
291 _M_state
&= ~_S_state_in_brace
;
298 template<typename _InputIterator
>
300 _Scanner
<_InputIterator
>::
303 if (_M_state
& _S_state_at_start
&& *_M_current
== _M_ctype
.widen('^'))
305 _M_curToken
= _S_token_inverse_class
;
306 _M_state
&= ~_S_state_at_start
;
310 else 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 if (!(_M_flags
& regex_constants::ECMAScript
)
347 || !(_M_state
& _S_state_at_start
))
349 // special case: only if _not_ chr first after
350 // '[' or '[^' and if not ECMAscript
351 _M_curToken
= _S_token_bracket_end
;
356 _M_curToken
= _S_token_collelem_single
;
357 _M_curValue
.assign(1, *_M_current
);
361 template<typename _InputIterator
>
363 _Scanner
<_InputIterator
>::
367 if (_M_current
== _M_end
)
369 _M_curToken
= _S_token_eof
;
372 _CharT __c
= *_M_current
;
375 if (__c
== _M_ctype
.widen('('))
377 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
379 _M_curToken
= _S_token_ord_char
;
380 _M_curValue
.assign(1, __c
);
383 _M_curToken
= _S_token_subexpr_begin
;
385 else if (__c
== _M_ctype
.widen(')'))
387 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
389 _M_curToken
= _S_token_ord_char
;
390 _M_curValue
.assign(1, __c
);
393 _M_curToken
= _S_token_subexpr_end
;
395 else if (__c
== _M_ctype
.widen('{'))
397 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
399 _M_curToken
= _S_token_ord_char
;
400 _M_curValue
.assign(1, __c
);
404 _M_curToken
= _S_token_interval_begin
;
405 _M_state
|= _S_state_in_brace
;
408 else if (__c
== _M_ctype
.widen('}'))
410 if (!(_M_flags
& (regex_constants::basic
| regex_constants::grep
)))
412 _M_curToken
= _S_token_ord_char
;
413 _M_curValue
.assign(1, __c
);
417 if (!(_M_state
&& _S_state_in_brace
))
418 __throw_regex_error(regex_constants::error_badbrace
);
419 _M_state
&= ~_S_state_in_brace
;
420 _M_curToken
= _S_token_interval_end
;
423 else if (__c
== _M_ctype
.widen('x'))
426 if (_M_current
== _M_end
)
428 _M_curToken
= _S_token_eof
;
431 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
433 _M_curValue
.assign(1, *_M_current
);
435 if (_M_current
== _M_end
)
437 _M_curToken
= _S_token_eof
;
440 if (_M_ctype
.is(_CtypeT::digit
, *_M_current
))
442 _M_curValue
+= *_M_current
;
448 else if (__c
== _M_ctype
.widen('^')
449 || __c
== _M_ctype
.widen('.')
450 || __c
== _M_ctype
.widen('*')
451 || __c
== _M_ctype
.widen('$')
452 || __c
== _M_ctype
.widen('\\'))
454 _M_curToken
= _S_token_ord_char
;
455 _M_curValue
.assign(1, __c
);
457 else if (_M_ctype
.is(_CtypeT::digit
, __c
))
459 _M_curToken
= _S_token_backref
;
460 _M_curValue
.assign(1, __c
);
463 __throw_regex_error(regex_constants::error_escape
);
467 // Eats a character class or throwns an exception.
468 // current point to ':' delimiter on entry, char after ']' on return
469 template<typename _InputIterator
>
471 _Scanner
<_InputIterator
>::
474 ++_M_current
; // skip ':'
475 if (_M_current
== _M_end
)
476 __throw_regex_error(regex_constants::error_ctype
);
477 for (_M_curValue
.clear();
478 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen(':');
480 _M_curValue
+= *_M_current
;
481 if (_M_current
== _M_end
)
482 __throw_regex_error(regex_constants::error_ctype
);
483 ++_M_current
; // skip ':'
484 if (*_M_current
!= _M_ctype
.widen(']'))
485 __throw_regex_error(regex_constants::error_ctype
);
486 ++_M_current
; // skip ']'
490 template<typename _InputIterator
>
492 _Scanner
<_InputIterator
>::
495 ++_M_current
; // skip '='
496 if (_M_current
== _M_end
)
497 __throw_regex_error(regex_constants::error_collate
);
498 for (_M_curValue
.clear();
499 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen('=');
501 _M_curValue
+= *_M_current
;
502 if (_M_current
== _M_end
)
503 __throw_regex_error(regex_constants::error_collate
);
504 ++_M_current
; // skip '='
505 if (*_M_current
!= _M_ctype
.widen(']'))
506 __throw_regex_error(regex_constants::error_collate
);
507 ++_M_current
; // skip ']'
511 template<typename _InputIterator
>
513 _Scanner
<_InputIterator
>::
516 ++_M_current
; // skip '.'
517 if (_M_current
== _M_end
)
518 __throw_regex_error(regex_constants::error_collate
);
519 for (_M_curValue
.clear();
520 _M_current
!= _M_end
&& *_M_current
!= _M_ctype
.widen('.');
522 _M_curValue
+= *_M_current
;
523 if (_M_current
== _M_end
)
524 __throw_regex_error(regex_constants::error_collate
);
525 ++_M_current
; // skip '.'
526 if (*_M_current
!= _M_ctype
.widen(']'))
527 __throw_regex_error(regex_constants::error_collate
);
528 ++_M_current
; // skip ']'
531 #ifdef _GLIBCXX_DEBUG
532 template<typename _InputIterator
>
534 _Scanner
<_InputIterator
>::
535 _M_print(std::ostream
& ostr
)
539 case _S_token_anychar
:
540 ostr
<< "any-character\n";
542 case _S_token_backref
:
545 case _S_token_bracket_begin
:
546 ostr
<< "bracket-begin\n";
548 case _S_token_bracket_end
:
549 ostr
<< "bracket-end\n";
551 case _S_token_char_class_name
:
552 ostr
<< "char-class-name \"" << _M_curValue
<< "\"\n";
554 case _S_token_closure0
:
555 ostr
<< "closure0\n";
557 case _S_token_closure1
:
558 ostr
<< "closure1\n";
560 case _S_token_collelem_multi
:
561 ostr
<< "coll-elem-multi \"" << _M_curValue
<< "\"\n";
563 case _S_token_collelem_single
:
564 ostr
<< "coll-elem-single \"" << _M_curValue
<< "\"\n";
566 case _S_token_collsymbol
:
567 ostr
<< "collsymbol \"" << _M_curValue
<< "\"\n";
575 case _S_token_dup_count
:
576 ostr
<< "dup count: " << _M_curValue
<< "\n";
581 case _S_token_equiv_class_name
:
582 ostr
<< "equiv-class-name \"" << _M_curValue
<< "\"\n";
584 case _S_token_interval_begin
:
585 ostr
<< "interval begin\n";
587 case _S_token_interval_end
:
588 ostr
<< "interval end\n";
590 case _S_token_line_begin
:
591 ostr
<< "line begin\n";
593 case _S_token_line_end
:
594 ostr
<< "line end\n";
602 case _S_token_ord_char
:
603 ostr
<< "ordinary character: \"" << _M_value() << "\"\n";
605 case _S_token_quoted_char
:
606 ostr
<< "quoted char\n";
608 case _S_token_subexpr_begin
:
609 ostr
<< "subexpr begin\n";
611 case _S_token_subexpr_end
:
612 ostr
<< "subexpr end\n";
614 case _S_token_word_begin
:
615 ostr
<< "word begin\n";
617 case _S_token_word_end
:
618 ostr
<< "word end\n";
620 case _S_token_unknown
:
621 ostr
<< "-- unknown token --\n";
628 // Builds an NFA from an input iterator interval.
629 template<typename _InIter
, typename _TraitsT
>
633 typedef _InIter _IterT
;
634 typedef typename
std::iterator_traits
<_InIter
>::value_type _CharT
;
635 typedef std::basic_string
<_CharT
> _StringT
;
636 typedef regex_constants::syntax_option_type _FlagT
;
639 _Compiler(const _InIter
& __b
, const _InIter
& __e
,
640 _TraitsT
& __traits
, _FlagT __flags
);
644 { return _M_state_store
; }
647 typedef _Scanner
<_InIter
> _ScannerT
;
648 typedef typename
_ScannerT::_TokenT _TokenT
;
649 typedef std::stack
<_StateSeq
, std::vector
<_StateSeq
> > _StackT
;
650 typedef _RangeMatcher
<_InIter
, _TraitsT
> _RMatcherT
;
652 // accepts a specific token or returns false.
654 _M_match_token(_TokenT __token
);
675 _M_bracket_expression();
678 _M_bracket_list(_RMatcherT
& __matcher
);
681 _M_follow_list(_RMatcherT
& __matcher
);
684 _M_follow_list2(_RMatcherT
& __matcher
);
687 _M_expression_term(_RMatcherT
& __matcher
);
690 _M_range_expression(_RMatcherT
& __matcher
);
693 _M_start_range(_RMatcherT
& __matcher
);
696 _M_collating_symbol(_RMatcherT
& __matcher
);
699 _M_equivalence_class(_RMatcherT
& __matcher
);
702 _M_character_class(_RMatcherT
& __matcher
);
705 _M_cur_int_value(int __radix
);
709 _ScannerT _M_scanner
;
710 _StringT _M_cur_value
;
715 template<typename _InIter
, typename _TraitsT
>
716 _Compiler
<_InIter
, _TraitsT
>::
717 _Compiler(const _InIter
& __b
, const _InIter
& __e
, _TraitsT
& __traits
,
718 _Compiler
<_InIter
, _TraitsT
>::_FlagT __flags
)
719 : _M_traits(__traits
), _M_scanner(__b
, __e
, __flags
, _M_traits
.getloc()),
720 _M_state_store(__flags
)
722 typedef _StartTagger
<_InIter
, _TraitsT
> _Start
;
723 typedef _EndTagger
<_InIter
, _TraitsT
> _End
;
725 _StateSeq
__r(_M_state_store
,
726 _M_state_store
._M_insert_subexpr_begin(_Start(0)));
728 if (!_M_stack
.empty())
730 __r
._M_append(_M_stack
.top());
733 __r
._M_append(_M_state_store
._M_insert_subexpr_end(0, _End(0)));
734 __r
._M_append(_M_state_store
._M_insert_accept());
737 template<typename _InIter
, typename _TraitsT
>
739 _Compiler
<_InIter
, _TraitsT
>::
740 _M_match_token(_Compiler
<_InIter
, _TraitsT
>::_TokenT token
)
742 if (token
== _M_scanner
._M_token())
744 _M_cur_value
= _M_scanner
._M_value();
745 _M_scanner
._M_advance();
751 template<typename _InIter
, typename _TraitsT
>
753 _Compiler
<_InIter
, _TraitsT
>::
756 this->_M_alternative();
757 if (_M_match_token(_ScannerT::_S_token_or
))
759 _StateSeq __alt1
= _M_stack
.top(); _M_stack
.pop();
760 this->_M_disjunction();
761 _StateSeq __alt2
= _M_stack
.top(); _M_stack
.pop();
762 _M_stack
.push(_StateSeq(__alt1
, __alt2
));
766 template<typename _InIter
, typename _TraitsT
>
768 _Compiler
<_InIter
, _TraitsT
>::
773 _StateSeq __re
= _M_stack
.top(); _M_stack
.pop();
774 this->_M_alternative();
775 if (!_M_stack
.empty())
777 __re
._M_append(_M_stack
.top());
786 template<typename _InIter
, typename _TraitsT
>
788 _Compiler
<_InIter
, _TraitsT
>::
791 if (this->_M_assertion())
795 this->_M_quantifier();
801 template<typename _InIter
, typename _TraitsT
>
803 _Compiler
<_InIter
, _TraitsT
>::
806 if (_M_match_token(_ScannerT::_S_token_line_begin
))
808 // __m.push(_Matcher::_S_opcode_line_begin);
811 if (_M_match_token(_ScannerT::_S_token_line_end
))
813 // __m.push(_Matcher::_S_opcode_line_end);
816 if (_M_match_token(_ScannerT::_S_token_word_begin
))
818 // __m.push(_Matcher::_S_opcode_word_begin);
821 if (_M_match_token(_ScannerT::_S_token_word_end
))
823 // __m.push(_Matcher::_S_opcode_word_end);
829 template<typename _InIter
, typename _TraitsT
>
831 _Compiler
<_InIter
, _TraitsT
>::
834 if (_M_match_token(_ScannerT::_S_token_closure0
))
836 if (_M_stack
.empty())
837 __throw_regex_error(regex_constants::error_badrepeat
);
838 _StateSeq
__r(_M_stack
.top(), -1);
839 __r
._M_append(__r
._M_front());
844 if (_M_match_token(_ScannerT::_S_token_closure1
))
846 if (_M_stack
.empty())
847 __throw_regex_error(regex_constants::error_badrepeat
);
848 _StateSeq
__r(_M_state_store
,
850 _M_insert_alt(_S_invalid_state_id
,
851 _M_stack
.top()._M_front()));
852 _M_stack
.top()._M_append(__r
);
855 if (_M_match_token(_ScannerT::_S_token_opt
))
857 if (_M_stack
.empty())
858 __throw_regex_error(regex_constants::error_badrepeat
);
859 _StateSeq
__r(_M_stack
.top(), -1);
864 if (_M_match_token(_ScannerT::_S_token_interval_begin
))
866 if (_M_stack
.empty())
867 __throw_regex_error(regex_constants::error_badrepeat
);
868 if (!_M_match_token(_ScannerT::_S_token_dup_count
))
869 __throw_regex_error(regex_constants::error_badbrace
);
870 _StateSeq
__r(_M_stack
.top());
871 int __min_rep
= _M_cur_int_value(10);
872 for (int __i
= 1; __i
< __min_rep
; ++__i
)
873 _M_stack
.top()._M_append(__r
._M_clone());
874 if (_M_match_token(_ScannerT::_S_token_comma
))
875 if (_M_match_token(_ScannerT::_S_token_dup_count
))
877 int __n
= _M_cur_int_value(10) - __min_rep
;
879 __throw_regex_error(regex_constants::error_badbrace
);
880 for (int __i
= 0; __i
< __n
; ++__i
)
882 _StateSeq
__r(_M_state_store
,
884 _M_insert_alt(_S_invalid_state_id
,
885 _M_stack
.top()._M_front()));
886 _M_stack
.top()._M_append(__r
);
891 _StateSeq
__r(_M_stack
.top(), -1);
892 __r
._M_push_back(__r
._M_front());
896 if (!_M_match_token(_ScannerT::_S_token_interval_end
))
897 __throw_regex_error(regex_constants::error_brace
);
903 template<typename _InIter
, typename _TraitsT
>
905 _Compiler
<_InIter
, _TraitsT
>::
908 typedef _CharMatcher
<_InIter
, _TraitsT
> _CMatcher
;
909 typedef _StartTagger
<_InIter
, _TraitsT
> _Start
;
910 typedef _EndTagger
<_InIter
, _TraitsT
> _End
;
912 if (_M_match_token(_ScannerT::_S_token_anychar
))
914 _M_stack
.push(_StateSeq(_M_state_store
,
915 _M_state_store
._M_insert_matcher
919 if (_M_match_token(_ScannerT::_S_token_ord_char
))
921 _M_stack
.push(_StateSeq(_M_state_store
,
922 _M_state_store
._M_insert_matcher
923 (_CMatcher(_M_cur_value
[0], _M_traits
))));
926 if (_M_match_token(_ScannerT::_S_token_quoted_char
))
928 // note that in the ECMA grammar, this case covers backrefs.
929 _M_stack
.push(_StateSeq(_M_state_store
,
930 _M_state_store
._M_insert_matcher
931 (_CMatcher(_M_cur_value
[0], _M_traits
))));
934 if (_M_match_token(_ScannerT::_S_token_backref
))
936 // __m.push(_Matcher::_S_opcode_ordchar, _M_cur_value);
939 if (_M_match_token(_ScannerT::_S_token_subexpr_begin
))
941 int __mark
= _M_state_store
._M_sub_count();
942 _StateSeq
__r(_M_state_store
,
944 _M_insert_subexpr_begin(_Start(__mark
)));
945 this->_M_disjunction();
946 if (!_M_match_token(_ScannerT::_S_token_subexpr_end
))
947 __throw_regex_error(regex_constants::error_paren
);
948 if (!_M_stack
.empty())
950 __r
._M_append(_M_stack
.top());
953 __r
._M_append(_M_state_store
._M_insert_subexpr_end
954 (__mark
, _End(__mark
)));
958 return _M_bracket_expression();
961 template<typename _InIter
, typename _TraitsT
>
963 _Compiler
<_InIter
, _TraitsT
>::
964 _M_bracket_expression()
966 if (_M_match_token(_ScannerT::_S_token_bracket_begin
))
968 _RMatcherT
__matcher(_M_match_token(_ScannerT::_S_token_line_begin
),
970 if (!_M_bracket_list(__matcher
)
971 || !_M_match_token(_ScannerT::_S_token_bracket_end
))
972 __throw_regex_error(regex_constants::error_brack
);
973 _M_stack
.push(_StateSeq(_M_state_store
,
974 _M_state_store
._M_insert_matcher(__matcher
)));
980 // If the dash is the last character in the bracket expression, it is not
982 template<typename _InIter
, typename _TraitsT
>
984 _Compiler
<_InIter
, _TraitsT
>::
985 _M_bracket_list(_RMatcherT
& __matcher
)
987 if (_M_follow_list(__matcher
))
989 if (_M_match_token(_ScannerT::_S_token_dash
))
990 __matcher
._M_add_char(_M_cur_value
[0]);
996 template<typename _InIter
, typename _TraitsT
>
998 _Compiler
<_InIter
, _TraitsT
>::
999 _M_follow_list(_RMatcherT
& __matcher
)
1000 { return _M_expression_term(__matcher
) && _M_follow_list2(__matcher
); }
1002 template<typename _InIter
, typename _TraitsT
>
1004 _Compiler
<_InIter
, _TraitsT
>::
1005 _M_follow_list2(_RMatcherT
& __matcher
)
1007 if (_M_expression_term(__matcher
))
1008 return _M_follow_list2(__matcher
);
1012 template<typename _InIter
, typename _TraitsT
>
1014 _Compiler
<_InIter
, _TraitsT
>::
1015 _M_expression_term(_RMatcherT
& __matcher
)
1017 return (_M_collating_symbol(__matcher
)
1018 || _M_character_class(__matcher
)
1019 || _M_equivalence_class(__matcher
)
1020 || (_M_start_range(__matcher
)
1021 && _M_range_expression(__matcher
)));
1024 template<typename _InIter
, typename _TraitsT
>
1026 _Compiler
<_InIter
, _TraitsT
>::
1027 _M_range_expression(_RMatcherT
& __matcher
)
1029 if (!_M_collating_symbol(__matcher
))
1030 if (!_M_match_token(_ScannerT::_S_token_dash
))
1031 __throw_regex_error(regex_constants::error_range
);
1032 __matcher
._M_make_range();
1036 template<typename _InIter
, typename _TraitsT
>
1038 _Compiler
<_InIter
, _TraitsT
>::
1039 _M_start_range(_RMatcherT
& __matcher
)
1040 { return _M_match_token(_ScannerT::_S_token_dash
); }
1042 template<typename _InIter
, typename _TraitsT
>
1044 _Compiler
<_InIter
, _TraitsT
>::
1045 _M_collating_symbol(_RMatcherT
& __matcher
)
1047 if (_M_match_token(_ScannerT::_S_token_collelem_single
))
1049 __matcher
._M_add_char(_M_cur_value
[0]);
1052 if (_M_match_token(_ScannerT::_S_token_collsymbol
))
1054 __matcher
._M_add_collating_element(_M_cur_value
);
1060 template<typename _InIter
, typename _TraitsT
>
1062 _Compiler
<_InIter
, _TraitsT
>::
1063 _M_equivalence_class(_RMatcherT
& __matcher
)
1065 if (_M_match_token(_ScannerT::_S_token_equiv_class_name
))
1067 __matcher
._M_add_equivalence_class(_M_cur_value
);
1073 template<typename _InIter
, typename _TraitsT
>
1075 _Compiler
<_InIter
, _TraitsT
>::
1076 _M_character_class(_RMatcherT
& __matcher
)
1078 if (_M_match_token(_ScannerT::_S_token_char_class_name
))
1080 __matcher
._M_add_character_class(_M_cur_value
);
1086 template<typename _InIter
, typename _TraitsT
>
1088 _Compiler
<_InIter
, _TraitsT
>::
1089 _M_cur_int_value(int __radix
)
1092 for (typename
_StringT::size_type __i
= 0;
1093 __i
< _M_cur_value
.length(); ++__i
)
1094 __v
=__v
* __radix
+ _M_traits
.value(_M_cur_value
[__i
], __radix
);
1098 template<typename _InIter
, typename _TraitsT
>
1100 __compile(const _InIter
& __b
, const _InIter
& __e
, _TraitsT
& __t
,
1101 regex_constants::syntax_option_type __f
)
1102 { return _AutomatonPtr(new _Nfa(_Compiler
<_InIter
, _TraitsT
>(__b
, __e
, __t
,
1105 _GLIBCXX_END_NAMESPACE_VERSION
1106 } // namespace __regex
1109 /* vim: set ts=8 sw=2 sts=2: */