Skip to content

Commit ec67f7b

Browse files
authored
<regex>: Process disjunctions non-recursively (#5745)
1 parent 3b1d7d2 commit ec67f7b

File tree

1 file changed

+37
-46
lines changed

1 file changed

+37
-46
lines changed

stl/inc/regex

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,8 @@ public:
16771677
enum class _Rx_unwind_ops {
16781678
_After_assert = _N_end + 1,
16791679
_After_neg_assert,
1680+
_Disjunction_eval_alt_on_failure,
1681+
_Disjunction_eval_alt_always,
16801682
};
16811683

16821684
template <class _BidIt>
@@ -1753,7 +1755,7 @@ public:
17531755

17541756
_Matched = false;
17551757

1756-
bool _Succeeded = _Match_pat(_Rep);
1758+
bool _Succeeded = _Match_pat(_Rep) || _Matched;
17571759
_STL_INTERNAL_CHECK(_Frames_count == 0);
17581760

17591761
if (!_Succeeded) {
@@ -1810,7 +1812,6 @@ private:
18101812
void _Increase_stack_usage_count();
18111813
void _Decrease_stack_usage_count();
18121814

1813-
bool _Do_if(_Node_if*);
18141815
bool _Do_rep0(_Node_rep*, bool);
18151816
bool _Do_rep(_Node_rep*, bool, int);
18161817
bool _Do_rep_first(_Node_rep*);
@@ -3402,44 +3403,6 @@ void _Matcher3<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Decrease_stack_usage_cou
34023403
}
34033404
}
34043405

3405-
template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
3406-
bool _Matcher3<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_if(_Node_if* _Node) { // apply if node
3407-
const size_t _Frame_idx = _Push_frame();
3408-
3409-
// look for the first match
3410-
for (; _Node; _Node = _Node->_Child) { // process one branch of if
3411-
_Tgt_state = _Frames[_Frame_idx]._Match_state; // rewind to where the alternation starts in input
3412-
if (_Match_pat(_Node->_Next)) { // try to match this branch
3413-
break;
3414-
}
3415-
}
3416-
3417-
// if none of the if branches matched, fail to match
3418-
if (!_Node) {
3419-
_Pop_frame(_Frame_idx);
3420-
return false;
3421-
}
3422-
3423-
// if we aren't looking for the longest match, that's it
3424-
if (!_Longest) {
3425-
_Pop_frame(_Frame_idx);
3426-
return true;
3427-
}
3428-
3429-
// see if there is a longer match
3430-
for (;;) { // process one branch of if
3431-
_Node = _Node->_Child;
3432-
if (!_Node) {
3433-
break;
3434-
}
3435-
3436-
_Tgt_state = _Frames[_Frame_idx]._Match_state;
3437-
(void) _Match_pat(_Node->_Next);
3438-
}
3439-
_Pop_frame(_Frame_idx);
3440-
return true;
3441-
}
3442-
34433406
template <class _BidIt, class _Elem, class _RxTraits, class _It, class _Alloc>
34443407
bool _Matcher3<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Do_rep0(_Node_rep* _Node, bool _Greedy) {
34453408
// apply repetition to loop with no nested if/do
@@ -4175,13 +4138,17 @@ bool _Matcher3<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Match_pat(_Node_base* _N
41754138
}
41764139

41774140
case _N_if:
4178-
if (!_Do_if(static_cast<_Node_if*>(_Nx))) {
4179-
_Failed = true;
4141+
{
4142+
auto _Node = static_cast<_Node_if*>(_Nx);
4143+
if (_Node->_Child) {
4144+
_Push_frame(_Longest ? _Rx_unwind_ops::_Disjunction_eval_alt_always
4145+
: _Rx_unwind_ops::_Disjunction_eval_alt_on_failure,
4146+
_Node->_Child);
4147+
_Increase_stack_usage_count();
4148+
}
4149+
break;
41804150
}
41814151

4182-
_Next = nullptr;
4183-
break;
4184-
41854152
case _N_endif:
41864153
break;
41874154

@@ -4236,7 +4203,7 @@ bool _Matcher3<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Match_pat(_Node_base* _N
42364203
} while (_Nx);
42374204

42384205
while (_Frames_count > _Initial_frames_count && !_Nx) {
4239-
const auto& _Frame = _Frames[--_Frames_count];
4206+
auto& _Frame = _Frames[--_Frames_count];
42404207

42414208
switch (_Frame._Code) {
42424209
case _Rx_unwind_ops::_After_assert:
@@ -4261,6 +4228,30 @@ bool _Matcher3<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Match_pat(_Node_base* _N
42614228
break;
42624229
}
42634230

4231+
case _Rx_unwind_ops::_Disjunction_eval_alt_on_failure:
4232+
// evaluate next alternative if matching prior alternatives failed
4233+
if (!_Failed) {
4234+
_Decrease_stack_usage_count();
4235+
break;
4236+
}
4237+
_FALLTHROUGH;
4238+
4239+
case _Rx_unwind_ops::_Disjunction_eval_alt_always:
4240+
// evaluate next alternative no matter if matching prior alternatives succeeded
4241+
{
4242+
auto _Node = static_cast<_Node_if*>(_Frame._Node);
4243+
_Nx = _Node->_Next;
4244+
_Tgt_state = _Frame._Match_state;
4245+
_Failed = false;
4246+
if (_Node->_Child) {
4247+
_Frame._Node = _Node->_Child;
4248+
++_Frames_count;
4249+
} else {
4250+
_Decrease_stack_usage_count();
4251+
}
4252+
break;
4253+
}
4254+
42644255
default:
42654256
#if _ITERATOR_DEBUG_LEVEL != 0
42664257
_STL_REPORT_ERROR("internal stack of regex matcher corrupted");

0 commit comments

Comments
 (0)