regex_executor.tcc 16.9 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 31 32 33 34 35 36
//
// 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.tcc
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{regex}
 */

namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __detail
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

37
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
38
	   bool __dfs_mode>
39
    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
40 41
    _M_search()
    {
42 43
      if (_M_search_from_first())
	return true;
44
      if (_M_flags & regex_constants::match_continuous)
45 46 47
	return false;
      _M_flags |= regex_constants::match_prev_avail;
      while (_M_begin != _M_end)
48
	{
49 50
	  ++_M_begin;
	  if (_M_search_from_first())
51 52 53 54 55
	    return true;
	}
      return false;
    }

56 57 58
  // The _M_main function operates in different modes, DFS mode or BFS mode,
  // indicated by template parameter __dfs_mode, and dispatches to one of the
  // _M_main_dispatch overloads.
59 60 61 62 63 64 65
  //
  // ------------------------------------------------------------
  //
  // DFS mode:
  //
  // It applies a Depth-First-Search (aka backtracking) on given NFA and input
  // string.
66 67 68
  // At the very beginning the executor stands in the start state, then it
  // tries every possible state transition in current state recursively. Some
  // state transitions consume input string, say, a single-char-matcher or a
69
  // back-reference matcher; some don't, like assertion or other anchor nodes.
70 71
  // When the input is exhausted and/or the current state is an accepting
  // state, the whole executor returns true.
72 73 74 75
  //
  // TODO: This approach is exponentially slow for certain input.
  //       Try to compile the NFA to a DFA.
  //
Tim Shen committed
76
  // Time complexity: \Omega(match_length), O(2^(_M_nfa.size()))
77 78
  // Space complexity: \theta(match_results.size() + match_length)
  //
79 80 81 82 83 84
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_main_dispatch(_Match_mode __match_mode, __dfs)
    {
      _M_has_sol = false;
85
      *_M_states._M_get_sol_pos() = _BiIter();
86 87 88 89 90
      _M_cur_results = _M_results;
      _M_dfs(__match_mode, _M_states._M_start);
      return _M_has_sol;
    }

91 92 93 94 95 96 97
  // ------------------------------------------------------------
  //
  // BFS mode:
  //
  // Russ Cox's article (http://swtch.com/~rsc/regexp/regexp1.html)
  // explained this algorithm clearly.
  //
Tim Shen committed
98 99
  // It first computes epsilon closure (states that can be achieved without
  // consuming characters) for every state that's still matching,
100 101
  // using the same DFS algorithm, but doesn't re-enter states (using
  // _M_states._M_visited to check), nor follow _S_opcode_match.
102
  //
103 104
  // Then apply DFS using every _S_opcode_match (in _M_states._M_match_queue)
  // as the start state.
105 106 107 108
  //
  // It significantly reduces potential duplicate states, so has a better
  // upper bound; but it requires more overhead.
  //
Tim Shen committed
109
  // Time complexity: \Omega(match_length * match_results.size())
110
  //                  O(match_length * _M_nfa.size() * match_results.size())
Tim Shen committed
111
  // Space complexity: \Omega(_M_nfa.size() + match_results.size())
112
  //                   O(_M_nfa.size() * match_results.size())
113
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
114
	   bool __dfs_mode>
115
    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
116
    _M_main_dispatch(_Match_mode __match_mode, __bfs)
117
    {
118 119 120
      _M_states._M_queue(_M_states._M_start, _M_results);
      bool __ret = false;
      while (1)
121 122
	{
	  _M_has_sol = false;
123 124 125 126 127
	  if (_M_states._M_match_queue.empty())
	    break;
	  std::fill_n(_M_states._M_visited_states.get(), _M_nfa.size(), false);
	  auto __old_queue = std::move(_M_states._M_match_queue);
	  for (auto& __task : __old_queue)
128
	    {
129 130
	      _M_cur_results = std::move(__task.second);
	      _M_dfs(__match_mode, __task.first);
131
	    }
132 133 134 135 136
	  if (__match_mode == _Match_mode::_Prefix)
	    __ret |= _M_has_sol;
	  if (_M_current == _M_end)
	    break;
	  ++_M_current;
137
	}
138 139
      if (__match_mode == _Match_mode::_Exact)
	__ret = _M_has_sol;
140
      _M_states._M_match_queue.clear();
141
      return __ret;
142 143 144 145
    }

  // Return whether now match the given sub-NFA.
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
146
	   bool __dfs_mode>
