some refactoring and comments
This commit is contained in:
parent
64121db9cb
commit
7024147cac
@ -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>`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user