@@ -1511,7 +1511,6 @@ public:
1511
1511
using _Difft = typename iterator_traits<_FwdIt>::difference_type;
1512
1512
1513
1513
_Builder(const _RxTraits& _Tr, regex_constants::syntax_option_type);
1514
- bool _Beg_expr() const;
1515
1514
void _Setlong();
1516
1515
// _Discard_pattern is an ABI zombie name
1517
1516
void _Tidy() noexcept;
@@ -1547,7 +1546,6 @@ private:
1547
1546
static void _Insert_node(_Node_base*, _Node_base*);
1548
1547
_Node_base* _New_node(_Node_type _Kind);
1549
1548
void _Add_str_node();
1550
- bool _Beg_expr(_Node_base*) const;
1551
1549
void _Add_char_to_bitmap(_Elem _Ch);
1552
1550
void _Add_char_to_array(_Elem _Ch);
1553
1551
void _Add_elts(_Node_class<_Elem, _RxTraits>*, typename _RxTraits::char_class_type, bool);
@@ -2784,17 +2782,6 @@ _Node_base* _Builder<_FwdIt, _Elem, _RxTraits>::_Getmark() const {
2784
2782
return _Current;
2785
2783
}
2786
2784
2787
- template <class _FwdIt, class _Elem, class _RxTraits>
2788
- bool _Builder<_FwdIt, _Elem, _RxTraits>::_Beg_expr(_Node_base* _Nx) const {
2789
- // test for beginning of expression or subexpression
2790
- return _Nx->_Kind == _N_begin || _Nx->_Kind == _N_group || _Nx->_Kind == _N_capture;
2791
- }
2792
-
2793
- template <class _FwdIt, class _Elem, class _RxTraits>
2794
- bool _Builder<_FwdIt, _Elem, _RxTraits>::_Beg_expr() const { // test for beginning of expression or subexpression
2795
- return _Beg_expr(_Current) || (_Current->_Kind == _N_bol && _Beg_expr(_Current->_Prev));
2796
- }
2797
-
2798
2785
template <class _FwdIt, class _Elem, class _RxTraits>
2799
2786
_Node_base* _Builder<_FwdIt, _Elem, _RxTraits>::_Link_node(_Node_base* _Nx) { // insert _Nx at current location
2800
2787
_Nx->_Prev = _Current;
@@ -3905,17 +3892,16 @@ void _Parser<_FwdIt, _Elem, _RxTraits>::_Trans() { // map character to meta-char
3905
3892
break;
3906
3893
3907
3894
case _Meta_star:
3908
- if ((_L_flags & _L_star_beg) && _Nfa._Beg_expr()) {
3909
- _Mchar = _Meta_chr;
3910
- }
3911
-
3895
+ // A star can always act as a quantifier outside bracket expressions,
3896
+ // but _L_star_beg (used by basic/grep) allows its use as an ordinary character
3897
+ // at the beginning of a (sub-)expression (potentially after an optional caret anchor).
3898
+ // We'll handle that when we are parsing alternatives in disjunctions.
3912
3899
break;
3913
3900
3914
3901
case _Meta_caret:
3915
- if ((_L_flags & _L_anch_rstr) && !_Nfa._Beg_expr()) {
3916
- _Mchar = _Meta_chr;
3917
- }
3918
-
3902
+ // A caret can always negate a bracket expression,
3903
+ // but _L_anch_rstr (used by basic/grep) restricts caret anchors to the beginning.
3904
+ // We'll handle that restriction when we're about to add a bol node.
3919
3905
break;
3920
3906
3921
3907
case _Meta_dlr:
@@ -4481,15 +4467,21 @@ bool _Parser<_FwdIt, _Elem, _RxTraits>::_Alternative() { // check for valid alte
4481
4467
_Next();
4482
4468
_Quant = _Wrapped_disjunction();
4483
4469
_Expect(_Meta_rpar, regex_constants::error_paren);
4484
- } else if (_Mchar == _Meta_caret) { // add bol node
4470
+ } else if (_Mchar == _Meta_caret && (!(_L_flags & _L_anch_rstr) || !_Found) ) { // add bol node
4485
4471
_Nfa._Add_bol();
4486
4472
_Next();
4487
- _Quant = false;
4473
+ if ((_L_flags & _L_star_beg) && _Mchar == _Meta_star && !_Found) {
4474
+ _Nfa._Add_char(_Char);
4475
+ _Next();
4476
+ } else {
4477
+ _Quant = false;
4478
+ }
4488
4479
} else if (_Mchar == _Meta_dlr) { // add eol node
4489
4480
_Nfa._Add_eol();
4490
4481
_Next();
4491
4482
_Quant = false;
4492
- } else if (_Mchar == _Meta_star || _Mchar == _Meta_plus || _Mchar == _Meta_query || _Mchar == _Meta_lbr) {
4483
+ } else if ((_Mchar == _Meta_star && (!(_L_flags & _L_star_beg) || _Found)) || _Mchar == _Meta_plus
4484
+ || _Mchar == _Meta_query || _Mchar == _Meta_lbr) {
4493
4485
_Error(regex_constants::error_badrepeat);
4494
4486
} else if (_Mchar == _Meta_rbr && !(_L_flags & _L_paren_bal)) {
4495
4487
_Error(regex_constants::error_brace);
0 commit comments