@@ -222,6 +222,8 @@ impl Hir {
222
222
info. set_all_assertions ( true ) ;
223
223
info. set_anchored_start ( false ) ;
224
224
info. set_anchored_end ( false ) ;
225
+ info. set_line_anchored_start ( false ) ;
226
+ info. set_line_anchored_end ( false ) ;
225
227
info. set_any_anchored_start ( false ) ;
226
228
info. set_any_anchored_end ( false ) ;
227
229
info. set_match_empty ( true ) ;
@@ -246,6 +248,8 @@ impl Hir {
246
248
info. set_all_assertions ( false ) ;
247
249
info. set_anchored_start ( false ) ;
248
250
info. set_anchored_end ( false ) ;
251
+ info. set_line_anchored_start ( false ) ;
252
+ info. set_line_anchored_end ( false ) ;
249
253
info. set_any_anchored_start ( false ) ;
250
254
info. set_any_anchored_end ( false ) ;
251
255
info. set_match_empty ( false ) ;
@@ -262,6 +266,8 @@ impl Hir {
262
266
info. set_all_assertions ( false ) ;
263
267
info. set_anchored_start ( false ) ;
264
268
info. set_anchored_end ( false ) ;
269
+ info. set_line_anchored_start ( false ) ;
270
+ info. set_line_anchored_end ( false ) ;
265
271
info. set_any_anchored_start ( false ) ;
266
272
info. set_any_anchored_end ( false ) ;
267
273
info. set_match_empty ( false ) ;
@@ -278,17 +284,27 @@ impl Hir {
278
284
info. set_all_assertions ( true ) ;
279
285
info. set_anchored_start ( false ) ;
280
286
info. set_anchored_end ( false ) ;
287
+ info. set_line_anchored_start ( false ) ;
288
+ info. set_line_anchored_end ( false ) ;
281
289
info. set_any_anchored_start ( false ) ;
282
290
info. set_any_anchored_end ( false ) ;
283
291
info. set_match_empty ( true ) ;
284
292
if let Anchor :: StartText = anchor {
285
293
info. set_anchored_start ( true ) ;
294
+ info. set_line_anchored_start ( true ) ;
286
295
info. set_any_anchored_start ( true ) ;
287
296
}
288
297
if let Anchor :: EndText = anchor {
289
298
info. set_anchored_end ( true ) ;
299
+ info. set_line_anchored_end ( true ) ;
290
300
info. set_any_anchored_end ( true ) ;
291
301
}
302
+ if let Anchor :: StartLine = anchor {
303
+ info. set_line_anchored_start ( true ) ;
304
+ }
305
+ if let Anchor :: EndLine = anchor {
306
+ info. set_line_anchored_end ( true ) ;
307
+ }
292
308
Hir {
293
309
kind : HirKind :: Anchor ( anchor) ,
294
310
info : info,
@@ -302,6 +318,8 @@ impl Hir {
302
318
info. set_all_assertions ( true ) ;
303
319
info. set_anchored_start ( false ) ;
304
320
info. set_anchored_end ( false ) ;
321
+ info. set_line_anchored_start ( false ) ;
322
+ info. set_line_anchored_end ( false ) ;
305
323
info. set_any_anchored_start ( false ) ;
306
324
info. set_any_anchored_end ( false ) ;
307
325
// A negated word boundary matches the empty string, but a normal
@@ -330,6 +348,12 @@ impl Hir {
330
348
info. set_anchored_end (
331
349
!rep. is_match_empty ( ) && rep. hir . is_anchored_end ( )
332
350
) ;
351
+ info. set_line_anchored_start (
352
+ !rep. is_match_empty ( ) && rep. hir . is_anchored_start ( )
353
+ ) ;
354
+ info. set_line_anchored_end (
355
+ !rep. is_match_empty ( ) && rep. hir . is_anchored_end ( )
356
+ ) ;
333
357
info. set_any_anchored_start ( rep. hir . is_any_anchored_start ( ) ) ;
334
358
info. set_any_anchored_end ( rep. hir . is_any_anchored_end ( ) ) ;
335
359
info. set_match_empty ( rep. is_match_empty ( ) || rep. hir . is_match_empty ( ) ) ;
@@ -346,6 +370,8 @@ impl Hir {
346
370
info. set_all_assertions ( group. hir . is_all_assertions ( ) ) ;
347
371
info. set_anchored_start ( group. hir . is_anchored_start ( ) ) ;
348
372
info. set_anchored_end ( group. hir . is_anchored_end ( ) ) ;
373
+ info. set_line_anchored_start ( group. hir . is_line_anchored_start ( ) ) ;
374
+ info. set_line_anchored_end ( group. hir . is_line_anchored_end ( ) ) ;
349
375
info. set_any_anchored_start ( group. hir . is_any_anchored_start ( ) ) ;
350
376
info. set_any_anchored_end ( group. hir . is_any_anchored_end ( ) ) ;
351
377
info. set_match_empty ( group. hir . is_match_empty ( ) ) ;
@@ -361,7 +387,7 @@ impl Hir {
361
387
pub fn concat ( mut exprs : Vec < Hir > ) -> Hir {
362
388
match exprs. len ( ) {
363
389
0 => Hir :: empty ( ) ,
364
- 1 => exprs. pop ( ) . unwrap ( ) ,
390
+ 1 => { exprs. pop ( ) . unwrap ( ) }
365
391
_ => {
366
392
let mut info = HirInfo :: new ( ) ;
367
393
info. set_always_utf8 ( true ) ;
@@ -418,6 +444,24 @@ impl Hir {
418
444
. any ( |e| {
419
445
e. is_anchored_end ( )
420
446
} ) ) ;
447
+ // Repeat the process for line anchors.
448
+ info. set_line_anchored_start (
449
+ exprs. iter ( )
450
+ . take_while ( |e| {
451
+ e. is_line_anchored_start ( ) || e. is_all_assertions ( )
452
+ } )
453
+ . any ( |e| {
454
+ e. is_line_anchored_start ( )
455
+ } ) ) ;
456
+ info. set_line_anchored_end (
457
+ exprs. iter ( )
458
+ . rev ( )
459
+ . take_while ( |e| {
460
+ e. is_line_anchored_end ( ) || e. is_all_assertions ( )
461
+ } )
462
+ . any ( |e| {
463
+ e. is_line_anchored_end ( )
464
+ } ) ) ;
421
465
Hir {
422
466
kind : HirKind :: Concat ( exprs) ,
423
467
info : info,
@@ -439,6 +483,8 @@ impl Hir {
439
483
info. set_all_assertions ( true ) ;
440
484
info. set_anchored_start ( true ) ;
441
485
info. set_anchored_end ( true ) ;
486
+ info. set_line_anchored_start ( true ) ;
487
+ info. set_line_anchored_end ( true ) ;
442
488
info. set_any_anchored_start ( false ) ;
443
489
info. set_any_anchored_end ( false ) ;
444
490
info. set_match_empty ( false ) ;
@@ -457,6 +503,14 @@ impl Hir {
457
503
let x = info. is_anchored_end ( ) && e. is_anchored_end ( ) ;
458
504
info. set_anchored_end ( x) ;
459
505
506
+ let x = info. is_line_anchored_start ( )
507
+ && e. is_line_anchored_start ( ) ;
508
+ info. set_line_anchored_start ( x) ;
509
+
510
+ let x = info. is_line_anchored_end ( )
511
+ && e. is_line_anchored_end ( ) ;
512
+ info. set_line_anchored_end ( x) ;
513
+
460
514
let x =
461
515
info. is_any_anchored_start ( )
462
516
|| e. is_any_anchored_start ( ) ;
@@ -551,6 +605,32 @@ impl Hir {
551
605
self . info . is_anchored_end ( )
552
606
}
553
607
608
+ /// Return true if and only if this HIR is required to match from the
609
+ /// beginning of text or the beginning of a line. This includes expressions
610
+ /// like `^foo`, `(?m)^foo`, `^(foo|bar)`, `^(foo|bar)`, `(?m)^foo|^bar`
611
+ /// but not `^foo|bar` or `(?m)^foo|bar`.
612
+ ///
613
+ /// Note that if `is_anchored_start` is `true`, then
614
+ /// `is_line_anchored_start` will also be `true`. The reverse implication
615
+ /// is not true. For example, `(?m)^foo` is line anchored, but not
616
+ /// `is_anchored_start`.
617
+ pub fn is_line_anchored_start ( & self ) -> bool {
618
+ self . info . is_line_anchored_start ( )
619
+ }
620
+
621
+ /// Return true if and only if this HIR is required to match at the
622
+ /// end of text or the end of a line. This includes expressions like
623
+ /// `foo$`, `(?m)foo$`, `(foo|bar)$`, `(?m)(foo|bar)$`, `foo$|bar$`,
624
+ /// `(?m)(foo|bar)$`, but not `foo$|bar` or `(?m)foo$|bar`.
625
+ ///
626
+ /// Note that if `is_anchored_end` is `true`, then
627
+ /// `is_line_anchored_end` will also be `true`. The reverse implication
628
+ /// is not true. For example, `(?m)foo$` is line anchored, but not
629
+ /// `is_anchored_end`.
630
+ pub fn is_line_anchored_end ( & self ) -> bool {
631
+ self . info . is_line_anchored_end ( )
632
+ }
633
+
554
634
/// Return true if and only if this HIR contains any sub-expression that
555
635
/// is required to match at the beginning of text. Specifically, this
556
636
/// returns true if the `^` symbol (when multiline mode is disabled) or the
@@ -1299,7 +1379,7 @@ struct HirInfo {
1299
1379
///
1300
1380
/// If more attributes need to be added, it is OK to increase the size of
1301
1381
/// this as appropriate.
1302
- bools : u8 ,
1382
+ bools : u16 ,
1303
1383
}
1304
1384
1305
1385
// A simple macro for defining bitfield accessors/mutators.
@@ -1330,9 +1410,11 @@ impl HirInfo {
1330
1410
define_bool ! ( 1 , is_all_assertions, set_all_assertions) ;
1331
1411
define_bool ! ( 2 , is_anchored_start, set_anchored_start) ;
1332
1412
define_bool ! ( 3 , is_anchored_end, set_anchored_end) ;
1333
- define_bool ! ( 4 , is_any_anchored_start, set_any_anchored_start) ;
1334
- define_bool ! ( 5 , is_any_anchored_end, set_any_anchored_end) ;
1335
- define_bool ! ( 6 , is_match_empty, set_match_empty) ;
1413
+ define_bool ! ( 4 , is_line_anchored_start, set_line_anchored_start) ;
1414
+ define_bool ! ( 5 , is_line_anchored_end, set_line_anchored_end) ;
1415
+ define_bool ! ( 6 , is_any_anchored_start, set_any_anchored_start) ;
1416
+ define_bool ! ( 7 , is_any_anchored_end, set_any_anchored_end) ;
1417
+ define_bool ! ( 8 , is_match_empty, set_match_empty) ;
1336
1418
}
1337
1419
1338
1420
#[ cfg( test) ]
0 commit comments