@@ -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 , $ hasMark ] = $ parseResult ;
128
+ [$ groupList , $ groupCombinations , $ markVerbs ] = $ parseResult ;
129
129
130
130
$ trailingOptionals = 0 ;
131
131
foreach (array_reverse ($ groupList ) as $ captureGroup ) {
@@ -152,7 +152,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
152
152
$ wasMatched ,
153
153
$ trailingOptionals ,
154
154
$ flags ?? 0 ,
155
- $ hasMark ,
155
+ $ markVerbs ,
156
156
);
157
157
158
158
if (!$ this ->containsUnmatchedAsNull ($ flags ?? 0 )) {
@@ -190,7 +190,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
190
190
$ wasMatched ,
191
191
$ trailingOptionals ,
192
192
$ flags ?? 0 ,
193
- $ hasMark ,
193
+ $ markVerbs ,
194
194
);
195
195
196
196
$ combiTypes [] = $ combiType ;
@@ -213,7 +213,7 @@ private function matchRegex(string $regex, ?int $flags, TrinaryLogic $wasMatched
213
213
$ wasMatched ,
214
214
$ trailingOptionals ,
215
215
$ flags ?? 0 ,
216
- $ hasMark ,
216
+ $ markVerbs ,
217
217
);
218
218
}
219
219
@@ -269,13 +269,14 @@ private function getOnlyTopLevelAlternationId(array $captureGroups): ?int
269
269
270
270
/**
271
271
* @param array<RegexCapturingGroup> $captureGroups
272
+ * @param list<string> $markVerbs
272
273
*/
273
274
private function buildArrayType (
274
275
array $ captureGroups ,
275
276
TrinaryLogic $ wasMatched ,
276
277
int $ trailingOptionals ,
277
278
int $ flags ,
278
- bool $ hasMark ,
279
+ array $ markVerbs ,
279
280
): Type
280
281
{
281
282
$ builder = ConstantArrayTypeBuilder::createEmpty ();
@@ -329,10 +330,14 @@ private function buildArrayType(
329
330
$ i ++;
330
331
}
331
332
332
- if ($ hasMark ) {
333
+ if (count ($ markVerbs ) > 0 ) {
334
+ $ markTypes = [];
335
+ foreach ($ markVerbs as $ mark ) {
336
+ $ markTypes [] = new ConstantStringType ($ mark );
337
+ }
333
338
$ builder ->setOffsetValueType (
334
339
$ this ->getKeyType ('MARK ' ),
335
- new IntersectionType ([ new StringType (), new AccessoryNonEmptyStringType ()] ),
340
+ TypeCombinator:: union (... $ markTypes ),
336
341
true ,
337
342
);
338
343
}
@@ -384,7 +389,7 @@ private function getValueType(Type $baseType, int $flags): Type
384
389
}
385
390
386
391
/**
387
- * @return array{array<int, RegexCapturingGroup>, array<int, array<int, int[]>>, bool }|null
392
+ * @return array{array<int, RegexCapturingGroup>, array<int, array<int, int[]>>, list<string> }|null
388
393
*/
389
394
private function parseGroups (string $ regex ): ?array
390
395
{
@@ -410,7 +415,7 @@ private function parseGroups(string $regex): ?array
410
415
$ groupCombinations = [];
411
416
$ alternationId = -1 ;
412
417
$ captureGroupId = 100 ;
413
- $ hasMark = false ;
418
+ $ markVerbs = [] ;
414
419
$ this ->walkRegexAst (
415
420
$ ast ,
416
421
false ,
@@ -421,15 +426,16 @@ private function parseGroups(string $regex): ?array
421
426
$ captureGroupId ,
422
427
$ capturingGroups ,
423
428
$ groupCombinations ,
424
- $ hasMark ,
429
+ $ markVerbs ,
425
430
);
426
431
427
- return [$ capturingGroups , $ groupCombinations , $ hasMark ];
432
+ return [$ capturingGroups , $ groupCombinations , $ markVerbs ];
428
433
}
429
434
430
435
/**
431
436
* @param array<int, RegexCapturingGroup> $capturingGroups
432
437
* @param array<int, array<int, int[]>> $groupCombinations
438
+ * @param list<string> $markVerbs
433
439
*/
434
440
private function walkRegexAst (
435
441
TreeNode $ ast ,
@@ -441,7 +447,7 @@ private function walkRegexAst(
441
447
int &$ captureGroupId ,
442
448
array &$ capturingGroups ,
443
449
array &$ groupCombinations ,
444
- bool &$ hasMark ,
450
+ array &$ markVerbs ,
445
451
): void
446
452
{
447
453
$ group = null ;
@@ -456,7 +462,7 @@ private function walkRegexAst(
456
462
);
457
463
$ parentGroup = $ group ;
458
464
} elseif ($ ast ->getId () === '#namedcapturing ' ) {
459
- $ name = $ ast ->getChild (0 )->getValue ()[ ' value ' ] ;
465
+ $ name = $ ast ->getChild (0 )->getValueValue () ;
460
466
$ group = new RegexCapturingGroup (
461
467
$ captureGroupId ++,
462
468
$ name ,
@@ -499,7 +505,7 @@ private function walkRegexAst(
499
505
}
500
506
501
507
if ($ ast ->getId () === '#mark ' ) {
502
- $ hasMark = true ;
508
+ $ markVerbs [] = $ ast -> getChild ( 0 )-> getValueValue () ;
503
509
return ;
504
510
}
505
511
@@ -526,7 +532,7 @@ private function walkRegexAst(
526
532
$ captureGroupId ,
527
533
$ capturingGroups ,
528
534
$ groupCombinations ,
529
- $ hasMark ,
535
+ $ markVerbs ,
530
536
);
531
537
532
538
if ($ ast ->getId () !== '#alternation ' ) {
0 commit comments