File Coverage

/usr/include/c++/5/bits/regex_automaton.tcc
Criterion Covered Total %
statement 0 54 0.0
branch 0 100 0.0
condition n/a
subroutine n/a
pod n/a
total 0 154 0.0


line stmt bran cond sub pod time code
1             // class template regex -*- C++ -*-
2              
3             // Copyright (C) 2013-2015 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             // .
24              
25             /**
26             * @file bits/regex_automaton.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             namespace std _GLIBCXX_VISIBILITY(default)
32             {
33             namespace __detail
34             {
35             _GLIBCXX_BEGIN_NAMESPACE_VERSION
36              
37             #ifdef _GLIBCXX_DEBUG
38             inline std::ostream&
39             _State_base::_M_print(std::ostream& ostr) const
40             {
41             switch (_M_opcode)
42             {
43             case _S_opcode_alternative:
44             case _S_opcode_repeat:
45             ostr << "alt next=" << _M_next << " alt=" << _M_alt;
46             break;
47             case _S_opcode_subexpr_begin:
48             ostr << "subexpr begin next=" << _M_next << " index=" << _M_subexpr;
49             break;
50             case _S_opcode_subexpr_end:
51             ostr << "subexpr end next=" << _M_next << " index=" << _M_subexpr;
52             break;
53             case _S_opcode_backref:
54             ostr << "backref next=" << _M_next << " index=" << _M_backref_index;
55             break;
56             case _S_opcode_match:
57             ostr << "match next=" << _M_next;
58             break;
59             case _S_opcode_accept:
60             ostr << "accept next=" << _M_next;
61             break;
62             default:
63             ostr << "unknown next=" << _M_next;
64             break;
65             }
66             return ostr;
67             }
68              
69             // Prints graphviz dot commands for state.
70             inline std::ostream&
71             _State_base::_M_dot(std::ostream& __ostr, _StateIdT __id) const
72             {
73             switch (_M_opcode)
74             {
75             case _S_opcode_alternative:
76             case _S_opcode_repeat:
77             __ostr << __id << " [label=\"" << __id << "\\nALT\"];\n"
78             << __id << " -> " << _M_next
79             << " [label=\"next\", tailport=\"s\"];\n"
80             << __id << " -> " << _M_alt
81             << " [label=\"alt\", tailport=\"n\"];\n";
82             break;
83             case _S_opcode_backref:
84             __ostr << __id << " [label=\"" << __id << "\\nBACKREF "
85             << _M_subexpr << "\"];\n"
86             << __id << " -> " << _M_next << " [label=\"\"];\n";
87             break;
88             case _S_opcode_line_begin_assertion:
89             __ostr << __id << " [label=\"" << __id << "\\nLINE_BEGIN \"];\n"
90             << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
91             break;
92             case _S_opcode_line_end_assertion:
93             __ostr << __id << " [label=\"" << __id << "\\nLINE_END \"];\n"
94             << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
95             break;
96             case _S_opcode_word_boundary:
97             __ostr << __id << " [label=\"" << __id << "\\nWORD_BOUNDRY "
98             << _M_neg << "\"];\n"
99             << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
100             break;
101             case _S_opcode_subexpr_lookahead:
102             __ostr << __id << " [label=\"" << __id << "\\nLOOK_AHEAD\"];\n"
103             << __id << " -> " << _M_next
104             << " [label=\"epsilon\", tailport=\"s\"];\n"
105             << __id << " -> " << _M_alt
106             << " [label=\"\", tailport=\"n\"];\n";
107             break;
108             case _S_opcode_subexpr_begin:
109             __ostr << __id << " [label=\"" << __id << "\\nSBEGIN "
110             << _M_subexpr << "\"];\n"
111             << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
112             break;
113             case _S_opcode_subexpr_end:
114             __ostr << __id << " [label=\"" << __id << "\\nSEND "
115             << _M_subexpr << "\"];\n"
116             << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
117             break;
118             case _S_opcode_dummy:
119             break;
120             case _S_opcode_match:
121             __ostr << __id << " [label=\"" << __id << "\\nMATCH\"];\n"
122             << __id << " -> " << _M_next << " [label=\"\"];\n";
123             break;
124             case _S_opcode_accept:
125             __ostr << __id << " [label=\"" << __id << "\\nACC\"];\n" ;
126             break;
127             default:
128             _GLIBCXX_DEBUG_ASSERT(false);
129             break;
130             }
131             return __ostr;
132             }
133              
134             template
135             std::ostream&
136             _NFA<_TraitsT>::_M_dot(std::ostream& __ostr) const
137             {
138             __ostr << "digraph _Nfa {\n"
139             " rankdir=LR;\n";
140             for (size_t __i = 0; __i < this->size(); ++__i)
141             (*this)[__i]._M_dot(__ostr, __i);
142             __ostr << "}\n";
143             return __ostr;
144             }
145             #endif
146              
147             template
148             _StateIdT
149 0           _NFA<_TraitsT>::_M_insert_backref(size_t __index)
150             {
151             // To figure out whether a backref is valid, a stack is used to store
152             // unfinished sub-expressions. For example, when parsing
153             // "(a(b)(c\\1(d)))" at '\\1', _M_subexpr_count is 3, indicating that 3
154             // sub expressions are parsed or partially parsed(in the stack), aka,
155             // "(a..", "(b)" and "(c..").
156             // _M_paren_stack is {1, 3}, for incomplete "(a.." and "(c..". At this
157             // time, "\\2" is valid, but "\\1" and "\\3" are not.
158 0 0         if (__index >= _M_subexpr_count)
159 0 0         __throw_regex_error(regex_constants::error_backref);
160 0 0         for (auto __it : this->_M_paren_stack)
161 0 0         if (__index == __it)
162 0 0         __throw_regex_error(regex_constants::error_backref);
163 0           this->_M_has_backref = true;
164 0           _StateT __tmp(_S_opcode_backref);
165 0           __tmp._M_backref_index = __index;
166 0 0         return _M_insert_state(std::move(__tmp));
    0          
167             }
168              
169             template
170             void
171 0           _NFA<_TraitsT>::_M_eliminate_dummy()
172             {
173 0 0         for (auto& __it : *this)
174             {
175 0 0         while (__it._M_next >= 0 && (*this)[__it._M_next]._M_opcode
    0          
    0          
176 0           == _S_opcode_dummy)
177 0           __it._M_next = (*this)[__it._M_next]._M_next;
178 0 0         if (__it._M_opcode == _S_opcode_alternative
    0          
    0          
179 0           || __it._M_opcode == _S_opcode_repeat
180 0           || __it._M_opcode == _S_opcode_subexpr_lookahead)
181 0 0         while (__it._M_alt >= 0 && (*this)[__it._M_alt]._M_opcode
    0          
    0          
182 0           == _S_opcode_dummy)
183 0           __it._M_alt = (*this)[__it._M_alt]._M_next;
184             }
185 0           }
186              
187             // Just apply DFS on the sequence and re-link their links.
188             template
189             _StateSeq<_TraitsT>
190 0           _StateSeq<_TraitsT>::_M_clone()
191             {
192 0           std::map<_StateIdT, _StateIdT> __m;
193 0 0         std::stack<_StateIdT> __stack;
    0          
194 0 0         __stack.push(_M_start);
195 0 0         while (!__stack.empty())
196             {
197 0           auto __u = __stack.top();
198 0           __stack.pop();
199 0 0         auto __dup = _M_nfa[__u];
200             // _M_insert_state() never return -1
201 0 0         auto __id = _M_nfa._M_insert_state(__dup);
    0          
202 0 0         __m[__u] = __id;
203 0 0         if (__dup._M_opcode == _S_opcode_alternative
    0          
    0          
204 0           || __dup._M_opcode == _S_opcode_repeat
205 0           || __dup._M_opcode == _S_opcode_subexpr_lookahead)
206 0 0         if (__dup._M_alt != _S_invalid_state_id
    0          
    0          
207 0 0         && __m.count(__dup._M_alt) == 0)
208 0 0         __stack.push(__dup._M_alt);
209 0 0         if (__u == _M_end)
210 0           continue;
211 0 0         if (__dup._M_next != _S_invalid_state_id
    0          
    0          
212 0 0         && __m.count(__dup._M_next) == 0)
213 0 0         __stack.push(__dup._M_next);
    0          
214             }
215 0 0         for (auto __it : __m)
216             {
217 0           auto __v = __it.second;
218 0           auto& __ref = _M_nfa[__v];
219 0 0         if (__ref._M_next != _S_invalid_state_id)
220             {
221             _GLIBCXX_DEBUG_ASSERT(__m.count(__ref._M_next) > 0);
222 0 0         __ref._M_next = __m[__ref._M_next];
223             }
224 0 0         if (__ref._M_opcode == _S_opcode_alternative
    0          
    0          
225 0           || __ref._M_opcode == _S_opcode_repeat
226 0           || __ref._M_opcode == _S_opcode_subexpr_lookahead)
227 0 0         if (__ref._M_alt != _S_invalid_state_id)
228             {
229             _GLIBCXX_DEBUG_ASSERT(__m.count(__ref._M_alt) > 0);
230 0 0         __ref._M_alt = __m[__ref._M_alt];
231             }
232             }
233 0 0         return _StateSeq(_M_nfa, __m[_M_start], __m[_M_end]);
    0          
234             }
235              
236             _GLIBCXX_END_NAMESPACE_VERSION
237             } // namespace __detail
238             } // namespace