OSDN Git Service

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