@@ -1108,7 +1108,7 @@ impl NFA {
1108
1108
1109
1109
/// Returns the starting states for initializing look-behind evaluation.
1110
1110
#[ inline]
1111
- pub fn lookbehinds ( & self ) -> & Vec < LookBehindInfo > {
1111
+ pub fn lookbehinds ( & self ) -> & [ LookBehindTree ] {
1112
1112
& self . 0 . lookbehinds
1113
1113
}
1114
1114
@@ -1277,46 +1277,83 @@ pub(super) struct Inner {
1277
1277
/// This is needed to initialize the table for storing the result of
1278
1278
/// look-around evaluation.
1279
1279
lookaround_count : usize ,
1280
- /// A vector of meta-data information about each look-behind in this NFA.
1281
- ///
1282
- /// Must be stored in a depth-first pre-order with regards to the nesting
1283
- /// of look-behinds.
1284
- lookbehinds : Vec < LookBehindInfo > ,
1280
+ /// A vector of look-behinds appearing in the regex. Order reflects the
1281
+ /// order in the regex.
1282
+ lookbehinds : Vec < LookBehindTree > ,
1285
1283
/// Heap memory used indirectly by NFA states and other things (like the
1286
1284
/// various capturing group representations above). Since each state
1287
1285
/// might use a different amount of heap, we need to keep track of this
1288
1286
/// incrementally.
1289
1287
memory_extra : usize ,
1290
1288
}
1291
1289
1292
- /// Information about a look-behind needed for execution.
1293
- # [ derive ( Clone , Copy , Debug ) ]
1294
- pub struct LookBehindInfo {
1295
- /// The id of the start state of the look-behind subexpression.
1290
+ /// Information about a look-behinds needed for execution. It preserves the
1291
+ /// nesting structure of look-behinds.
1292
+ # [ derive ( Clone , Debug ) ]
1293
+ pub struct LookBehindTree {
1296
1294
start_id : StateID ,
1297
- /// The offset (in bytes) from the beginning of the main regex that a
1298
- /// look-behind starts at. If `None`, the offset is unbounded.
1299
1295
offset_from_start : Option < usize > ,
1296
+ children : Vec < LookBehindTree > ,
1300
1297
}
1301
1298
1302
- impl LookBehindInfo {
1303
- pub ( super ) fn new (
1304
- start_id : StateID ,
1305
- offset_from_start : Option < usize > ,
1306
- ) -> Self {
1307
- Self { start_id, offset_from_start }
1299
+ impl LookBehindTree {
1300
+ pub fn new ( start_id : StateID , offset_from_start : Option < usize > ) -> Self {
1301
+ Self { start_id, offset_from_start, children : Vec :: new ( ) }
1308
1302
}
1309
1303
1310
- /// Start states of the look-behind subexpression.
1311
- pub ( super ) fn start_state ( & self ) -> StateID {
1304
+ /// The id of the start state of the look-behind subexpression.
1305
+ pub fn start_id ( & self ) -> StateID {
1312
1306
self . start_id
1313
1307
}
1314
1308
1315
1309
/// The offset (in bytes) from the beginning of the main regex that a
1316
1310
/// look-behind starts at. If `None`, the offset is unbounded.
1317
- pub ( super ) fn offset_from_start ( & self ) -> Option < usize > {
1311
+ pub fn offset_from_start ( & self ) -> Option < usize > {
1318
1312
self . offset_from_start
1319
1313
}
1314
+
1315
+ /// The look-behinds this look-behind contains. Order reflects the order
1316
+ /// in the regex.
1317
+ pub fn children ( & self ) -> & [ LookBehindTree ] {
1318
+ & self . children
1319
+ }
1320
+
1321
+ /// Calls `fun` on this look-behind tree and all of its children in pre-order.
1322
+ /// `fun` should return `true` if the traversal should continue and `false`
1323
+ /// if it should stop.
1324
+ ///
1325
+ /// The return value indicates whether the traversal was at any point stopped.
1326
+ pub fn preorder ( & self , fun : & impl Fn ( & LookBehindTree ) -> bool ) -> bool {
1327
+ if !fun ( self ) {
1328
+ return false ;
1329
+ }
1330
+ for child in & self . children {
1331
+ if !child. preorder ( fun) {
1332
+ return false ;
1333
+ }
1334
+ }
1335
+ true
1336
+ }
1337
+
1338
+ /// Like [`preorder`], but allows mutating the nodes.
1339
+ pub fn preorder_mut (
1340
+ & mut self ,
1341
+ fun : & impl Fn ( & mut LookBehindTree ) -> bool ,
1342
+ ) -> bool {
1343
+ if !fun ( self ) {
1344
+ return false ;
1345
+ }
1346
+ for child in & mut self . children {
1347
+ if !child. preorder_mut ( fun) {
1348
+ return false ;
1349
+ }
1350
+ }
1351
+ true
1352
+ }
1353
+
1354
+ pub fn children_mut ( & mut self ) -> & mut Vec < LookBehindTree > {
1355
+ & mut self . children
1356
+ }
1320
1357
}
1321
1358
1322
1359
impl Inner {
@@ -1465,7 +1502,7 @@ impl Inner {
1465
1502
///
1466
1503
/// The slice must be in a depth-first pre-order with regards to the
1467
1504
/// nesting of look-behinds.
1468
- pub ( super ) fn set_lookbehinds ( & mut self , lookbehinds : & [ LookBehindInfo ] ) {
1505
+ pub ( super ) fn set_lookbehinds ( & mut self , lookbehinds : & [ LookBehindTree ] ) {
1469
1506
self . lookbehinds = lookbehinds. to_vec ( ) ;
1470
1507
}
1471
1508
@@ -1522,9 +1559,12 @@ impl Inner {
1522
1559
for id in self . start_pattern . iter_mut ( ) {
1523
1560
* id = old_to_new[ * id] ;
1524
1561
}
1525
- for LookBehindInfo { start_id : id, .. } in self . lookbehinds . iter_mut ( )
1526
- {
1527
- * id = old_to_new[ * id] ;
1562
+
1563
+ for lbs in self . lookbehinds . iter_mut ( ) {
1564
+ lbs. preorder_mut ( & |e| {
1565
+ e. start_id = old_to_new[ e. start_id ] ;
1566
+ true
1567
+ } ) ;
1528
1568
}
1529
1569
}
1530
1570
}
@@ -1537,7 +1577,11 @@ impl fmt::Debug for Inner {
1537
1577
'^'
1538
1578
} else if sid == self . start_unanchored {
1539
1579
'>'
1540
- } else if self . lookbehinds . iter ( ) . any ( |i| i. start_state ( ) == sid) {
1580
+ } else if self
1581
+ . lookbehinds
1582
+ . iter ( )
1583
+ . any ( |i| !i. preorder ( & |e| e. start_id ( ) != sid) )
1584
+ {
1541
1585
'<'
1542
1586
} else {
1543
1587
' '
0 commit comments