@@ -125,7 +125,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
125
125
// regex could not be parsed by Hoa/Regex
126
126
return null ;
127
127
}
128
- [$ groupList , $ groupCombinations ] = $ parseResult ;
128
+ [$ groupList , $ groupCombinations, $ hasMark ] = $ parseResult ;
129
129
130
130
$ trailingOptionals = 0 ;
131
131
foreach (array_reverse ($ groupList ) as $ captureGroup ) {
@@ -152,6 +152,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
152
152
$ wasMatched ,
153
153
$ trailingOptionals ,
154
154
$ flags ?? 0 ,
155
+ $ hasMark ,
155
156
);
156
157
157
158
if (!$ this ->containsUnmatchedAsNull ($ flags ?? 0 )) {
@@ -189,6 +190,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
189
190
$ wasMatched ,
190
191
$ trailingOptionals ,
191
192
$ flags ?? 0 ,
193
+ $ hasMark ,
192
194
);
193
195
194
196
$ combiTypes [] = $ combiType ;
@@ -211,6 +213,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
211
213
$ wasMatched ,
212
214
$ trailingOptionals ,
213
215
$ flags ?? 0 ,
216
+ $ hasMark ,
214
217
);
215
218
}
216
219
@@ -272,6 +275,7 @@ private function buildArrayType(
272
275
TrinaryLogic $ wasMatched ,
273
276
int $ trailingOptionals ,
274
277
int $ flags ,
278
+ bool $ hasMark ,
275
279
): Type
276
280
{
277
281
$ builder = ConstantArrayTypeBuilder::createEmpty ();
@@ -325,6 +329,14 @@ private function buildArrayType(
325
329
$ i ++;
326
330
}
327
331
332
+ if ($ hasMark ) {
333
+ $ builder ->setOffsetValueType (
334
+ $ this ->getKeyType ('MARK ' ),
335
+ new IntersectionType ([new StringType (), new AccessoryNonEmptyStringType ()]),
336
+ true ,
337
+ );
338
+ }
339
+
328
340
return $ builder ->getArray ();
329
341
}
330
342
@@ -372,7 +384,7 @@ private function getValueType(Type $baseType, int $flags): Type
372
384
}
373
385
374
386
/**
375
- * @return array{array<int, RegexCapturingGroup>, array<int, array<int, int[]>>}|null
387
+ * @return array{array<int, RegexCapturingGroup>, array<int, array<int, int[]>>, bool }|null
376
388
*/
377
389
private function parseGroups (string $ regex ): ?array
378
390
{
@@ -398,6 +410,7 @@ private function parseGroups(string $regex): ?array
398
410
$ groupCombinations = [];
399
411
$ alternationId = -1 ;
400
412
$ captureGroupId = 100 ;
413
+ $ hasMark = false ;
401
414
$ this ->walkRegexAst (
402
415
$ ast ,
403
416
false ,
@@ -408,9 +421,10 @@ private function parseGroups(string $regex): ?array
408
421
$ captureGroupId ,
409
422
$ capturingGroups ,
410
423
$ groupCombinations ,
424
+ $ hasMark ,
411
425
);
412
426
413
- return [$ capturingGroups , $ groupCombinations ];
427
+ return [$ capturingGroups , $ groupCombinations, $ hasMark ];
414
428
}
415
429
416
430
/**
@@ -427,6 +441,7 @@ private function walkRegexAst(
427
441
int &$ captureGroupId ,
428
442
array &$ capturingGroups ,
429
443
array &$ groupCombinations ,
444
+ bool &$ hasMark ,
430
445
): void
431
446
{
432
447
$ group = null ;
@@ -483,6 +498,11 @@ private function walkRegexAst(
483
498
$ inAlternation = true ;
484
499
}
485
500
501
+ if ($ ast ->getId () === '#mark ' ) {
502
+ $ hasMark = true ;
503
+ return ;
504
+ }
505
+
486
506
if ($ group instanceof RegexCapturingGroup) {
487
507
$ capturingGroups [$ group ->getId ()] = $ group ;
488
508
@@ -506,6 +526,7 @@ private function walkRegexAst(
506
526
$ captureGroupId ,
507
527
$ capturingGroups ,
508
528
$ groupCombinations ,
529
+ $ hasMark ,
509
530
);
510
531
511
532
if ($ ast ->getId () !== '#alternation ' ) {
0 commit comments