fn remove_block_comments(source: &str) -> String {
let mut result = String::new();
let bytes = source.as_bytes();
let mut i = 0;
while i < bytes.len() {
if i + 1 < bytes.len() && bytes[i] == b'/' && bytes[i + 1] == b'*' {
i += 2;
while i + 1 < bytes.len() {
if bytes[i] == b'*' && bytes[i + 1] == b'/' {
i += 2;
break;
}
i += 1;
}
} else {
result.push(bytes[i] as char);
i += 1;
}
}
result
}
fn remove_line_comment(line: &str) -> String {
let mut in_quotes = false;
let mut quote_char = '\0';
let mut escape = false;
let mut index = None;
let mut chars = line.char_indices().peekable();
while let Some((i, c)) = chars.next() {
if escape {
escape = false;
continue;
}
if c == '\\' {
escape = true;
continue;
}
if matches!(c, '"' | '\'' | '`') {
if in_quotes && quote_char == c {
in_quotes = false;
} else if !in_quotes {
in_quotes = true;
quote_char = c;
}
}
if !in_quotes && c == '/' {
if let Some(&(_, nx)) = chars.peek() {
if nx == '/' {
index = Some(i);
break;
}
}
}
}
if let Some(pos) = index {
line[..pos].to_string()
} else {
line.to_string()
}
}
fn unify_partial_usage_lines(lines: &[String]) -> Vec<String> {
let mut result = Vec::new();
let mut i = 0;
while i < lines.len() {
let mut current_line = lines[i].clone();
if i + 1 < lines.len() {
let trimmed = current_line.trim_end();
let next_trimmed = lines[i + 1].trim_start();
let next_trimmed_strict = lines[i + 1].trim();
if trimmed.ends_with('}') && next_trimmed_strict == ")" {
current_line.push(' ');
current_line.push_str(next_trimmed_strict);
i += 1;
} else {
let ends_with_paren = trimmed.ends_with(')');
let ends_with_combo = trimmed.ends_with(")(");
let next_starts_pair = next_trimmed.starts_with('(') || next_trimmed.starts_with('[');
if (ends_with_paren || ends_with_combo) && next_starts_pair {
current_line.push(' ');
current_line.push_str(next_trimmed);
i += 1;
}
}
}
result.push(current_line);
i += 1;
}
result
}
pub fn gather_statements(source: &str, verbose: bool) -> Vec<String> {
let no_block = remove_block_comments(source);
let mut raw_lines = Vec::new();
for line in no_block.lines() {
let stripped = remove_line_comment(line);
let trimmed = stripped.trim();
if !trimmed.is_empty() { raw_lines.push(trimmed.to_string()); }
}
let merged_lines = unify_partial_usage_lines(&raw_lines);
let merged_str = merged_lines.join("\n");
let chars: Vec<char> = merged_str.chars().collect();
let mut statements = Vec::new();
let mut current = String::new();
let mut in_quotes = false;
let mut quote_char = '\0';
let mut bracket_depth = 0;
let mut paren_depth = 0;
let mut in_brace_lambda = false;
let mut brace_depth = 0;
let mut i = 0;
while i < chars.len() {
let c = chars[i];
current.push(c);
match c {
'"' | '\'' | '`' => {
if in_quotes && quote_char == c {
in_quotes = false;
} else if !in_quotes {
in_quotes = true;
quote_char = c;
}
}
'(' => { if !in_quotes { paren_depth += 1; } }
')' => { if !in_quotes && paren_depth > 0 { paren_depth -= 1; } }
'[' => { if !in_quotes { bracket_depth += 1; } }
']' => { if !in_quotes && bracket_depth > 0 { bracket_depth -= 1; } }
'{' => {
if !in_quotes {
if current.contains("=>") {
in_brace_lambda = true;
brace_depth = 1;
} else if in_brace_lambda {
brace_depth += 1;
}
}
}
'}' => {
if in_brace_lambda {
if brace_depth > 0 { brace_depth -= 1; }
if brace_depth == 0 {
in_brace_lambda = false;
let st = current.trim();
if !st.is_empty() { statements.push(st.to_string()); }
current.clear();
i += 1;
continue;
}
}
}
'=' => {
if i + 1 < chars.len() && chars[i + 1] == '>' {
current.push('>');
i += 1;
in_brace_lambda = true;
brace_depth = 0;
} else if i + 1 < chars.len() && chars[i + 1] == '=' {
current.push('=');
i += 1;
}
}
'>' | '<' => {
if !in_quotes && i + 1 < chars.len() && chars[i + 1] == '=' {
current.push(chars[i + 1]);
i += 1;
}
}
'\n' => {
if !in_quotes && !in_brace_lambda && bracket_depth == 0 && paren_depth == 0 {
let st = current.trim();
if !st.is_empty() { statements.push(st.to_string()); }
current.clear();
}
}
_ => {}
}
i += 1;
}
let leftover = current.trim();
if !leftover.is_empty() { statements.push(leftover.to_string()); }
if verbose { eprintln!("[gather_statements] final => {:#?}", statements); }
statements
}