use super::types::OpType;
use crate::error::MatrixError;
pub fn parse_operation(op_str: &str, target_row: usize) -> Result<OpType, MatrixError> {
let op_str = op_str.trim();
if let Some(pos) = op_str.find('+') {
let rest = &op_str[pos + 1..].trim();
let parts: Vec<&str> = rest.split_whitespace().collect();
if parts.len() >= 2 {
let multiplier = parts[0]
.parse::<f64>()
.map_err(|_| MatrixError::ParseError {
line: 0,
message: format!("Invalid multiplier: {}", parts[0]),
})?;
let source = parse_row_index(parts[1])?;
return Ok(OpType::AddMultiple {
target: target_row,
source,
multiplier,
});
}
}
if let Some(pos) = op_str.find('-') {
if pos == 0 || !op_str.chars().nth(pos - 1).unwrap().is_ascii_digit() {
let rest = &op_str[pos + 1..].trim();
let parts: Vec<&str> = rest.split_whitespace().collect();
if parts.len() >= 2 {
let multiplier = parts[0]
.parse::<f64>()
.map_err(|_| MatrixError::ParseError {
line: 0,
message: format!("Invalid multiplier: {}", parts[0]),
})?;
let source = parse_row_index(parts[1])?;
return Ok(OpType::AddMultiple {
target: target_row,
source,
multiplier: -multiplier,
});
}
}
}
if let Some(pos) = op_str.find('x') {
let rest = &op_str[pos + 1..].trim();
let multiplier = rest.parse::<f64>().map_err(|_| MatrixError::ParseError {
line: 0,
message: format!("Invalid multiplier: {}", rest),
})?;
return Ok(OpType::Multiply {
target: target_row,
multiplier,
});
}
if let Some(pos) = op_str.find('<') {
let rest = &op_str[pos + 1..].trim();
let source = parse_row_index(rest)?;
return Ok(OpType::Replace {
target: target_row,
source,
});
}
Err(MatrixError::ParseError {
line: 0,
message: format!("No valid operation found: {}", op_str),
})
}
fn parse_row_index(s: &str) -> Result<usize, MatrixError> {
let cleaned = s
.trim()
.trim_start_matches('r')
.trim_start_matches('R')
.trim_start_matches('[')
.trim_end_matches(']');
cleaned.parse().map_err(|_| MatrixError::ParseError {
line: 0,
message: format!("Invalid row index: {}", s),
})
}