libstdc++
regex_grep_matcher.tcc
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