@@ -4,6 +4,8 @@ use std::mem;
4
4
use std:: num:: NonZeroU32 ;
5
5
use std:: slice;
6
6
7
+ use bitvec:: vec:: BitVec ;
8
+
7
9
use crate :: file:: Context ;
8
10
use crate :: file:: File ;
9
11
use crate :: file:: Span ;
@@ -15,6 +17,8 @@ use crate::spec::Lexeme;
15
17
use crate :: spec:: Spec ;
16
18
use crate :: token;
17
19
20
+ use super :: Token ;
21
+
18
22
/// A tree-like stream of tokens.
19
23
///
20
24
/// This is type returned by by [`File::lex()`] when lexing succeeds.
@@ -26,6 +30,8 @@ pub struct Stream<'ctx> {
26
30
pub ( crate ) toks : Vec < rt:: Token > ,
27
31
pub ( crate ) meta_idx : Vec < token:: Id > ,
28
32
pub ( crate ) meta : Vec < rt:: Metadata > ,
33
+
34
+ pub ( crate ) silent : BitVec , // Set of lexemes that have been silenced.
29
35
}
30
36
31
37
impl < ' ctx > Stream < ' ctx > {
@@ -65,6 +71,28 @@ impl<'ctx> Stream<'ctx> {
65
71
self . token_at_hint ( id, meta_hint) . unwrap ( )
66
72
}
67
73
74
+ /// Returns whether the given lexeme has been slienced.
75
+ pub fn is_silenced < R > ( & self , lexeme : Lexeme < R > ) -> bool {
76
+ self . silent . get ( lexeme. index ( ) ) . is_some_and ( |p| * p)
77
+ }
78
+
79
+ /// Silences the given lexeme in this stream.
80
+ ///
81
+ /// This means that all tokens with this lexeme will be skipped when yielded
82
+ /// from [`Cursor::next()`]. Use [`Cursor::noisy()`] to yield all tokens,
83
+ /// including silenced ones.
84
+ ///
85
+ /// This is useful for tokens that can appear anywhere in the stream, but
86
+ /// which should be ignored unless they are being explicitly searched for.
87
+ /// This is useful, for example, for [`rule::LineEnd`] tokens.
88
+ pub fn silence < R > ( & mut self , lexeme : Lexeme < R > ) {
89
+ let idx = lexeme. index ( ) ;
90
+ if self . silent . len ( ) <= idx {
91
+ self . silent . resize ( idx + 1 , false ) ;
92
+ }
93
+ self . silent . set ( idx, true ) ;
94
+ }
95
+
68
96
/// Returns the last token pushed to this stream.
69
97
pub ( crate ) fn last_token ( & self ) -> token:: Any {
70
98
let mut cursor = self . cursor ( ) ;
@@ -296,6 +324,22 @@ impl<'lex> Cursor<'lex> {
296
324
self . cursor >= self . end
297
325
}
298
326
327
+ /// Returns an iterator that yields all of the values in this cursor,
328
+ /// including silenced ones.
329
+ pub fn noisy ( & mut self ) -> impl Iterator < Item = token:: Any < ' lex > > + ' _ {
330
+ iter:: from_fn ( move || loop {
331
+ if self . is_empty ( ) {
332
+ return None ;
333
+ }
334
+
335
+ let next = self . stream . token_at_hint ( self . id ( ) , self . meta_cursor ) ;
336
+ self . step_forward ( ) ;
337
+ if next. is_some ( ) {
338
+ return next;
339
+ }
340
+ } )
341
+ }
342
+
299
343
/// Returns the next token under the cursor without consuming it.
300
344
pub fn peek_any ( & self ) -> Option < token:: Any < ' lex > > {
301
345
let mut copy = * self ;
@@ -514,18 +558,8 @@ impl fmt::Debug for Cursor<'_> {
514
558
impl < ' lex > Iterator for Cursor < ' lex > {
515
559
type Item = token:: Any < ' lex > ;
516
560
fn next ( & mut self ) -> Option < Self :: Item > {
517
- loop {
518
- if self . is_empty ( ) {
519
- return None ;
520
- }
521
-
522
- let next = self . stream . token_at_hint ( self . id ( ) , self . meta_cursor ) ;
523
- self . step_forward ( ) ;
524
-
525
- if next. is_some ( ) {
526
- return next;
527
- }
528
- }
561
+ let stream = self . stream ;
562
+ self . noisy ( ) . find ( |next| !stream. is_silenced ( next. lexeme ( ) ) )
529
563
}
530
564
}
531
565
@@ -623,24 +657,30 @@ pub mod switch {
623
657
where
624
658
X : Impl < ' lex , T > ,
625
659
{
626
- let Some ( next) = cursor. next ( ) else {
627
- report. builtins ( cursor. spec ( ) ) . expected (
628
- self . 0 . lexemes ( 0 ) ,
629
- Lexeme :: eof ( ) ,
630
- cursor. end ( ) ,
631
- ) ;
660
+ loop {
661
+ let Some ( next) = cursor. noisy ( ) . next ( ) else {
662
+ report. builtins ( cursor. spec ( ) ) . expected (
663
+ self . 0 . lexemes ( 0 ) ,
664
+ Lexeme :: eof ( ) ,
665
+ cursor. end ( ) ,
666
+ ) ;
632
667
633
- return None ;
634
- } ;
668
+ return None ;
669
+ } ;
635
670
636
- if let Some ( found) = self . 0 . apply ( next, cursor) {
637
- return Some ( found) ;
638
- }
671
+ if let Some ( found) = self . 0 . apply ( next, cursor) {
672
+ return Some ( found) ;
673
+ }
639
674
640
- report
641
- . builtins ( cursor. spec ( ) )
642
- . expected ( self . 0 . lexemes ( 0 ) , next, next) ;
643
- None
675
+ if cursor. stream . is_silenced ( next. lexeme ( ) ) {
676
+ continue ;
677
+ }
678
+
679
+ report
680
+ . builtins ( cursor. spec ( ) )
681
+ . expected ( self . 0 . lexemes ( 0 ) , next, next) ;
682
+ return None ;
683
+ }
644
684
}
645
685
646
686
/// Takes the next token from `cursor` and matches it against this switch.
0 commit comments