@@ -48,6 +48,7 @@ fn consume_any(input: &str, what: impl Fn(char) -> bool) -> (&str, &str) {
48
48
/// [§3.1 Parsing]: https://gpuweb.github.io/gpuweb/wgsl/#parsing
49
49
fn consume_token ( input : & str , generic : bool ) -> ( Token < ' _ > , & str ) {
50
50
let mut chars = input. chars ( ) ;
51
+ let full_chars = input. chars ( ) ;
51
52
let cur = match chars. next ( ) {
52
53
Some ( c) => c,
53
54
None => return ( Token :: End , "" ) ,
@@ -82,33 +83,36 @@ fn consume_token(input: &str, generic: bool) -> (Token<'_>, &str) {
82
83
let og_chars = chars. as_str ( ) ;
83
84
match chars. next ( ) {
84
85
Some ( '/' ) => {
85
- let og_chars = chars. as_str ( ) ;
86
86
let documentation = if let Some ( end_position) = chars. position ( is_comment_end) {
87
- & og_chars [ ..end_position]
87
+ & full_chars . as_str ( ) [ ..end_position + 1 ]
88
88
} else {
89
- og_chars
89
+ full_chars . as_str ( )
90
90
} ;
91
91
( Token :: Comment ( documentation) , chars. as_str ( ) )
92
92
}
93
93
Some ( '*' ) => {
94
94
let mut depth = 1 ;
95
95
let mut prev = None ;
96
-
96
+ let mut nb_characters = 1 ;
97
97
for c in & mut chars {
98
98
match ( prev, c) {
99
99
( Some ( '*' ) , '/' ) => {
100
100
prev = None ;
101
101
depth -= 1 ;
102
+ nb_characters += 1 ;
102
103
if depth == 0 {
103
- return ( Token :: Trivia , chars. as_str ( ) ) ;
104
+ let doc = & full_chars. as_str ( ) [ ..nb_characters + 1 ] ;
105
+ return ( Token :: Comment ( doc) , chars. as_str ( ) ) ;
104
106
}
105
107
}
106
108
( Some ( '/' ) , '*' ) => {
107
109
prev = None ;
108
110
depth += 1 ;
111
+ nb_characters += 1 ;
109
112
}
110
113
_ => {
111
114
prev = Some ( c) ;
115
+ nb_characters += 1 ;
112
116
}
113
117
}
114
118
}
@@ -309,17 +313,25 @@ impl<'a> Lexer<'a> {
309
313
///
310
314
/// See [`consume_token`] for the meaning of `generic`.
311
315
fn next_impl ( & mut self , generic : bool ) -> TokenSpan < ' a > {
316
+ self . next_until (
317
+ |token| !matches ! ( token, Token :: Trivia | Token :: Comment ( _) ) ,
318
+ generic,
319
+ )
320
+ }
321
+
322
+ /// Return the next token from `self` for which `stop_at` returns true.
323
+ ///
324
+ /// See [`consume_token`] for the meaning of `generic`.
325
+ pub fn next_until ( & mut self , stop_at : fn ( Token ) -> bool , generic : bool ) -> TokenSpan < ' a > {
312
326
let mut start_byte_offset = self . current_byte_offset ( ) ;
313
327
loop {
314
328
let ( token, rest) = consume_token ( self . input , generic) ;
315
329
self . input = rest;
316
- match token {
317
- Token :: Trivia | Token :: Comment ( _) => start_byte_offset = self . current_byte_offset ( ) ,
318
- _ => {
319
- self . last_end_offset = self . current_byte_offset ( ) ;
320
- return ( token, self . span_from ( start_byte_offset) ) ;
321
- }
330
+ if stop_at ( token) {
331
+ self . last_end_offset = self . current_byte_offset ( ) ;
332
+ return ( token, self . span_from ( start_byte_offset) ) ;
322
333
}
334
+ start_byte_offset = self . current_byte_offset ( ) ;
323
335
}
324
336
}
325
337
@@ -477,7 +489,11 @@ impl<'a> Lexer<'a> {
477
489
fn sub_test ( source : & str , expected_tokens : & [ Token ] ) {
478
490
let mut lex = Lexer :: new ( source) ;
479
491
for & token in expected_tokens {
480
- assert_eq ! ( lex. next( ) . 0 , token) ;
492
+ assert_eq ! (
493
+ lex. next_until( |token| !matches!( token, Token :: Trivia ) , false )
494
+ . 0 ,
495
+ token
496
+ ) ;
481
497
}
482
498
assert_eq ! ( lex. next( ) . 0 , Token :: End ) ;
483
499
}
@@ -763,3 +779,60 @@ fn test_variable_decl() {
763
779
] ,
764
780
) ;
765
781
}
782
+
783
+ #[ test]
784
+ fn test_comments ( ) {
785
+ sub_test ( "// Single comment" , & [ Token :: Comment ( "// Single comment" ) ] ) ;
786
+ sub_test (
787
+ "/* multi
788
+ line
789
+ comment */" ,
790
+ & [ Token :: Comment (
791
+ "/* multi
792
+ line
793
+ comment */" ,
794
+ ) ] ,
795
+ ) ;
796
+ sub_test (
797
+ "/* multi
798
+ line
799
+ comment */
800
+ // and another" ,
801
+ & [
802
+ Token :: Comment (
803
+ "/* multi
804
+ line
805
+ comment */" ,
806
+ ) ,
807
+ Token :: Comment ( "// and another" ) ,
808
+ ] ,
809
+ ) ;
810
+ }
811
+
812
+ #[ test]
813
+ fn test_comment_nested ( ) {
814
+ sub_test (
815
+ "/*
816
+ a comment with nested one /*
817
+ nested comment
818
+ */
819
+ */
820
+ const a : i32 = 2;" ,
821
+ & [
822
+ Token :: Comment (
823
+ "/*
824
+ a comment with nested one /*
825
+ nested comment
826
+ */
827
+ */" ,
828
+ ) ,
829
+ Token :: Word ( "const" ) ,
830
+ Token :: Word ( "a" ) ,
831
+ Token :: Separator ( ':' ) ,
832
+ Token :: Word ( "i32" ) ,
833
+ Token :: Operation ( '=' ) ,
834
+ Token :: Number ( Ok ( Number :: AbstractInt ( 2 ) ) ) ,
835
+ Token :: Separator ( ';' ) ,
836
+ ] ,
837
+ ) ;
838
+ }
0 commit comments