fix block comment parsing with proper nesting support
This commit is contained in:
parent
80017cf84f
commit
23594548ed
|
|
@ -88,36 +88,40 @@ fn is_ident(s: &str) -> bool {
|
||||||
|
|
||||||
pub fn classify_document(text: &str) -> Vec<ClassifiedLine> {
|
pub fn classify_document(text: &str) -> Vec<ClassifiedLine> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let mut in_block_comment = false;
|
let mut depth: usize = 0;
|
||||||
|
|
||||||
for (i, line) in text.lines().enumerate() {
|
for (i, line) in text.lines().enumerate() {
|
||||||
if in_block_comment {
|
let was_in_comment = depth > 0;
|
||||||
let cl = ClassifiedLine { index: i, kind: LineKind::Comment, content: line.to_string() };
|
depth = scan_comment_depth(line, depth);
|
||||||
if line.contains("*/") {
|
|
||||||
in_block_comment = false;
|
|
||||||
}
|
|
||||||
result.push(cl);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let trimmed = line.trim();
|
if was_in_comment || line.trim().starts_with("/*") {
|
||||||
|
|
||||||
if trimmed.starts_with("/*") {
|
|
||||||
if trimmed.contains("*/") && trimmed.find("*/").unwrap() > trimmed.find("/*").unwrap() {
|
|
||||||
// single-line block comment
|
|
||||||
} else {
|
|
||||||
in_block_comment = true;
|
|
||||||
}
|
|
||||||
result.push(ClassifiedLine { index: i, kind: LineKind::Comment, content: line.to_string() });
|
result.push(ClassifiedLine { index: i, kind: LineKind::Comment, content: line.to_string() });
|
||||||
continue;
|
} else {
|
||||||
|
result.push(classify_line(i, line));
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(classify_line(i, line));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scan_comment_depth(line: &str, mut depth: usize) -> usize {
|
||||||
|
let bytes = line.as_bytes();
|
||||||
|
let len = bytes.len();
|
||||||
|
let mut i = 0;
|
||||||
|
while i < len.saturating_sub(1) {
|
||||||
|
if bytes[i] == b'/' && bytes[i + 1] == b'*' {
|
||||||
|
depth += 1;
|
||||||
|
i += 2;
|
||||||
|
} else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
|
||||||
|
depth = depth.saturating_sub(1);
|
||||||
|
i += 2;
|
||||||
|
} else {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
depth
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -199,4 +203,22 @@ mod tests {
|
||||||
assert_eq!(lines[0].kind, LineKind::Comment);
|
assert_eq!(lines[0].kind, LineKind::Comment);
|
||||||
assert_eq!(lines[1].kind, LineKind::Eval);
|
assert_eq!(lines[1].kind, LineKind::Eval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nested_block_comments() {
|
||||||
|
let lines = classify_document("/* outer /* inner */ still comment */\nlet x = 5");
|
||||||
|
assert_eq!(lines[0].kind, LineKind::Comment);
|
||||||
|
assert_eq!(lines[1].kind, LineKind::Cordial);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nested_multiline_block_comments() {
|
||||||
|
let doc = "/* outer\n/* inner */\nstill in outer\n*/\nlet x = 5";
|
||||||
|
let lines = classify_document(doc);
|
||||||
|
assert_eq!(lines[0].kind, LineKind::Comment);
|
||||||
|
assert_eq!(lines[1].kind, LineKind::Comment);
|
||||||
|
assert_eq!(lines[2].kind, LineKind::Comment);
|
||||||
|
assert_eq!(lines[3].kind, LineKind::Comment);
|
||||||
|
assert_eq!(lines[4].kind, LineKind::Cordial);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue