86 lines
2.6 KiB
Rust
86 lines
2.6 KiB
Rust
use crate::keywords::{
|
|
has_export, is_function_end, is_function_start, is_procedure_end, is_procedure_start,
|
|
};
|
|
use crate::models::{ParsedProcedure, SourceRange};
|
|
|
|
pub fn extract_procedures(source: &str) -> Vec<ParsedProcedure> {
|
|
let mut result = Vec::new();
|
|
let mut current_index: Option<usize> = None;
|
|
for (index, line) in source.lines().enumerate() {
|
|
let line_no = index + 1;
|
|
if is_procedure_start(line) || is_function_start(line) {
|
|
let is_function = is_function_start(line);
|
|
let name = extract_routine_name(line, is_function);
|
|
result.push(ParsedProcedure {
|
|
name,
|
|
export: has_export(line),
|
|
is_function,
|
|
parameters: extract_parameters(line),
|
|
source_range: SourceRange {
|
|
line_start: line_no,
|
|
line_end: line_no,
|
|
column_start: 1,
|
|
column_end: line.len() + 1,
|
|
},
|
|
});
|
|
current_index = Some(result.len() - 1);
|
|
} else if routine_ended(line) {
|
|
if let Some(procedure_index) = current_index.take() {
|
|
result[procedure_index].source_range.line_end = line_no;
|
|
result[procedure_index].source_range.column_end = line.len() + 1;
|
|
}
|
|
}
|
|
}
|
|
result
|
|
}
|
|
|
|
pub fn routine_ended(line: &str) -> bool {
|
|
is_procedure_end(line) || is_function_end(line)
|
|
}
|
|
|
|
pub fn extract_name_from_header(line: &str) -> String {
|
|
line.split_whitespace()
|
|
.nth(1)
|
|
.unwrap_or("")
|
|
.split('(')
|
|
.next()
|
|
.unwrap_or("")
|
|
.to_string()
|
|
}
|
|
|
|
fn extract_routine_name(line: &str, is_function: bool) -> String {
|
|
let trimmed = line.trim();
|
|
let prefixes = if is_function {
|
|
vec!["Функция", "Function"]
|
|
} else {
|
|
vec!["Процедура", "Procedure"]
|
|
};
|
|
for prefix in prefixes {
|
|
if trimmed.to_lowercase().starts_with(&prefix.to_lowercase()) {
|
|
return trimmed[prefix.len()..]
|
|
.trim()
|
|
.split('(')
|
|
.next()
|
|
.unwrap_or("")
|
|
.trim()
|
|
.to_string();
|
|
}
|
|
}
|
|
String::new()
|
|
}
|
|
|
|
fn extract_parameters(line: &str) -> Vec<String> {
|
|
let Some(start) = line.find('(') else {
|
|
return Vec::new();
|
|
};
|
|
let Some(end) = line[start + 1..].find(')') else {
|
|
return Vec::new();
|
|
};
|
|
let params = &line[start + 1..start + 1 + end];
|
|
params
|
|
.split(',')
|
|
.map(|p| p.trim().to_string())
|
|
.filter(|p| !p.is_empty())
|
|
.collect()
|
|
}
|