@@ -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, $ markVerbs ] = $ 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
+ $ markVerbs ,
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
+ $ markVerbs ,
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
+ $ markVerbs ,
214
217
);
215
218
}
216
219
@@ -266,12 +269,14 @@ private function getOnlyTopLevelAlternationId(array $captureGroups): ?int
266
269
267
270
/**
268
271
* @param array<RegexCapturingGroup> $captureGroups
272
+ * @param list<string> $markVerbs
269
273
*/
270
274
private function buildArrayType (
271
275
array $ captureGroups ,
272
276
TrinaryLogic $ wasMatched ,
273
277
int $ trailingOptionals ,
274
278
int $ flags ,
279
+ array $ markVerbs ,
275
280
): Type
276
281
{
277
282
$ builder = ConstantArrayTypeBuilder::createEmpty ();
@@ -325,6 +330,18 @@ private function buildArrayType(
325
330
$ i ++;
326
331
}
327
332
333
+ if (count ($ markVerbs ) > 0 ) {
334
+ $ markTypes = [];
335
+ foreach ($ markVerbs as $ mark ) {
336
+ $ markTypes [] = new ConstantStringType ($ mark );
337
+ }
338
+ $ builder ->setOffsetValueType (
339
+ $ this ->getKeyType ('MARK ' ),
340
+ TypeCombinator::union (...$ markTypes ),
341
+ true ,
342
+ );
343
+ }
344
+
328
345
return $ builder ->getArray ();
329
346
}
330
347
@@ -372,7 +389,7 @@ private function getValueType(Type $baseType, int $flags): Type
372
389
}
373
390
374
391
/**
375
- * @return array{array<int, RegexCapturingGroup>, array<int, array<int, int[]>>}|null
392
+ * @return array{array<int, RegexCapturingGroup>, array<int, array<int, int[]>>, list<string> }|null
376
393
*/
377
394
private function parseGroups (string $ regex ): ?array
378
395
{
@@ -398,6 +415,7 @@ private function parseGroups(string $regex): ?array
398
415
$ groupCombinations = [];
399
416
$ alternationId = -1 ;
400
417
$ captureGroupId = 100 ;
418
+ $ markVerbs = [];
401
419
$ this ->walkRegexAst (
402
420
$ ast ,
403
421
false ,
@@ -408,14 +426,16 @@ private function parseGroups(string $regex): ?array
408
426
$ captureGroupId ,
409
427
$ capturingGroups ,
410
428
$ groupCombinations ,
429
+ $ markVerbs ,
411
430
);
412
431
413
- return [$ capturingGroups , $ groupCombinations ];
432
+ return [$ capturingGroups , $ groupCombinations, $ markVerbs ];
414
433
}
415
434
416
435
/**
417
436
* @param array<int, RegexCapturingGroup> $capturingGroups
418
437
* @param array<int, array<int, int[]>> $groupCombinations
438
+ * @param list<string> $markVerbs
419
439
*/
420
440
private function walkRegexAst (
421
441
TreeNode $ ast ,
@@ -427,6 +447,7 @@ private function walkRegexAst(
427
447
int &$ captureGroupId ,
428
448
array &$ capturingGroups ,
429
449
array &$ groupCombinations ,
450
+ array &$ markVerbs ,
430
451
): void
431
452
{
432
453
$ group = null ;
@@ -441,7 +462,7 @@ private function walkRegexAst(
441
462
);
442
463
$ parentGroup = $ group ;
443
464
} elseif ($ ast ->getId () === '#namedcapturing ' ) {
444
- $ name = $ ast ->getChild (0 )->getValue ()[ ' value ' ] ;
465
+ $ name = $ ast ->getChild (0 )->getValueValue () ;
445
466
$ group = new RegexCapturingGroup (
446
467
$ captureGroupId ++,
447
468
$ name ,
@@ -483,6 +504,11 @@ private function walkRegexAst(
483
504
$ inAlternation = true ;
484
505
}
485
506
507
+ if ($ ast ->getId () === '#mark ' ) {
508
+ $ markVerbs [] = $ ast ->getChild (0 )->getValueValue ();
509
+ return ;
510
+ }
511
+
486
512
if ($ group instanceof RegexCapturingGroup) {
487
513
$ capturingGroups [$ group ->getId ()] = $ group ;
488
514
@@ -506,6 +532,7 @@ private function walkRegexAst(
506
532
$ captureGroupId ,
507
533
$ capturingGroups ,
508
534
$ groupCombinations ,
535
+ $ markVerbs ,
509
536
);
510
537
511
538
if ($ ast ->getId () !== '#alternation ' ) {
0 commit comments