Skip to content

Commit bcd469c

Browse files
committed
add empty subexpression grammar and tests
1 parent 6390d8d commit bcd469c

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

resources/RegexGrammar.pp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
alternation()
136136

137137
alternation:
138-
concatenation() ( ::alternation:: concatenation() #alternation )*
138+
concatenation()? ( <alternation> concatenation()? #alternation )*
139139

140140
concatenation:
141141
( internal_options() | assertion() | quantification() | condition() )
@@ -154,8 +154,8 @@
154154
<index>
155155
| ::assertion_reference_:: alternation() #assertioncondition
156156
)
157-
::_capturing:: concatenation()?
158-
( ::alternation:: concatenation()? )?
157+
::_capturing::
158+
alternation()
159159
::_capturing::
160160

161161
assertion:
@@ -165,7 +165,8 @@
165165
| ::lookbehind_:: #lookbehind
166166
| ::negative_lookbehind_:: #negativelookbehind
167167
)
168-
alternation() ::_capturing::
168+
alternation()
169+
::_capturing::
169170

170171
quantification:
171172
( class() | simple() ) ( quantifier() #quantification )?
@@ -208,7 +209,8 @@
208209
| ::atomic_group_:: #atomicgroup
209210
| ::capturing_::
210211
)
211-
alternation() ::_capturing::
212+
alternation()
213+
::_capturing::
212214

213215
non_capturing_internal_options:
214216
<non_capturing_internal_option>

tests/PHPStan/Analyser/nsrt/preg_match_shapes.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,3 +899,29 @@ function bugUnescapedDashAfterRange (string $string): void {
899899
assertType("array{string, non-empty-string}", $matches);
900900
}
901901
}
902+
903+
function bugEmptySubexpression (string $string): void {
904+
if (preg_match('//', $string, $matches)) {
905+
assertType("array{string}", $matches); // could be array{''}
906+
}
907+
908+
if (preg_match('/()/', $string, $matches)) {
909+
assertType("array{string, ''}", $matches); // could be array{'', ''}
910+
}
911+
912+
if (preg_match('/|/', $string, $matches)) {
913+
assertType("array{string}", $matches); // could be array{''}
914+
}
915+
916+
if (preg_match('(|a)', $string, $matches)) {
917+
assertType("array{string, ''|'a'}", $matches);
918+
}
919+
920+
if (preg_match('(|a)', $string, $matches)) {
921+
assertType("array{string, ''|'a'}", $matches);
922+
}
923+
924+
if (preg_match('(a||b)', $string, $matches)) {
925+
assertType("array{string, ''|'a'|'b'}", $matches);
926+
}
927+
}

0 commit comments

Comments
 (0)