| // class template regex -*- C++ -*- |
| |
| // Copyright (C) 2010 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // Under Section 7 of GPL version 3, you are granted additional |
| // permissions described in the GCC Runtime Library Exception, version |
| // 3.1, as published by the Free Software Foundation. |
| |
| // You should have received a copy of the GNU General Public License and |
| // a copy of the GCC Runtime Library Exception along with this program; |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| // <http://www.gnu.org/licenses/>. |
| |
| /** |
| * @file bits/regex_grep_matcher.tcc |
| * This is an internal header file, included by other library headers. |
| * Do not attempt to use it directly. @headername{regex} |
| */ |
| |
| #include <regex> |
| |
| namespace std _GLIBCXX_VISIBILITY(default) |
| { |
| namespace |
| { |
| // A stack of states used in evaluating the NFA. |
| typedef std::stack<std::__regex::_StateIdT, |
| std::vector<std::__regex::_StateIdT> |
| > _StateStack; |
| |
| // Obtains the next state set given the current state set __s and the current |
| // input character. |
| inline std::__regex::_StateSet |
| __move(const std::__regex::_PatternCursor& __p, |
| const std::__regex::_Nfa& __nfa, |
| const std::__regex::_StateSet& __s) |
| { |
| std::__regex::_StateSet __m; |
| for (std::__regex::_StateSet::const_iterator __i = __s.begin(); |
| __i != __s.end(); ++__i) |
| { |
| if (*__i == std::__regex::_S_invalid_state_id) |
| continue; |
| |
| const std::__regex::_State& __state = __nfa[*__i]; |
| if (__state._M_opcode == std::__regex::_S_opcode_match |
| && __state._M_matches(__p)) |
| __m.insert(__state._M_next); |
| } |
| return __m; |
| } |
| |
| // returns true if (__s intersect __t) is not empty |
| inline bool |
| __includes_some(const std::__regex::_StateSet& __s, |
| const std::__regex::_StateSet& __t) |
| { |
| if (__s.size() > 0 && __t.size() > 0) |
| { |
| std::__regex::_StateSet::const_iterator __first = __s.begin(); |
| std::__regex::_StateSet::const_iterator __second = __t.begin(); |
| while (__first != __s.end() && __second != __t.end()) |
| { |
| if (*__first < *__second) |
| ++__first; |
| else if (*__second < *__first) |
| ++__second; |
| else |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| // If an identified state __u is not already in the current state set __e, |
| // insert it and push it on the current state stack __s. |
| inline void |
| __add_visited_state(const std::__regex::_StateIdT __u, |
| _StateStack& __s, |
| std::__regex::_StateSet& __e) |
| { |
| if (__e.count(__u) == 0) |
| { |
| __e.insert(__u); |
| __s.push(__u); |
| } |
| } |
| |
| } // anonymous namespace |
| |
| namespace __regex |
| { |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION |
| |
| inline _Grep_matcher:: |
| _Grep_matcher(_PatternCursor& __p, _Results& __r, |
| const _AutomatonPtr& __nfa, |
| regex_constants::match_flag_type __flags) |
| : _M_nfa(static_pointer_cast<_Nfa>(__nfa)), _M_pattern(__p), _M_results(__r) |
| { |
| __regex::_StateSet __t = this->_M_e_closure(_M_nfa->_M_start()); |
| for (; !_M_pattern._M_at_end(); _M_pattern._M_next()) |
| __t = this->_M_e_closure(__move(_M_pattern, *_M_nfa, __t)); |
| |
| _M_results._M_set_matched(0, |
| __includes_some(_M_nfa->_M_final_states(), __t)); |
| } |
| |
| // Creates the e-closure set for the initial state __i. |
| inline _StateSet _Grep_matcher:: |
| _M_e_closure(_StateIdT __i) |
| { |
| _StateSet __s; |
| __s.insert(__i); |
| _StateStack __stack; |
| __stack.push(__i); |
| return this->_M_e_closure(__stack, __s); |
| } |
| |
| // Creates the e-closure set for an arbitrary state set __s. |
| inline _StateSet _Grep_matcher:: |
| _M_e_closure(const _StateSet& __s) |
| { |
| _StateStack __stack; |
| for (_StateSet::const_iterator __i = __s.begin(); __i != __s.end(); ++__i) |
| __stack.push(*__i); |
| return this->_M_e_closure(__stack, __s); |
| } |
| |
| inline _StateSet _Grep_matcher:: |
| _M_e_closure(_StateStack& __stack, const _StateSet& __s) |
| { |
| _StateSet __e = __s; |
| while (!__stack.empty()) |
| { |
| _StateIdT __t = __stack.top(); __stack.pop(); |
| if (__t == _S_invalid_state_id) |
| continue; |
| // for each __u with edge from __t to __u labeled e do ... |
| const _State& __state = _M_nfa->operator[](__t); |
| switch (__state._M_opcode) |
| { |
| case _S_opcode_alternative: |
| __add_visited_state(__state._M_next, __stack, __e); |
| __add_visited_state(__state._M_alt, __stack, __e); |
| break; |
| case _S_opcode_subexpr_begin: |
| __add_visited_state(__state._M_next, __stack, __e); |
| __state._M_tagger(_M_pattern, _M_results); |
| break; |
| case _S_opcode_subexpr_end: |
| __add_visited_state(__state._M_next, __stack, __e); |
| __state._M_tagger(_M_pattern, _M_results); |
| _M_results._M_set_matched(__state._M_subexpr, true); |
| break; |
| case _S_opcode_accept: |
| __add_visited_state(__state._M_next, __stack, __e); |
| break; |
| default: |
| break; |
| } |
| } |
| return __e; |
| } |
| |
| _GLIBCXX_END_NAMESPACE_VERSION |
| } // namespace __regex |
| } // namespace |