@@ -1293,24 +1293,16 @@ impl PikeVM {
1293
1293
* look_behind_start,
1294
1294
) ;
1295
1295
}
1296
-
1297
- // This brings the look-behind threads into the state they must be for
1298
- // starting at input.start() instead of the beginning. This is
1299
- // necessary for lookbehinds to be able to match outside of the input
1300
- // span.
1301
- for lb_at in 0 ..input. start ( ) {
1302
- self . nexts (
1303
- stack,
1304
- curr_lookaround,
1305
- next_lookaround,
1306
- lookaround,
1307
- input,
1308
- lb_at,
1309
- & mut [ ] ,
1310
- ) ;
1311
- core:: mem:: swap ( curr_lookaround, next_lookaround) ;
1312
- next_lookaround. set . clear ( ) ;
1313
- }
1296
+ // This is necessary for look-behinds to be able to match outside of the
1297
+ // input span.
1298
+ self . fast_forward_lookbehinds (
1299
+ Span { start : 0 , end : input. start ( ) } ,
1300
+ input,
1301
+ stack,
1302
+ curr_lookaround,
1303
+ next_lookaround,
1304
+ lookaround,
1305
+ ) ;
1314
1306
}
1315
1307
1316
1308
let mut hm = None ;
@@ -1352,7 +1344,21 @@ impl PikeVM {
1352
1344
let span = Span :: from ( at..input. end ( ) ) ;
1353
1345
match pre. find ( input. haystack ( ) , span) {
1354
1346
None => break ,
1355
- Some ( ref span) => at = span. start ,
1347
+ Some ( ref span) => {
1348
+ if self . lookaround_count ( ) > 0 {
1349
+ // We are jumping ahead due to the pre-filter, thus we must bring
1350
+ // the look-behind threads to the new position.
1351
+ self . fast_forward_lookbehinds (
1352
+ Span { start : at, end : span. start } ,
1353
+ input,
1354
+ stack,
1355
+ curr_lookaround,
1356
+ next_lookaround,
1357
+ lookaround,
1358
+ ) ;
1359
+ }
1360
+ at = span. start
1361
+ }
1356
1362
}
1357
1363
}
1358
1364
}
@@ -1459,6 +1465,36 @@ impl PikeVM {
1459
1465
hm
1460
1466
}
1461
1467
1468
+ /// This brings the look-behind threads into the state they must be for
1469
+ /// starting at [input.end]. The assumption is that they are currently
1470
+ /// at [input.start].
1471
+ fn fast_forward_lookbehinds (
1472
+ & self ,
1473
+ forward_span : Span ,
1474
+ input : & Input < ' _ > ,
1475
+ stack : & mut Vec < FollowEpsilon > ,
1476
+ curr_lookaround : & mut ActiveStates ,
1477
+ next_lookaround : & mut ActiveStates ,
1478
+ lookaround : & mut Vec < Option < NonMaxUsize > > ,
1479
+ ) {
1480
+ for lb_at in forward_span. start ..forward_span. end {
1481
+ self . nexts (
1482
+ stack,
1483
+ curr_lookaround,
1484
+ next_lookaround,
1485
+ lookaround,
1486
+ input,
1487
+ lb_at,
1488
+ // Since capture groups are not allowed inside look-arounds,
1489
+ // there won't be any Capture epsilon transitions and hence it is ok to
1490
+ // use &mut [] for the slots parameter.
1491
+ & mut [ ] ,
1492
+ ) ;
1493
+ core:: mem:: swap ( curr_lookaround, next_lookaround) ;
1494
+ next_lookaround. set . clear ( ) ;
1495
+ }
1496
+ }
1497
+
1462
1498
/// The implementation for the 'which_overlapping_matches' API. Basically,
1463
1499
/// we do a single scan through the entire haystack (unless our regex
1464
1500
/// or search is anchored) and record every pattern that matched. In
@@ -1527,19 +1563,14 @@ impl PikeVM {
1527
1563
* look_behind_start,
1528
1564
) ;
1529
1565
}
1530
- for lb_at in 0 ..input. start ( ) {
1531
- self . nexts (
1532
- stack,
1533
- curr_lookaround,
1534
- next_lookaround,
1535
- lookaround,
1536
- input,
1537
- lb_at,
1538
- & mut [ ] ,
1539
- ) ;
1540
- core:: mem:: swap ( curr_lookaround, next_lookaround) ;
1541
- next_lookaround. set . clear ( ) ;
1542
- }
1566
+ self . fast_forward_lookbehinds (
1567
+ Span { start : 0 , end : input. start ( ) } ,
1568
+ input,
1569
+ stack,
1570
+ curr_lookaround,
1571
+ next_lookaround,
1572
+ lookaround,
1573
+ ) ;
1543
1574
for at in input. start ( ) ..=input. end ( ) {
1544
1575
let any_matches = !patset. is_empty ( ) ;
1545
1576
if curr. set . is_empty ( ) {
0 commit comments