regex_executor.h 7.31 KB
Newer Older
1 2
// class template regex -*- C++ -*-

3
// Copyright (C) 2013-2017 Free Software Foundation, Inc.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
//
// 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_executor.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{regex}
 */

Tim Shen committed
31 32
// FIXME convert comments to doxygen format.

33 34 35 36 37 38 39 40 41 42 43
namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __detail
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @addtogroup regex-detail
   * @{
   */

Tim Shen committed
44
  /**
45
   * @brief Takes a regex and an input string and does the matching.
Tim Shen committed
46 47 48 49
   *
   * The %_Executor class has two modes: DFS mode and BFS mode, controlled
   * by the template parameter %__dfs_mode.
   */
50
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
51
	   bool __dfs_mode>
52 53
    class _Executor
    {
54 55 56 57 58 59
      using __search_mode = integral_constant<bool, __dfs_mode>;
      using __dfs = true_type;
      using __bfs = false_type;

      enum class _Match_mode : unsigned char { _Exact, _Prefix };

60
    public:
61 62 63 64 65
      typedef typename iterator_traits<_BiIter>::value_type _CharT;
      typedef basic_regex<_CharT, _TraitsT>                 _RegexT;
      typedef std::vector<sub_match<_BiIter>, _Alloc>       _ResultsVec;
      typedef regex_constants::match_flag_type              _FlagT;
      typedef typename _TraitsT::char_class_type            _ClassT;
66
      typedef _NFA<_TraitsT>                                _NFAT;
67

Tim Shen committed
68 69 70
    public:
      _Executor(_BiIter         __begin,
		_BiIter         __end,
Tim Shen committed
71
		_ResultsVec&    __results,
Tim Shen committed
72 73 74 75 76
		const _RegexT&  __re,
		_FlagT          __flags)
      : _M_begin(__begin),
      _M_end(__end),
      _M_re(__re),
77
      _M_nfa(*__re._M_automaton),
78
      _M_results(__results),
79
      _M_rep_count(_M_nfa.size()),
80
      _M_states(_M_nfa._M_start(), _M_nfa.size()),
Tim Shen committed
81 82 83 84
      _M_flags((__flags & regex_constants::match_prev_avail)
	       ? (__flags
		  & ~regex_constants::match_not_bol
		  & ~regex_constants::match_not_bow)
85
	       : __flags)
86 87
      { }

88
      // Set matched when string exactly matches the pattern.
Tim Shen committed
89 90 91
      bool
      _M_match()
      {
92
	_M_current = _M_begin;
93
	return _M_main(_Match_mode::_Exact);
Tim Shen committed
94
      }
95 96

      // Set matched when some prefix of the string matches the pattern.
Tim Shen committed
97 98 99
      bool
      _M_search_from_first()
      {
100
	_M_current = _M_begin;
101
	return _M_main(_Match_mode::_Prefix);
Tim Shen committed
102
      }
103

Tim Shen committed
104
      bool
105
      _M_search();
106

107
    private:
108 109
      void
      _M_rep_once_more(_Match_mode __match_mode, _StateIdT);
110

111
      void
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
      _M_handle_repeat(_Match_mode, _StateIdT);

      void
      _M_handle_subexpr_begin(_Match_mode, _StateIdT);

      void
      _M_handle_subexpr_end(_Match_mode, _StateIdT);

      void
      _M_handle_line_begin_assertion(_Match_mode, _StateIdT);

      void
      _M_handle_line_end_assertion(_Match_mode, _StateIdT);

      void
      _M_handle_word_boundary(_Match_mode, _StateIdT);

      void
      _M_handle_subexpr_lookahead(_Match_mode, _StateIdT);

      void
      _M_handle_match(_Match_mode, _StateIdT);

      void
      _M_handle_backref(_Match_mode, _StateIdT);

      void
      _M_handle_accept(_Match_mode, _StateIdT);

      void
      _M_handle_alternative(_Match_mode, _StateIdT);

      void
145
      _M_dfs(_Match_mode __match_mode, _StateIdT __start);
146

147 148 149 150 151 152 153 154 155
      bool
      _M_main(_Match_mode __match_mode)
      { return _M_main_dispatch(__match_mode, __search_mode{}); }

      bool
      _M_main_dispatch(_Match_mode __match_mode, __dfs);

      bool
      _M_main_dispatch(_Match_mode __match_mode, __bfs);
156

157
      bool
Tim Shen committed
158
      _M_is_word(_CharT __ch) const
159
      {
160
	static const _CharT __s[2] = { 'w' };
161 162
	return _M_re._M_automaton->_M_traits.isctype
	  (__ch, _M_re._M_automaton->_M_traits.lookup_classname(__s, __s+1));
Tim Shen committed
163 164 165 166 167 168 169 170
      }

      bool
      _M_at_begin() const
      {
	return _M_current == _M_begin
	  && !(_M_flags & (regex_constants::match_not_bol
			   | regex_constants::match_prev_avail));
171 172
      }

Tim Shen committed
173 174 175 176 177 178 179 180
      bool
      _M_at_end() const
      {
	return _M_current == _M_end
	  && !(_M_flags & regex_constants::match_not_eol);
      }

      bool
181
      _M_word_boundary() const;
Tim Shen committed
182 183

      bool
184
      _M_lookahead(_StateIdT __next);
185

186 187 188 189 190 191 192 193 194
       // Holds additional information used in BFS-mode.
      template<typename _SearchMode, typename _ResultsVec>
	struct _State_info;

      template<typename _ResultsVec>
	struct _State_info<__bfs, _ResultsVec>
	{
	  explicit
	  _State_info(_StateIdT __start, size_t __n)
195
	  : _M_visited_states(new bool[__n]()), _M_start(__start)
196 197 198 199 200 201 202 203 204 205 206 207 208
	  { }

	  bool _M_visited(_StateIdT __i)
	  {
	    if (_M_visited_states[__i])
	      return true;
	    _M_visited_states[__i] = true;
	    return false;
	  }

	  void _M_queue(_StateIdT __i, const _ResultsVec& __res)
	  { _M_match_queue.emplace_back(__i, __res); }

209 210 211
	  // Dummy implementations for BFS mode.
	  _BiIter* _M_get_sol_pos() { return nullptr; }

212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
	  // Saves states that need to be considered for the next character.
	  vector<pair<_StateIdT, _ResultsVec>>	_M_match_queue;
	  // Indicates which states are already visited.
	  unique_ptr<bool[]>			_M_visited_states;
	  // To record current solution.
	  _StateIdT _M_start;
	};

      template<typename _ResultsVec>
	struct _State_info<__dfs, _ResultsVec>
	{
	  explicit
	  _State_info(_StateIdT __start, size_t) : _M_start(__start)
	  { }

	  // Dummy implementations for DFS mode.
	  bool _M_visited(_StateIdT) const { return false; }
	  void _M_queue(_StateIdT, const _ResultsVec&) { }

231 232
	  _BiIter* _M_get_sol_pos() { return &_M_sol_pos; }

233 234
	  // To record current solution.
	  _StateIdT _M_start;
235
	  _BiIter   _M_sol_pos;
236 237
	};

Tim Shen committed
238
    public:
239 240
      _ResultsVec                                           _M_cur_results;
      _BiIter                                               _M_current;
241
      _BiIter                                               _M_begin;
242 243 244 245
      const _BiIter                                         _M_end;
      const _RegexT&                                        _M_re;
      const _NFAT&                                          _M_nfa;
      _ResultsVec&                                          _M_results;
246
      vector<pair<_BiIter, int>>                            _M_rep_count;
247
      _State_info<__search_mode, _ResultsVec>		    _M_states;
248
      _FlagT                                                _M_flags;
249
      // Do we have a solution so far?
250
      bool                                                  _M_has_sol;
251 252 253 254 255 256 257 258
    };

 //@} regex-detail
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
} // namespace std

#include <bits/regex_executor.tcc>