diff --git a/src/lexic/scanner/new_comment.rs b/src/lexic/scanner/new_comment.rs index b373554..b680911 100644 --- a/src/lexic/scanner/new_comment.rs +++ b/src/lexic/scanner/new_comment.rs @@ -35,7 +35,7 @@ fn scan_any_except_new_line( pub fn scan_multiline(chars: &Vec, start_pos: usize) -> LexResult { match multiline_impl(chars, start_pos + 2) { Some((value, next_position)) => LexResult::Some( - Token::new_multiline_comment(value, start_pos), + Token::new_multiline_comment(value.iter().collect(), start_pos), next_position, ), None => { @@ -49,17 +49,39 @@ pub fn scan_multiline(chars: &Vec, start_pos: usize) -> LexResult { } } -fn multiline_impl(chars: &Vec, start_pos: usize) -> Option<(String, usize)> { +fn multiline_impl(chars: &Vec, start_pos: usize) -> Option<(Vec, usize)> { let mut current_position = start_pos; let mut result = Vec::::new(); loop { match chars.get(current_position) { Some('/') => { - // TODO: Check for a nested comment instead of - // appending - result.push('/'); - current_position += 1; + + match chars.get(current_position + 1) { + Some('*') => { + // Scan nested comment + let (mut nested, next_position) = match multiline_impl(chars, current_position + 2) + { + Some(v) => v, + None => { + // The nested comment is not closed. + return None; + } + }; + result.push('/'); + result.push('*'); + result.append(&mut nested); + result.push('*'); + result.push('/'); + current_position = next_position; + } + Some(c) => { + // Append both characters + result.push('/'); + result.push(*c); + } + None => return None, + } } Some('*') => { // Check for the end of a comment @@ -67,7 +89,7 @@ fn multiline_impl(chars: &Vec, start_pos: usize) -> Option<(String, usize) Some('/') => { // Create and return the token, // ignoring the `*/` - return Some((result.iter().collect(), current_position + 2)); + return Some((result, current_position + 2)); } Some(c) => { // Append both and continue @@ -87,7 +109,6 @@ fn multiline_impl(chars: &Vec, start_pos: usize) -> Option<(String, usize) current_position += 1; } None => { - // Throw an error // TODO: Also return the position where this token ends, // to display better error messages. // Requires LexError to implement an end_position field @@ -231,4 +252,22 @@ mod tests { } } } + + #[test] + fn shoud_scan_nested_multiline_comments() { + let input = str_to_vec("/* my /* comment */ */"); + + let result = scan_multiline(&input, 0); + match result { + LexResult::Some(t, next) => { + assert_eq!(22, next); + assert_eq!(" my /* comment */ ", t.value); + assert_eq!(0, t.position); + assert_eq!(TokenType::MultilineComment, t.token_type); + } + _ => { + panic!("Expected a multine comment") + } + } + } }