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