Home | History | Annotate | Download | only in bits
      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
    180