diff --git a/src/bong/lexer.rs b/src/bong/lexer.rs index 7102fe8..ccf1f64 100644 --- a/src/bong/lexer.rs +++ b/src/bong/lexer.rs @@ -116,12 +116,15 @@ fn make_number>( *col += 1; if result.contains(&'.') { iter.next(); - return Err(TokenError { + let error = TokenError { error: "unexpected token".to_string(), col: *col, line: *line, - }); + }; + *col += 1; + return Err(error); } + *col += 1; iter.next().expect(NO_MUT_PEEK_NEXT_MESSAGE); result.push('.'); @@ -209,13 +212,67 @@ fn make_comment>( *col += 2; match second_character { '/' => loop { + *col += 1; match iter.peek() { Some('\n') | None => break Ok(Token::SlComment(String::from_iter(result))), _ => result.push(iter.next().expect(NO_MUT_PEEK_NEXT_MESSAGE)), } }, '*' => { - todo!(); + let mut current = if let Some(c) = iter.next() { + c + } else { + return Err(TokenError { + error: "unexpected EOF".to_string(), + col: *col, + line: *line, + }); + }; + let mut nesting = 0; + loop { + if let Some(next) = iter.peek() { + println!("{current:?}|{next:?}|{result:?}"); + if current == '/' { + if *next == '*' { + result.push(current); + current = iter.next().expect(NO_MUT_PEEK_NEXT_MESSAGE); + result.push(current); + current = iter.next().expect(NO_MUT_PEEK_NEXT_MESSAGE); + nesting += 1; + } + } else if current == '*' { + if *next == '/' { + result.push(current); + current = iter.next().expect(NO_MUT_PEEK_NEXT_MESSAGE); + result.push(current); + + if nesting == 0 { + break Ok(Token::MlComment(String::from_iter(result))); + } + + if iter.peek().is_none() { + return Err(TokenError { + error: "unexpected EOF".to_string(), + col: *col, + line: *line, + }); + } + current = iter.next().expect(NO_MUT_PEEK_NEXT_MESSAGE); + + nesting -= 1; + } + } else { + result.push(current); + current = iter.next().expect(NO_MUT_PEEK_NEXT_MESSAGE); + } + } else { + break Err(TokenError { + error: "unexpected EOF".to_string(), + col: *col, + line: *line, + }); + } + } } c => Err(TokenError { error: format!("unexpected token {c}"), @@ -356,4 +413,21 @@ mod tests { ] ) } + + #[test] + fn unnested_multiline_comment() { + let text = "/* hello */"; + let tokens = lexer(text); + assert_eq!(tokens, vec![Token::MlComment("/* hello */".to_string()),]) + } + + #[test] + fn nested_multiline_comment() { + let text = "/* /* hello */ */"; + let tokens = lexer(text); + assert_eq!( + tokens, + vec![Token::MlComment("/* /* hello */ */".to_string()),] + ) + } }