use log::debug;
pub fn remove_comments(content: &str) -> String {
enum State {
Normal,
MaybeSlash, LineComment, BlockComment, MaybeEndBlockComment, StringLiteral, StringEscape, CharLiteral, CharEscape, }
let mut result = String::with_capacity(content.len());
let mut state = State::Normal;
let chars = content.chars().peekable();
for c in chars {
match state {
State::Normal => match c {
'/' => state = State::MaybeSlash,
'"' => {
state = State::StringLiteral;
result.push(c);
}
'\'' => {
state = State::CharLiteral;
result.push(c);
}
_ => result.push(c),
},
State::MaybeSlash => match c {
'/' => state = State::LineComment,
'*' => state = State::BlockComment,
_ => {
result.push('/');
match c {
'"' => {
state = State::StringLiteral;
result.push(c);
}
'\'' => {
state = State::CharLiteral;
result.push(c);
}
'/' => {
result.push(c);
}
_ => {
result.push(c);
state = State::Normal; }
}
}
},
State::LineComment => {
if c == '\n' {
result.push(c); state = State::Normal;
}
}
State::BlockComment => {
if c == '*' {
state = State::MaybeEndBlockComment;
}
}
State::MaybeEndBlockComment => match c {
'/' => state = State::Normal,
'*' => {} _ => state = State::BlockComment, },
State::StringLiteral => {
result.push(c);
match c {
'"' => state = State::Normal,
'\\' => state = State::StringEscape,
_ => {}
}
}
State::StringEscape => {
result.push(c); state = State::StringLiteral; }
State::CharLiteral => {
result.push(c);
match c {
'\'' => state = State::Normal,
'\\' => state = State::CharEscape,
_ => {} }
}
State::CharEscape => {
result.push(c); state = State::CharLiteral; }
}
}
if matches!(state, State::MaybeSlash) {
result.push('/');
}
let processed_result = result .lines()
.map(|line| line.trim_end()) .collect::<Vec<&str>>()
.join("\n") .trim_matches(|c: char| c == '\r' || c == '\n') .to_string();
debug!(
"Comment removal applied. Original len: {}, New len: {}",
content.len(),
processed_result.len() );
processed_result }