@@ -48,6 +48,7 @@ fn consume_any(input: &str, what: impl Fn(char) -> bool) -> (&str, &str) {
4848/// [§3.1 Parsing]: https://gpuweb.github.io/gpuweb/wgsl/#parsing
4949fn consume_token ( input : & str , generic : bool ) -> ( Token < ' _ > , & str ) {
5050 let mut chars = input. chars ( ) ;
51+ let full_chars = input. chars ( ) ;
5152 let cur = match chars. next ( ) {
5253 Some ( c) => c,
5354 None => return ( Token :: End , "" ) ,
@@ -82,33 +83,36 @@ fn consume_token(input: &str, generic: bool) -> (Token<'_>, &str) {
8283 let og_chars = chars. as_str ( ) ;
8384 match chars. next ( ) {
8485 Some ( '/' ) => {
85- let og_chars = chars. as_str ( ) ;
8686 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 ]
8888 } else {
89- og_chars
89+ full_chars . as_str ( )
9090 } ;
9191 ( Token :: Comment ( documentation) , chars. as_str ( ) )
9292 }
9393 Some ( '*' ) => {
9494 let mut depth = 1 ;
9595 let mut prev = None ;
96-
96+ let mut nb_characters = 1 ;
9797 for c in & mut chars {
9898 match ( prev, c) {
9999 ( Some ( '*' ) , '/' ) => {
100100 prev = None ;
101101 depth -= 1 ;
102+ nb_characters += 1 ;
102103 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 ( ) ) ;
104106 }
105107 }
106108 ( Some ( '/' ) , '*' ) => {
107109 prev = None ;
108110 depth += 1 ;
111+ nb_characters += 1 ;
109112 }
110113 _ => {
111114 prev = Some ( c) ;
115+ nb_characters += 1 ;
112116 }
113117 }
114118 }
@@ -309,17 +313,25 @@ impl<'a> Lexer<'a> {
309313 ///
310314 /// See [`consume_token`] for the meaning of `generic`.
311315 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 > {
312326 let mut start_byte_offset = self . current_byte_offset ( ) ;
313327 loop {
314328 let ( token, rest) = consume_token ( self . input , generic) ;
315329 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) ) ;
322333 }
334+ start_byte_offset = self . current_byte_offset ( ) ;
323335 }
324336 }
325337
@@ -477,7 +489,11 @@ impl<'a> Lexer<'a> {
477489fn sub_test ( source : & str , expected_tokens : & [ Token ] ) {
478490 let mut lex = Lexer :: new ( source) ;
479491 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+ ) ;
481497 }
482498 assert_eq ! ( lex. next( ) . 0 , Token :: End ) ;
483499}
@@ -763,3 +779,60 @@ fn test_variable_decl() {
763779 ] ,
764780 ) ;
765781}
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