@@ -832,22 +832,23 @@ impl<'a> Tokenizer<'a> {
832
832
chars : & mut Peekable < Chars < ' _ > > ,
833
833
) -> Result < Option < Token > , TokenizerError > {
834
834
let mut s = String :: new ( ) ;
835
- let mut maybe_closing_comment = false ;
836
- // TODO: deal with nested comments
835
+ let mut nested = 1 ;
836
+ let mut last_ch = ' ' ;
837
+
837
838
loop {
838
839
match chars. next ( ) {
839
840
Some ( ch) => {
840
- if maybe_closing_comment {
841
- if ch == '/' {
841
+ if last_ch == '/' && ch == '*' {
842
+ nested += 1 ;
843
+ } else if last_ch == '*' && ch == '/' {
844
+ nested -= 1 ;
845
+ if nested == 0 {
846
+ s. pop ( ) ;
842
847
break Ok ( Some ( Token :: Whitespace ( Whitespace :: MultiLineComment ( s) ) ) ) ;
843
- } else {
844
- s. push ( '*' ) ;
845
848
}
846
849
}
847
- maybe_closing_comment = ch == '*' ;
848
- if !maybe_closing_comment {
849
- s. push ( ch) ;
850
- }
850
+ s. push ( ch) ;
851
+ last_ch = ch;
851
852
}
852
853
None => break self . tokenizer_error ( "Unexpected EOF while in a multi-line comment" ) ,
853
854
}
@@ -1355,6 +1356,23 @@ mod tests {
1355
1356
compare ( expected, tokens) ;
1356
1357
}
1357
1358
1359
+ #[ test]
1360
+ fn tokenize_nested_multiline_comment ( ) {
1361
+ let sql = String :: from ( "0/*multi-line\n * \n /* comment \n /*comment*/*/ */ /comment*/1" ) ;
1362
+
1363
+ let dialect = GenericDialect { } ;
1364
+ let mut tokenizer = Tokenizer :: new ( & dialect, & sql) ;
1365
+ let tokens = tokenizer. tokenize ( ) . unwrap ( ) ;
1366
+ let expected = vec ! [
1367
+ Token :: Number ( "0" . to_string( ) , false ) ,
1368
+ Token :: Whitespace ( Whitespace :: MultiLineComment (
1369
+ "multi-line\n * \n /* comment \n /*comment*/*/ */ /comment" . to_string( ) ,
1370
+ ) ) ,
1371
+ Token :: Number ( "1" . to_string( ) , false ) ,
1372
+ ] ;
1373
+ compare ( expected, tokens) ;
1374
+ }
1375
+
1358
1376
#[ test]
1359
1377
fn tokenize_multiline_comment_with_even_asterisks ( ) {
1360
1378
let sql = String :: from ( "\n /** Comment **/\n " ) ;
0 commit comments