147
    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
148
    _M_lookahead(_StateIdT __next)
149
    {
150 151 152 153
      // Backreferences may refer to captured content.
      // We may want to make this faster by not copying,
      // but let's not be clever prematurely.
      _ResultsVec __what(_M_cur_results);
154
      _Executor __sub(_M_current, _M_end, __what, _M_re, _M_flags);
155
      __sub._M_states._M_start = __next;
156
      if (__sub._M_search_from_first())
157 158 159 160 161 162 163 164 165
	{
	  for (size_t __i = 0; __i < __what.size(); __i++)
	    if (__what[__i].matched)
	      _M_cur_results[__i] = __what[__i];
	  return true;
	}
      return false;
    }

166 167 168 169 170 171 172 173 174
  // __rep_count records how many times (__rep_count.second)
  // this node is visited under certain input iterator
  // (__rep_count.first). This prevent the executor from entering
  // infinite loop by refusing to continue when it's already been
  // visited more than twice. It's `twice` instead of `once` because
  // we need to spare one more time for potential group capture.
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
    bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
175
    _M_rep_once_more(_Match_mode __match_mode, _StateIdT __i)
176 177 178 179 180 181 182 183
    {
      const auto& __state = _M_nfa[__i];
      auto& __rep_count = _M_rep_count[__i];
      if (__rep_count.second == 0 || __rep_count.first != _M_current)
	{
	  auto __back = __rep_count;
	  __rep_count.first = _M_current;
	  __rep_count.second = 1;
184
	  _M_dfs(__match_mode, __state._M_alt);
185 186 187 188 189 190 191
	  __rep_count = __back;
	}
      else
	{
	  if (__rep_count.second < 2)
	    {
	      __rep_count.second++;
192
	      _M_dfs(__match_mode, __state._M_alt);
193 194 195 196 197
	      __rep_count.second--;
	    }
	}
    };

198 199 200 201
  // _M_alt branch is "match once more", while _M_next is "get me out
  // of this quantifier". Executing _M_next first or _M_alt first don't
  // mean the same thing, and we need to choose the correct order under
  // given greedy mode.
202
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
203
	   bool __dfs_mode>
204
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
205
    _M_handle_repeat(_Match_mode __match_mode, _StateIdT __i)
