Initial SFERA platform baseline
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
use crate::keywords::{is_function_start, is_procedure_start};
|
||||
use crate::models::{ParsedCall, SourceRange};
|
||||
use crate::parser::{extract_name_from_header, routine_ended};
|
||||
|
||||
pub fn extract_calls(source: &str) -> Vec<ParsedCall> {
|
||||
let mut result = Vec::new();
|
||||
let mut current_routine: Option<String> = None;
|
||||
for (index, line) in source.lines().enumerate() {
|
||||
let line_no = index + 1;
|
||||
let trimmed = strip_inline_comment(line).trim();
|
||||
if is_procedure_start(trimmed) || is_function_start(trimmed) {
|
||||
current_routine = Some(extract_name_from_header(trimmed));
|
||||
continue;
|
||||
}
|
||||
if routine_ended(trimmed) {
|
||||
current_routine = None;
|
||||
continue;
|
||||
}
|
||||
let Some(caller) = current_routine.as_ref() else {
|
||||
continue;
|
||||
};
|
||||
if let Some(callee) = simple_call_name(trimmed).or_else(|| condition_call_name(trimmed)) {
|
||||
result.push(ParsedCall {
|
||||
caller: caller.clone(),
|
||||
callee,
|
||||
source_range: SourceRange {
|
||||
line_start: line_no,
|
||||
line_end: line_no,
|
||||
column_start: 1,
|
||||
column_end: line.len() + 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn simple_call_name(line: &str) -> Option<String> {
|
||||
if !line.ends_with(';') || !line.contains('(') || !line.contains(')') || line.contains('.') {
|
||||
return None;
|
||||
}
|
||||
let call_expr = line.split('=').next_back().unwrap_or(line).trim();
|
||||
let name = call_expr.split('(').next()?.trim();
|
||||
if name.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(name.to_string())
|
||||
}
|
||||
|
||||
fn condition_call_name(line: &str) -> Option<String> {
|
||||
let lowered = line.to_lowercase();
|
||||
let is_condition = (lowered.starts_with("если ") && lowered.contains(" тогда"))
|
||||
|| (lowered.starts_with("if ") && lowered.contains(" then"));
|
||||
if !is_condition || line.contains('.') {
|
||||
return None;
|
||||
}
|
||||
let before_then = if let Some(index) = lowered.find(" тогда") {
|
||||
&line[..index]
|
||||
} else if let Some(index) = lowered.find(" then") {
|
||||
&line[..index]
|
||||
} else {
|
||||
line
|
||||
};
|
||||
let name_part = before_then.split('(').next()?.split_whitespace().last()?;
|
||||
if name_part.eq_ignore_ascii_case("Если") || name_part.eq_ignore_ascii_case("If") {
|
||||
return None;
|
||||
}
|
||||
Some(name_part.to_string())
|
||||
}
|
||||
|
||||
fn strip_inline_comment(line: &str) -> &str {
|
||||
line.split("//").next().unwrap_or(line)
|
||||
}
|
||||
Reference in New Issue
Block a user