some refactoring and comments

This commit is contained in:
Simon Gardling 2022-05-03 13:43:16 -04:00
parent 64121db9cb
commit 7024147cac

View File

@ -15,23 +15,28 @@ macro_rules! test_print {
pub fn split_function(input: &str) -> Vec<String> { pub fn split_function(input: &str) -> Vec<String> {
split_function_chars( split_function_chars(
&input &input
.replace("pi", "π") .replace("pi", "π") // replace "pi" text with pi symbol
.replace("**", "^") .replace("**", "^") // support alternate manner of expressing exponents
.replace("exp", "\u{1fc93}") .replace("exp", "\u{1fc93}") //stop-gap solution to fix the `exp` function
.chars() .chars()
.collect::<Vec<char>>(), .collect::<Vec<char>>(),
) )
.iter() .iter()
.map(|x| x.replace("\u{1fc93}", "exp")) .map(|x| x.replace("\u{1fc93}", "exp")) // Convert back to `exp` text
.collect::<Vec<String>>() .collect::<Vec<String>>()
} }
// __REVIEW__
fn split_function_chars(chars: &[char]) -> Vec<String> { fn split_function_chars(chars: &[char]) -> Vec<String> {
assert!(!chars.is_empty()); if chars.is_empty() {
return Vec::new();
}
let mut split: Vec<String> = Vec::new(); // Resulting split-up data
let mut data: Vec<String> = Vec::new();
let mut buffer: Vec<char> = Vec::new(); // Buffer used to store data ready to be appended
let mut buffer: Vec<&char> = Vec::new();
#[derive(Default)] #[derive(Default)]
struct BoolSlice { struct BoolSlice {
@ -45,15 +50,17 @@ fn split_function_chars(chars: &[char]) -> Vec<String> {
} }
impl BoolSlice { impl BoolSlice {
#[inline] #[inline(always)]
fn is_variable(&self) -> bool { self.variable && !self.masked_var } fn is_variable(&self) -> bool { self.variable && !self.masked_var }
#[inline] #[inline(always)]
fn is_number(&self) -> bool { self.number && !self.masked_num } fn is_number(&self) -> bool { self.number && !self.masked_num }
} }
let mut prev_char: BoolSlice = BoolSlice::default(); let mut prev_char: BoolSlice = BoolSlice::default();
for c in chars { for c in chars {
// Set data about current character
let mut curr_c = { let mut curr_c = {
let isnumber = is_number(c); let isnumber = is_number(c);
let isvariable = is_variable(c); let isvariable = is_variable(c);
@ -74,28 +81,26 @@ fn split_function_chars(chars: &[char]) -> Vec<String> {
} }
}; };
let buffer_string = buffer.iter().collect::<String>();
// Check if prev_char is valid // Check if prev_char is valid
if prev_char.exists { if prev_char.exists {
// if previous char was a masked number, and current char is a number, mask current char's variable status // If previous char was a masked number, and current char is a number, mask current char's variable status
if prev_char.masked_num && curr_c.number { if prev_char.masked_num && curr_c.number {
curr_c.masked_num = true; curr_c.masked_num = true;
} }
// if previous char was a masked variable, and current char is a variable, mask current char's variable status // If previous char was a masked variable, and current char is a variable, mask current char's variable status
if prev_char.masked_var && curr_c.variable { if prev_char.masked_var && curr_c.variable {
curr_c.masked_var = true; curr_c.masked_var = true;
} }
// if letter and not a variable (or a masked variable) // If letter and not a variable (or a masked variable)
if prev_char.letter && !(prev_char.variable && !prev_char.masked_var) { if prev_char.letter && !(prev_char.variable && !prev_char.masked_var) {
// mask number status if current char is number // Mask number status if current char is number
if curr_c.number { if curr_c.number {
curr_c.masked_num = true; curr_c.masked_num = true;
} }
// mask variable status if current char is a variable // Mask variable status if current char is a variable
if curr_c.variable { if curr_c.variable {
curr_c.masked_var = true; curr_c.masked_var = true;
} }
@ -105,7 +110,7 @@ fn split_function_chars(chars: &[char]) -> Vec<String> {
let mut do_split = false; let mut do_split = false;
if prev_char.closing_parens { if prev_char.closing_parens {
// cases like `)x`, `)2`, and `)(` // Cases like `)x`, `)2`, and `)(`
if (c == &'(') if (c == &'(')
| (curr_c.letter && !curr_c.is_variable()) | (curr_c.letter && !curr_c.is_variable())
| curr_c.is_variable() | curr_c.is_variable()
@ -114,17 +119,17 @@ fn split_function_chars(chars: &[char]) -> Vec<String> {
do_split = true; do_split = true;
} }
} else if c == &'(' { } else if c == &'(' {
// cases like `x(` and `2(` // Cases like `x(` and `2(`
if (prev_char.is_variable() | prev_char.is_number()) && !prev_char.letter { if (prev_char.is_variable() | prev_char.is_number()) && !prev_char.letter {
do_split = true; do_split = true;
} }
} else if prev_char.is_number() { } else if prev_char.is_number() {
// cases like `2x` and `2sin(x)` // Cases like `2x` and `2sin(x)`
if curr_c.is_variable() | curr_c.letter { if curr_c.is_variable() | curr_c.letter {
do_split = true; do_split = true;
} }
} else if curr_c.is_variable() | curr_c.letter { } else if curr_c.is_variable() | curr_c.letter {
// cases like `e2` and `xx` // Cases like `e2` and `xx`
if prev_char.is_number() if prev_char.is_number()
| (prev_char.is_variable() && curr_c.is_variable()) | (prev_char.is_variable() && curr_c.is_variable())
| prev_char.is_variable() | prev_char.is_variable()
@ -134,26 +139,31 @@ fn split_function_chars(chars: &[char]) -> Vec<String> {
} else if (curr_c.is_number() | curr_c.letter | curr_c.is_variable()) } else if (curr_c.is_number() | curr_c.letter | curr_c.is_variable())
&& (prev_char.is_number() | prev_char.letter) && (prev_char.is_number() | prev_char.letter)
{ {
// cases like `x2` and `xx`
do_split = true; do_split = true;
} else if curr_c.is_number() && prev_char.is_variable() { } else if curr_c.is_number() && prev_char.is_variable() {
// Cases like `x2`
do_split = true; do_split = true;
} }
// split and append buffer // Append split
if do_split { if do_split {
split.push(buffer_string); data.push(buffer.iter().cloned().collect::<String>());
buffer.clear(); buffer.clear();
} }
buffer.push(*c); // Add character to buffer
buffer.push(c);
// Move current character data to `prev_char`
prev_char = curr_c; prev_char = curr_c;
} }
// If there is still data in the buffer, append it
if !buffer.is_empty() { if !buffer.is_empty() {
split.push(buffer.iter().collect::<String>()); data.push(buffer.iter().cloned().collect::<String>());
} }
split
data
} }
/// Generate a hint based on the input `input`, returns an `Option<String>` /// Generate a hint based on the input `input`, returns an `Option<String>`