task param parsing implementation

This commit is contained in:
Christoph J. Scherr 2023-02-12 15:46:09 +01:00
parent f03541d056
commit d5ee7a420a
1 changed files with 69 additions and 14 deletions

View File

@ -1,17 +1,16 @@
use std::fmt; use std::fmt;
use std::collections::HashMap;
use std::hash::Hash;
use regex::Regex; use regex::Regex;
// In an expression like `sqrt(25)` the Task would correspond to `sqrt`. This is the enum to // In an expression like `sqrt(25)` the Task would correspond to `sqrt`. This is the enum to
// configure possible Tasks. // configure possible Tasks.
// None means, the Expression doesn't send it's Value to a Task Handler // None means, the Expression doesn't send it's Value to a Task Handler
#[derive(Debug)] // automatically generate Debug Formatter #[derive(Debug)] // automatically generate Debug Formatter
pub enum Task { pub enum Task {
None, None,
Sqrt, Root(u64),
Power, Power(f64),
Log(u64), Log(f64),
} }
// How to clone a Task, i was supprised I had to do it myself. // How to clone a Task, i was supprised I had to do it myself.
@ -20,8 +19,8 @@ impl Clone for Task {
// This can probably be done cleaner than with a verbose match. FIXME // This can probably be done cleaner than with a verbose match. FIXME
match self { match self {
Task::None => Task::None, Task::None => Task::None,
Task::Sqrt => Task::Sqrt, Task::Root(depth) => Task::Root(*depth),
Task::Power => Task::Power, Task::Power(exp) => Task::Power(*exp),
Task::Log(base) => Task::Log(*base), // TODO add base for log Task::Log(base) => Task::Log(*base), // TODO add base for log
} }
} }
@ -29,12 +28,51 @@ impl Clone for Task {
impl Task { impl Task {
pub fn new(task_text: &str, task_param: &str) -> Task { pub fn new(task_text: &str, task_param: &str) -> Task {
if task_text.is_empty() {
return Task::None;
}
let task_text = task_text.to_lowercase(); let task_text = task_text.to_lowercase();
match task_text.as_str() { match task_text.as_str() {
"none" => Task::None, "none" => Task::None,
"sqrt" => Task::Sqrt, "sqrt"|"root" => {
"power"|"pow" => Task::Power, if task_param.is_empty() {
"log"|"ln" => Task::Log(10), // TODO add base return Task::Root(2);
}
let pot_param = task_param.parse::<u64>();
match pot_param {
Ok(value) => {Task::Root(value)},
Err(error) => {
eprintln!("could not parse task parameter: {error}");
std::process::exit(1);
},
}
},
"power"|"pow"|"sq" => {
if task_param.is_empty() {
return Task::Power(2.0);
}
let pot_param = task_param.parse::<f64>();
match pot_param {
Ok(value) => {Task::Power(value)},
Err(error) => {
eprintln!("could not parse task parameter: {error}");
std::process::exit(1);
},
}
},
"log"|"ln" => {
if task_param.is_empty() {
return Task::Log(10.0);
}
let pot_param = task_param.parse::<f64>();
match pot_param {
Ok(value) => {Task::Log(value)},
Err(error) => {
eprintln!("could not parse task parameter: {error}");
std::process::exit(1);
},
}
},
// what to do if a bad task was given: // what to do if a bad task was given:
&_ => {eprintln!("Bad Task: {}", task_text); std::process::exit(1); }, &_ => {eprintln!("Bad Task: {}", task_text); std::process::exit(1); },
} }
@ -42,7 +80,8 @@ impl Task {
} }
// An Expression is something that can be calculated. 20+5 is an expression. Expressions can // An Expression is something that can be calculated. 20+5 is an expression. Expressions can
// contain other // contain other
// Expressions and have tasks: 20+sqrt(20+5) // Expressions and have tasks: 20+log_10(20+5)
// Tasks may have parameters, denoted using an underscore '_'
// Expressions are marked down with braces and a task before those braces: // Expressions are marked down with braces and a task before those braces:
// task(Expression) // task(Expression)
// once the Value of the Expression got calculated, the calculated value should be sent to the // once the Value of the Expression got calculated, the calculated value should be sent to the
@ -112,7 +151,6 @@ fn find_brace_groups(haystack: String) -> Vec<Vec<(usize, usize)>> {
parenthesis_open_processed = parenthesis_open_processed + 1; parenthesis_open_processed = parenthesis_open_processed + 1;
}, },
')' => { ')' => {
let len = parenthesis_group.len();
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
dbg!(char); dbg!(char);
@ -162,12 +200,29 @@ impl Expression {
let text = &expression_text[pair.0..pair.1 + 1]; let text = &expression_text[pair.0..pair.1 + 1];
let text = &text[1..text.len() - 1]; let text = &text[1..text.len() - 1];
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
dbg!(text);
brace_groups_texts.push(text.to_string()); brace_groups_texts.push(text.to_string());
// we have the expression_text, now we just need to get the task until we can // we have the expression_text, now we just need to get the task until we can
// pass these parameters into Expression::new(). This is the recursive part. // pass these parameters into Expression::new(). This is the recursive part.
let possible_task = &expression_text[..pair.0].chars().rev().collect::<String>(); let possible_task = &expression_text[..pair.0].chars().rev().collect::<String>();
dbg!(possible_task); let mut stop_at: usize = 0;
// TODO check for task parameters
for (index, char) in possible_task.chars().enumerate() {
stop_at = index;
if !(char.is_alphanumeric() | (char == '.') | (char == '_')) {
break;
}
}
let task_text_full = possible_task.clone()[..stop_at + 1].chars().rev().collect::<String>();
let task: Task;
if task_text_full.contains('_') {
let split: Vec<&str> = task_text_full.split('_').collect();
task = Task::new(split[0], split[1]);
}
else {
task = Task::new(task_text_full.as_str(), "");
}
let child = Expression::new(text.to_string(), task);
children.push(child);
} }
} }
} }