1 // class template regex -*- C++ -*- 2 3 // Copyright (C) 2010-2013 Free Software Foundation, Inc. 4 // 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) 9 // any later version. 10 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. 15 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. 19 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/>. 24 25 /** 26 * @file bits/regex_grep_matcher.tcc 27 * This is an internal header file, included by other library headers. 28 * Do not attempt to use it directly. @headername{regex} 29 */ 30 31 #include <regex> 32 33 namespace std _GLIBCXX_VISIBILITY(default) 34 { 35 namespace 36 { 37 // A stack of states used in evaluating the NFA. 38 typedef std::stack<std::__detail::_StateIdT, 39 std::vector<std::__detail::_StateIdT> 40 > _StateStack; 41 42 // Obtains the next state set given the current state set __s and the current 43 // input character. 44 inline std::__detail::_StateSet 45 __move(const std::__detail::_PatternCursor& __p, 46 const std::__detail::_Nfa& __nfa, 47 const std::__detail::_StateSet& __s) 48 { 49 std::__detail::_StateSet __m; 50 for (std::__detail::_StateSet::const_iterator __i = __s.begin(); 51 __i != __s.end(); ++__i) 52 { 53 if (*__i == std::__detail::_S_invalid_state_id) 54 continue; 55 56 const std::__detail::_State& __state = __nfa[*__i]; 57 if (__state._M_opcode == std::__detail::_S_opcode_match 58 && __state._M_matches(__p)) 59 __m.insert(__state._M_next); 60 } 61 return __m; 62 } 63 64 // returns true if (__s intersect __t) is not empty 65 inline bool 66 __includes_some(const std::__detail::_StateSet& __s, 67 const std::__detail::_StateSet& __t) 68 { 69 if (__s.size() > 0 && __t.size() > 0) 70 { 71 std::__detail::_StateSet::const_iterator __first = __s.begin(); 72 std::__detail::_StateSet::const_iterator __second = __t.begin(); 73 while (__first != __s.end() && __second != __t.end()) 74 { 75 if (*__first < *__second) 76 ++__first; 77 else if (*__second < *__first) 78 ++__second; 79 else 80 return true; 81 } 82 } 83 return false; 84 } 85 86 // If an identified state __u is not already in the current state set __e, 87 // insert it and push it on the current state stack __s. 88 inline void 89 __add_visited_state(const std::__detail::_StateIdT __u, 90 _StateStack& __s, 91 std::__detail::_StateSet& __e) 92 { 93 if (__e.count(__u) == 0) 94 { 95 __e.insert(__u); 96 __s.push(__u); 97 } 98 } 99 100 } // anonymous namespace 101 102 namespace __detail 103 { 104 _GLIBCXX_BEGIN_NAMESPACE_VERSION 105 106 inline _Grep_matcher:: 107 _Grep_matcher(_PatternCursor& __p, _Results& __r, 108 const _AutomatonPtr& __nfa, 109 regex_constants::match_flag_type __flags) 110 : _M_nfa(static_pointer_cast<_Nfa>(__nfa)), _M_pattern(__p), _M_results(__r) 111 { 112 __detail::_StateSet __t = this->_M_e_closure(_M_nfa->_M_start()); 113 for (; !_M_pattern._M_at_end(); _M_pattern._M_next()) 114 __t = this->_M_e_closure(__move(_M_pattern, *_M_nfa, __t)); 115 116 _M_results._M_set_matched(0, 117 __includes_some(_M_nfa->_M_final_states(), __t)); 118 } 119 120 // Creates the e-closure set for the initial state __i. 121 inline _StateSet _Grep_matcher:: 122 _M_e_closure(_StateIdT __i) 123 { 124 _StateSet __s; 125 __s.insert(__i); 126 _StateStack __stack; 127 __stack.push(__i); 128 return this->_M_e_closure(__stack, __s); 129 } 130 131 // Creates the e-closure set for an arbitrary state set __s. 132 inline _StateSet _Grep_matcher:: 133 _M_e_closure(const _StateSet& __s) 134 { 135 _StateStack __stack; 136 for (_StateSet::const_iterator __i = __s.begin(); __i != __s.end(); ++__i) 137 __stack.push(*__i); 138 return this->_M_e_closure(__stack, __s); 139 } 140 141 inline _StateSet _Grep_matcher:: 142 _M_e_closure(_StateStack& __stack, const _StateSet& __s) 143 { 144 _StateSet __e = __s; 145 while (!__stack.empty()) 146 { 147 _StateIdT __t = __stack.top(); __stack.pop(); 148 if (__t == _S_invalid_state_id) 149 continue; 150 // for each __u with edge from __t to __u labeled e do ... 151 const _State& __state = _M_nfa->operator[](__t); 152 switch (__state._M_opcode) 153 { 154 case _S_opcode_alternative: 155 __add_visited_state(__state._M_next, __stack, __e); 156 __add_visited_state(__state._M_alt, __stack, __e); 157 break; 158 case _S_opcode_subexpr_begin: 159 __add_visited_state(__state._M_next, __stack, __e); 160 __state._M_tagger(_M_pattern, _M_results); 161 break; 162 case _S_opcode_subexpr_end: 163 __add_visited_state(__state._M_next, __stack, __e); 164 __state._M_tagger(_M_pattern, _M_results); 165 _M_results._M_set_matched(__state._M_subexpr, true); 166 break; 167 case _S_opcode_accept: 168 __add_visited_state(__state._M_next, __stack, __e); 169 break; 170 default: 171 break; 172 } 173 } 174 return __e; 175 } 176 177 _GLIBCXX_END_NAMESPACE_VERSION 178 } // namespace __detail 179 } // namespace 180