206
    {
207
      const auto& __state = _M_nfa[__i];
208 209 210

      // Greedy.
      if (!__state._M_neg)
211
	{
212 213 214
	  _M_rep_once_more(__match_mode, __i);
	  // If it's DFS executor and already accepted, we're done.
	  if (!__dfs_mode || !_M_has_sol)
215
	    _M_dfs(__match_mode, __state._M_next);
216 217 218
	}
      else // Non-greedy mode
	{
219
	  if (__dfs_mode)
220
	    {
221 222 223 224
	      // vice-versa.
	      _M_dfs(__match_mode, __state._M_next);
	      if (!_M_has_sol)
		_M_rep_once_more(__match_mode, __i);
225
	    }
226
	  else
227
	    {
228 229 230 231
	      // DON'T attempt anything, because there's already another
	      // state with higher priority accepted. This state cannot
	      // be better by attempting its next node.
	      if (!_M_has_sol)
232
		{
233 234 235 236 237 238
		  _M_dfs(__match_mode, __state._M_next);
		  // DON'T attempt anything if it's already accepted. An
		  // accepted state *must* be better than a solution that
		  // matches a non-greedy quantifier one more time.
		  if (!_M_has_sol)
		    _M_rep_once_more(__match_mode, __i);
239
		}
240
	    }
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
	}
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_subexpr_begin(_Match_mode __match_mode, _StateIdT __i)
    {
      const auto& __state = _M_nfa[__i];

      auto& __res = _M_cur_results[__state._M_subexpr];
      auto __back = __res.first;
      __res.first = _M_current;
      _M_dfs(__match_mode, __state._M_next);
      __res.first = __back;
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_subexpr_end(_Match_mode __match_mode, _StateIdT __i)
    {
      const auto& __state = _M_nfa[__i];

      auto& __res = _M_cur_results[__state._M_subexpr];
      auto __back = __res;
      __res.second = _M_current;
      __res.matched = true;
      _M_dfs(__match_mode, __state._M_next);
      __res = __back;
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_line_begin_assertion(_Match_mode __match_mode, _StateIdT __i)
    {
      const auto& __state = _M_nfa[__i];
      if (_M_at_begin())
	_M_dfs(__match_mode, __state._M_next);
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_line_end_assertion(_Match_mode __match_mode, _StateIdT __i)
    {
      const auto& __state = _M_nfa[__i];
      if (_M_at_end())
	_M_dfs(__match_mode, __state._M_next);
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    inline void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_word_boundary(_Match_mode __match_mode, _StateIdT __i)
    {
      const auto& __state = _M_nfa[__i];
      if (_M_word_boundary() == !__state._M_neg)
	_M_dfs(__match_mode, __state._M_next);
    }

  // Here __state._M_alt offers a single start node for a sub-NFA.
  // We recursively invoke our algorithm to match the sub-NFA.
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_subexpr_lookahead(_Match_mode __match_mode, _StateIdT __i)
    {
      const auto& __state = _M_nfa[__i];
      if (_M_lookahead(__state._M_alt) == !__state._M_neg)
	_M_dfs(__match_mode, __state._M_next);
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_match(_Match_mode __match_mode, _StateIdT __i)
    {
      const auto& __state = _M_nfa[__i];

      if (_M_current == _M_end)
	return;
      if (__dfs_mode)
	{
	  if (__state._M_matches(*_M_current))
327
	    {
328 329 330
	      ++_M_current;
	      _M_dfs(__match_mode, __state._M_next);
	      --_M_current;
331
	    }
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
	}
      else
	if (__state._M_matches(*_M_current))
	  _M_states._M_queue(__state._M_next, _M_cur_results);
    }

  // First fetch the matched result from _M_cur_results as __submatch;
  // then compare it with
  // (_M_current, _M_current + (__submatch.second - __submatch.first)).
  // If matched, keep going; else just return and try another state.
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_backref(_Match_mode __match_mode, _StateIdT __i)
    {
      __glibcxx_assert(__dfs_mode);

      const auto& __state = _M_nfa[__i];
      auto& __submatch = _M_cur_results[__state._M_backref_index];
      if (!__submatch.matched)
	return;
      auto __last = _M_current;
      for (auto __tmp = __submatch.first;
	   __last != _M_end && __tmp != __submatch.second;
	   ++__tmp)
	++__last;
      if (_M_re._M_automaton->_M_traits.transform(__submatch.first,
						  __submatch.second)
	  == _M_re._M_automaton->_M_traits.transform(_M_current, __last))
	{
	  if (__last != _M_current)
363
	    {
364 365 366 367
	      auto __backup = _M_current;
	      _M_current = __last;
	      _M_dfs(__match_mode, __state._M_next);
	      _M_current = __backup;
368 369
	    }
	  else
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
	    _M_dfs(__match_mode, __state._M_next);
	}
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_accept(_Match_mode __match_mode, _StateIdT __i)
    {
      if (__dfs_mode)
	{
	  __glibcxx_assert(!_M_has_sol);
	  if (__match_mode == _Match_mode::_Exact)
	    _M_has_sol = _M_current == _M_end;
	  else
	    _M_has_sol = true;
	  if (_M_current == _M_begin
	      && (_M_flags & regex_constants::match_not_null))
	    _M_has_sol = false;
	  if (_M_has_sol)
390
	    {
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
	      if (_M_nfa._M_flags & regex_constants::ECMAScript)
		_M_results = _M_cur_results;
	      else // POSIX
		{
		  __glibcxx_assert(_M_states._M_get_sol_pos());
		  // Here's POSIX's logic: match the longest one. However
		  // we never know which one (lhs or rhs of "|") is longer
		  // unless we try both of them and compare the results.
		  // The member variable _M_sol_pos records the end
		  // position of the last successful match. It's better
		  // to be larger, because POSIX regex is always greedy.
		  // TODO: This could be slow.
		  if (*_M_states._M_get_sol_pos() == _BiIter()
		      || std::distance(_M_begin,
				       *_M_states._M_get_sol_pos())
			 < std::distance(_M_begin, _M_current))
		    {
		      *_M_states._M_get_sol_pos() = _M_current;
		      _M_results = _M_cur_results;
		    }
		}
412
	    }
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
	}
      else
	{
	  if (_M_current == _M_begin
	      && (_M_flags & regex_constants::match_not_null))
	    return;
	  if (__match_mode == _Match_mode::_Prefix || _M_current == _M_end)
	    if (!_M_has_sol)
	      {
		_M_has_sol = true;
		_M_results = _M_cur_results;
	      }
	}
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_handle_alternative(_Match_mode __match_mode, _StateIdT __i)
    {
      const auto& __state = _M_nfa[__i];

      if (_M_nfa._M_flags & regex_constants::ECMAScript)
	{
	  // TODO: Fix BFS support. It is wrong.
	  _M_dfs(__match_mode, __state._M_alt);
	  // Pick lhs if it matches. Only try rhs if it doesn't.
	  if (!_M_has_sol)
	    _M_dfs(__match_mode, __state._M_next);
	}
      else
	{
	  // Try both and compare the result.
	  // See "case _S_opcode_accept:" handling above.
	  _M_dfs(__match_mode, __state._M_alt);
	  auto __has_sol = _M_has_sol;
	  _M_has_sol = false;
	  _M_dfs(__match_mode, __state._M_next);
	  _M_has_sol |= __has_sol;
	}
    }

  template<typename _BiIter, typename _Alloc, typename _TraitsT,
	   bool __dfs_mode>
    void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
    _M_dfs(_Match_mode __match_mode, _StateIdT __i)
    {
      if (_M_states._M_visited(__i))
	return;

      switch (_M_nfa[__i]._M_opcode())
	{
	case _S_opcode_repeat:
	  _M_handle_repeat(__match_mode, __i); break;
	case _S_opcode_subexpr_begin:
	  _M_handle_subexpr_begin(__match_mode, __i); break;
	case _S_opcode_subexpr_end:
	  _M_handle_subexpr_end(__match_mode, __i); break;
	case _S_opcode_line_begin_assertion:
	  _M_handle_line_begin_assertion(__match_mode, __i); break;
	case _S_opcode_line_end_assertion:
	  _M_handle_line_end_assertion(__match_mode, __i); break;
	case _S_opcode_word_boundary:
	  _M_handle_word_boundary(__match_mode, __i); break;
	case _S_opcode_subexpr_lookahead:
	  _M_handle_subexpr_lookahead(__match_mode, __i); break;
	case _S_opcode_match:
	  _M_handle_match(__match_mode, __i); break;
	case _S_opcode_backref:
	  _M_handle_backref(__match_mode, __i); break;
	case _S_opcode_accept:
	  _M_handle_accept(__match_mode, __i); break;
	case _S_opcode_alternative:
	  _M_handle_alternative(__match_mode, __i); break;
487
	default:
488
	  __glibcxx_assert(false);
489
	}
490 491
    }

492
  // Return whether now is at some word boundary.
493
  template<typename _BiIter, typename _Alloc, typename _TraitsT,
494
	   bool __dfs_mode>
495
    bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
496
    _M_word_boundary() const
Tim Shen committed
497
    {
498 499 500 501 502
      if (_M_current == _M_begin && (_M_flags & regex_constants::match_not_bow))
	return false;
      if (_M_current == _M_end && (_M_flags & regex_constants::match_not_eow))
	return false;

503 504 505
      bool __left_is_word = false;
      if (_M_current != _M_begin
	  || (_M_flags & regex_constants::match_prev_avail))
506
	{
507 508 509
	  auto __prev = _M_current;
	  if (_M_is_word(*std::prev(__prev)))
	    __left_is_word = true;
510
	}
511 512 513
      bool __right_is_word =
        _M_current != _M_end && _M_is_word(*_M_current);

514
      return __left_is_word != __right_is_word;
Tim Shen committed
515 516
    }

517 518 519
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
} // namespace