From 3279a7035f2985aa105c56b23ad9383c40f61f7f Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Wed, 16 Feb 2022 15:50:09 -0500 Subject: [PATCH] improve parsing (very janky) --- src/lib.rs | 56 +++++++++++++++++++++++++------------------------- src/misc.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ www/index.html | 2 +- 3 files changed, 84 insertions(+), 29 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2fb37aa..efeeacc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ use std::panic; use wasm_bindgen::prelude::*; use web_sys::HtmlCanvasElement; mod misc; -use crate::misc::{Cache, ChartOutput, DrawResult}; +use crate::misc::{Cache, ChartOutput, DrawResult, add_asterisks, test_func_basic}; #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; @@ -57,27 +57,21 @@ impl ChartManager { // Used in order to hook into `panic!()` to log in the browser's console pub fn init_panic_hook() { panic::set_hook(Box::new(console_error_panic_hook::hook)); } + fn get_func(&self) -> impl Fn(f64) -> f64 { + + let expr: Expr = self.func_str.parse().unwrap(); + let func = expr.bind("x").unwrap(); + func + } + pub fn test_func(function_string: String) -> String { - let expr_result = function_string.parse(); - let expr_error = match &expr_result { - Ok(_) => "".to_string(), - Err(error) => format!("{}", error), - }; - if !expr_error.is_empty() { - return expr_error; + let new_func_str: String = add_asterisks(function_string.clone()); + let run1_result = test_func_basic(new_func_str); + if run1_result == "" { + return run1_result; } - let expr: Expr = expr_result.unwrap(); - let func_result = expr.bind("x"); - let func_error = match &func_result { - Ok(_) => "".to_string(), - Err(error) => format!("{}", error), - }; - if !func_error.is_empty() { - return func_error; - } - - "".to_string() + return test_func_basic(function_string); } // Recommends a possible solution to an error from method `test_func` @@ -87,12 +81,6 @@ impl ChartManager { }.to_string() } - fn get_func(&self) -> impl Fn(f64) -> f64 { - let expr: Expr = self.func_str.parse().unwrap(); - let func = expr.bind("x").unwrap(); - func - } - #[inline] fn draw( &mut self, element: HtmlCanvasElement, dark_mode: bool @@ -190,15 +178,27 @@ impl ChartManager { #[allow(clippy::too_many_arguments)] pub fn update( - &mut self, canvas: HtmlCanvasElement, func_str: &str, min_x: f32, max_x: f32, min_y: f32, + &mut self, canvas: HtmlCanvasElement, func_str_new: String, min_x: f32, max_x: f32, min_y: f32, max_y: f32, num_interval: usize, resolution: i32, dark_mode: bool ) -> Result { - let underlying_update = (*func_str != self.func_str) + let func_str: String; + let new_func_str: String = add_asterisks(func_str_new.clone()); + if test_func_basic(add_asterisks(func_str_new.clone())) == "" { + func_str = new_func_str; + } else if test_func_basic(func_str_new.clone()) == "" { + func_str = func_str_new; + } else { + panic!("function is invalid"); + } + + + let underlying_update = (func_str != self.func_str) | (min_x != self.min_x) | (max_x != self.max_x) | (min_y != self.min_y) | (max_y != self.max_y); + if 0 > resolution { panic!("resolution cannot be less than 0"); } @@ -221,7 +221,7 @@ impl ChartManager { self.front_cache.invalidate(); } - self.func_str = func_str.to_string(); + self.func_str = func_str; self.min_x = min_x; self.max_x = max_x; self.min_y = min_y; diff --git a/src/misc.rs b/src/misc.rs index 1bc2cbb..ae0a0a5 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,7 +1,62 @@ use wasm_bindgen::prelude::*; +use meval::Expr; pub type DrawResult = Result>; +pub fn test_func_basic(function_string: String) -> String { + let expr_result = function_string.parse(); + let expr_error = match &expr_result { + Ok(_) => "".to_string(), + Err(error) => format!("{}", error), + }; + if !expr_error.is_empty() { + return expr_error; + } + + let expr: Expr = expr_result.unwrap(); + let func_result = expr.bind("x"); + let func_error = match &func_result { + Ok(_) => "".to_string(), + Err(error) => format!("{}", error), + }; + if !func_error.is_empty() { + return func_error; + } + + "".to_string() +} + + +// EXTREMELY Janky function that tries to put asterisks in the proper places to be parsed +pub fn add_asterisks(function: String) -> String { + let letters: Vec= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".chars().collect(); + let numbers: Vec = "0123456789".chars().collect(); + let function_chars = function.chars(); + let mut output_string: String = String::new(); + let mut prev_char: char = ' '; + for c in function_chars { + if prev_char == ')' { + if c == '(' { + output_string += "*"; + } else if (c == 'x') | numbers.contains(&c) { + output_string += "*" + } + } else if letters.contains(&c) { + if numbers.contains(&prev_char) { + output_string += "*"; + } + } else if numbers.contains(&c) { + if letters.contains(&prev_char) { + output_string += "*"; + } + } + prev_char = c; + output_string += &c.to_string(); + } + + return output_string; +} + /// Result of screen to chart coordinates conversion. #[wasm_bindgen] pub struct Point { diff --git a/www/index.html b/www/index.html index 3a03664..92b8343 100644 --- a/www/index.html +++ b/www/index.html @@ -42,7 +42,7 @@

Not Using Explicit Multiplication

    -
  • Equations such as y=-2x that doesn’t explicitly request multiplication through the use of an asterisk will fail. Also chaining variables such as y=xxxx will fail, whereas y=x*x*x*x (or y=x^4) will not fail, this also applies for static variables such as e.
  • +
  • Equations such as chaining variables such as y=xxxx will fail, whereas y=x*x*x*x (or y=x^4) will not fail, this also applies for static variables such as e in situations like eeee, will fail.

What Expressions Can I Use?