From 71d9aaa039adbbdd6baa18dafde3bac53f106707 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 28 Mar 2023 10:46:29 -0700 Subject: [PATCH] Added square root, fixed many parser bugs --- src/evaluate.rs | 6 +- src/parser/find_subs.rs | 5 +- src/parser/groupify.rs | 86 +++++++++++++---- src/parser/mod.rs | 18 +++- src/parser/tokenize.rs | 82 ++++++++-------- src/parser/treeify.rs | 201 +++++++++++++++++++++------------------- src/tokens.rs | 118 +++++++++-------------- 7 files changed, 277 insertions(+), 239 deletions(-) diff --git a/src/evaluate.rs b/src/evaluate.rs index cd13682..06f3c16 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -43,14 +43,14 @@ pub fn evaluate( } match h { - Token::Operator(_,_,_) + Token::Operator(_,_) => { coords.push(0); continue 'outer; }, - Token::Constant(_,_,_) | - Token::Number(_,_) => { + Token::Constant(_,_) | + Token::Number(_) => { let l = coords.pop().unwrap(); coords.push(l + 1); continue 'outer; diff --git a/src/parser/find_subs.rs b/src/parser/find_subs.rs index 9c9546a..4ec62d9 100644 --- a/src/parser/find_subs.rs +++ b/src/parser/find_subs.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; use crate::parser::PreToken; -use crate::tokens::LineLocation; +use crate::parser::LineLocation; pub(in crate::parser) fn find_subs( @@ -64,7 +64,10 @@ pub(in crate::parser) fn find_subs( "chi" => {Some("χ")}, "psi" => {Some("ψ")}, "omega" => {Some("ω")}, + + // Operators "sqrt" => {Some("√")}, + "rt" => {Some("√")}, _ => {None} }; diff --git a/src/parser/groupify.rs b/src/parser/groupify.rs index dc1c9f1..ecd46c2 100644 --- a/src/parser/groupify.rs +++ b/src/parser/groupify.rs @@ -1,16 +1,28 @@ use std::collections::VecDeque; -use crate::tokens::LineLocation; -use crate::tokens::Operator; use crate::parser::PreToken; - +use crate::parser::LineLocation; use crate::parser::ParserError; +use crate::tokens::Operator; + // Inserts implicit operators fn lookback( g: &mut VecDeque ) -> Result<(), (LineLocation, ParserError)> { - if g.len() >= 2 { + if g.len() == 1 { + let a: PreToken = g.pop_back().unwrap(); + match &a { + PreToken::PreOperator(l,o) + => { + if o == "-" { + g.push_back(PreToken::PreOperator(*l, String::from("neg"))); + } else { g.push_back(a); } + }, + _ => { g.push_back(a); } + }; + + } else { let b: PreToken = g.pop_back().unwrap(); let a: PreToken = g.pop_back().unwrap(); @@ -42,10 +54,58 @@ fn lookback( )); } - // The following are fine - (PreToken::PreOperator(_,_), _) | - (_, PreToken::PreOperator(_,_)) - => { g.push_back(a); g.push_back(b); }, + (PreToken::PreOperator(_, sa), PreToken::PreOperator(l,sb)) + => { + if sb == "-" && { + let o = Operator::from_string(sa); + + o.is_some() && + ( + o.unwrap().is_binary() || + !o.unwrap().is_left_associative() + ) + } { + g.push_back(a); + g.push_back(PreToken::PreOperator(*l, String::from("neg"))); + } else { g.push_back(a); g.push_back(b); } + } + + // Insert implicit multiplications for unary operators + (PreToken::PreNumber(_,_), PreToken::PreOperator(l,s)) + | (PreToken::PreGroup(_,_), PreToken::PreOperator(l,s)) + | (PreToken::PreWord(_,_), PreToken::PreOperator(l,s)) + => { + let o = Operator::from_string(s); + g.push_back(a); + if o.is_some() { + let o = o.unwrap(); + if (!o.is_binary()) && (!o.is_left_associative()) { + g.push_back(PreToken::PreOperator( + LineLocation{pos: l.pos-1, len: 0}, + String::from("i*") + )); + } + } + g.push_back(b); + }, + + (PreToken::PreOperator(_,s), PreToken::PreNumber(l,_)) + | (PreToken::PreOperator(_,s), PreToken::PreGroup(l,_)) + | (PreToken::PreOperator(_,s), PreToken::PreWord(l,_)) + => { + let o = Operator::from_string(s); + g.push_back(a); + if o.is_some() { + let o = o.unwrap(); + if (!o.is_binary()) && o.is_left_associative() { + g.push_back(PreToken::PreOperator( + LineLocation{pos: l.pos-1, len: 0}, + String::from("i*") + )); + } + } + g.push_back(b); + }, // This shouldn't ever happen. (PreToken::PreGroupStart(_), _) @@ -102,16 +162,6 @@ pub(in crate::parser) fn groupify( lookback(v_now)?; }, - PreToken::PreWord(ref l, ref s) => { - let o = Operator::from_string(&s[..]); - if o.is_some() { - v_now.push_back(PreToken::PreOperator(*l, s.clone())); - } else { - v_now.push_back(t); - } - lookback(v_now)?; - } - _ => { v_now.push_back(t); lookback(v_now)?; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 7892077..9c0ad4d 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -12,9 +12,17 @@ use crate::parser::groupify::groupify; use crate::parser::treeify::treeify; use crate::parser::find_subs::find_subs; -use crate::tokens::LineLocation; use crate::tokens::Token; +/// Specifies the location of a token in an input string. +/// Used to locate ParserErrors. +#[derive(Debug)] +#[derive(Copy, Clone)] +pub struct LineLocation { + pub pos: usize, + pub len: usize +} + #[derive(Debug)] enum PreToken { PreNumber(LineLocation, String), @@ -67,14 +75,14 @@ impl PreToken { Ok(n) => n, Err(_) => return Err((l, ParserError::BadNumber)) }; - return Ok(Token::Number(l, n)); + return Ok(Token::Number(n)); }, PreToken::PreWord(l, s) => { return Ok(match &s[..] { // Mathematical constants - "π"|"pi" => { Token::Constant(l, 3.141592653, String::from("pi")) }, - "e" => { Token::Constant(l, 2.71828, String::from("e")) }, - "phi"|"φ" => { Token::Constant(l, 1.61803, String::from("phi")) }, + "π"|"pi" => { Token::Constant(3.141592653, String::from("pi")) }, + "e" => { Token::Constant(2.71828, String::from("e")) }, + "phi"|"φ" => { Token::Constant(1.61803, String::from("phi")) }, _ => { return Err((l, ParserError::Undefined(s))); } }); } diff --git a/src/parser/tokenize.rs b/src/parser/tokenize.rs index 0d8bac2..71ba6e9 100644 --- a/src/parser/tokenize.rs +++ b/src/parser/tokenize.rs @@ -1,28 +1,44 @@ use std::collections::VecDeque; use crate::parser::PreToken; -use crate::tokens::LineLocation; +use crate::parser::LineLocation; -/// Updates the length of a Token's LineLocation. -/// Run whenever a token is finished. +use crate::tokens::Operator; + +// Called whenever a token is finished. #[inline(always)] -fn update_line_location(mut t: PreToken, stop_i: usize) -> PreToken { +fn push_token(g: &mut VecDeque, t: Option, stop_i: usize) { + + if t.is_none() { return } + let mut t = t.unwrap(); + match t { - PreToken::PreGroupStart(ref mut l) | - PreToken::PreGroupEnd(ref mut l) | - PreToken::PreOperator(ref mut l, _) | - PreToken::PreNumber(ref mut l, _) | - PreToken::PreWord(ref mut l, _) + PreToken::PreGroupStart(ref mut l) + | PreToken::PreGroupEnd(ref mut l) + | PreToken::PreOperator(ref mut l, _) + | PreToken::PreNumber(ref mut l, _) + | PreToken::PreWord(ref mut l, _) => { *l = LineLocation{ pos: l.pos, len: stop_i - l.pos, }; }, - _ => panic!() + + PreToken::PreGroup(_,_) + | PreToken::Container(_) + => panic!() }; - return t; + + if let PreToken::PreWord(l, s) = &t { + let o = Operator::from_string(s); + if o.is_some() { + t = PreToken::PreOperator(*l, s.clone()); + } + } + + g.push_back(t); } /// Turns a string into Tokens. First stage of parsing. @@ -36,27 +52,11 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque { // The minus sign can be both a Negative and an Operator. // Needs special treatment. '-' => { - if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } - match g.back().as_ref() { - // If previous token was any of the following, - // this is the "minus" operator - Some(PreToken::PreNumber(_, _)) | - Some(PreToken::PreGroupEnd(_)) | - Some(PreToken::PreWord(_, _)) => { - t = Some(PreToken::PreOperator( - LineLocation{pos: i, len: 1}, - String::from("-") - )); - }, - - // Otherwise, this is a negative sign. - _ => { - t = Some(PreToken::PreOperator( - LineLocation{pos: i, len: 1}, - String::from("neg") - )); - } - }; + push_token(&mut g, t, i); + t = Some(PreToken::PreOperator( + LineLocation{pos: i, len: 1}, + String::from("-") + )); }, // Number @@ -72,7 +72,7 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque { // If we're not building a number, finalize // previous token and start one. _ => { - if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } + push_token(&mut g, t, i); t = Some(PreToken::PreNumber(LineLocation{pos: i, len: 0}, String::from(c))); } }; @@ -85,7 +85,7 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque { match &mut t { Some(PreToken::PreOperator(_, val)) => { val.push(c); }, _ => { - if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } + push_token(&mut g, t, i); t = Some(PreToken::PreOperator(LineLocation{pos: i, len: 0}, String::from(c))); } }; @@ -93,20 +93,18 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque { // Group '(' => { - if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } + push_token(&mut g, t, i); t = Some(PreToken::PreGroupStart(LineLocation{pos: i, len: 0})); }, ')' => { - if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } + push_token(&mut g, t, i); t = Some(PreToken::PreGroupEnd(LineLocation{pos: i, len: 0})); }, // Space. Basic seperator. ' ' => { - if t.is_some() { - g.push_back(update_line_location(t.unwrap(), i)); - t = None; - } + push_token(&mut g, t, i); + t = None; } // Word @@ -115,7 +113,7 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque { Some(PreToken::PreWord(_, val)) => { val.push(c); }, _ => { - if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } + push_token(&mut g, t, i); t = Some(PreToken::PreWord(LineLocation{pos: i, len: 0}, String::from(c))); } }; @@ -123,7 +121,7 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque { }; } - if t.is_some() { g.push_back(update_line_location(t.unwrap(), input.chars().count())); } + push_token(&mut g, t, input.chars().count()); return g; } \ No newline at end of file diff --git a/src/parser/treeify.rs b/src/parser/treeify.rs index 9ba138a..dd5dbcf 100644 --- a/src/parser/treeify.rs +++ b/src/parser/treeify.rs @@ -3,17 +3,14 @@ use std::collections::VecDeque; use crate::parser::PreToken; use crate::parser::ParserError; +use crate::parser::LineLocation; use crate::tokens::Token; use crate::tokens::Operator; -use crate::tokens::LineLocation; - - fn treeify_binary( i: usize, - g_inner: &mut VecDeque, - left_associative: bool + g_inner: &mut VecDeque ) -> Result<(), (LineLocation, ParserError)> { let this: &PreToken = &g_inner[i]; @@ -27,45 +24,44 @@ fn treeify_binary( return Err((*l, ParserError::Syntax)); } - let next: &PreToken; - if left_associative { - next = { - if i < g_inner.len()-1 { - &g_inner[i+1] - } else { - let l = match this { - PreToken::PreOperator(l, _) => l, - _ => panic!() - }; - return Err((*l, ParserError::Syntax)); - } - }; - } else { - next = { - if i > 0 { - &g_inner[i-1] - } else { - let l = match this { - PreToken::PreOperator(l, _) => l, - _ => panic!() - }; - return Err((*l, ParserError::Syntax)); - } - }; - } + + let left = { + if i > 0 { + &g_inner[i-1] + } else { + let l = match this { + PreToken::PreOperator(l, _) => l, + _ => panic!() + }; + return Err((*l, ParserError::Syntax)); + } + }; + + let right = { + if i < g_inner.len()-1 { + &g_inner[i+1] + } else { + let l = match this { + PreToken::PreOperator(l, _) => l, + _ => panic!() + }; + return Err((*l, ParserError::Syntax)); + } + }; - if let PreToken::PreOperator(l, s) = next { + + + if let PreToken::PreOperator(l, s) = left { let o = Operator::from_string(s); if o.is_none() { return Err((*l, ParserError::Syntax)); } let o = o.unwrap(); if { (!o.is_binary()) && - !(o.is_left_associative() && left_associative) + o.is_left_associative() } { - // Only right-associative unary operators can follow a binary operator return Ok(()); } else { let tl = *this.get_line_location(); @@ -74,59 +70,79 @@ fn treeify_binary( ParserError::Syntax )); } - } else { - // Precedence of this operator - let this_val = { - let PreToken::PreOperator(l, s) = this else {panic!()}; - let o = Operator::from_string(s); - if o.is_none() { return Err((*l, ParserError::Syntax)); } - o.unwrap() as isize - }; + } - // Precedence of the operators contesting our arguments - let left_val = if i > 1 { - let PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; - let o = Operator::from_string(s); - if o.is_none() { return Err((*l, ParserError::Syntax)); } - Some(o.unwrap() as isize) - } else { None }; - - let right_val = if i < g_inner.len()-2 { - let PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; - let o = Operator::from_string(s); - if o.is_none() { return Err((*l, ParserError::Syntax)); } - Some(o.unwrap() as isize) - } else { None }; + if let PreToken::PreOperator(l, s) = right { + let o = Operator::from_string(s); + if o.is_none() { return Err((*l, ParserError::Syntax)); } + let o = o.unwrap(); if { - (left_val.is_none() || this_val >= left_val.unwrap()) && - (right_val.is_none() || this_val >= right_val.unwrap()) + (!o.is_binary()) && + !o.is_left_associative() } { - // This operator has higher precedence, it takes both arguments - let left_pre = g_inner.remove(i-1).unwrap(); - let this_pre = g_inner.remove(i-1).unwrap(); - let right_pre = g_inner.remove(i-1).unwrap(); - let left: Token; let right: Token; - if let PreToken::PreGroup(_, _) = right_pre { right = treeify(right_pre)?; } else {right = right_pre.to_token()?;} - if let PreToken::PreGroup(_, _) = left_pre { left = treeify(left_pre)?; } else {left = left_pre.to_token()?;} - - let (l, o) = { - let PreToken::PreOperator(l, s) = this_pre else {panic!()}; - let o = Operator::from_string(&s); - if o.is_none() { panic!() } - (l, o.unwrap()) - }; - - let mut new_token_args: VecDeque = VecDeque::with_capacity(2); - new_token_args.push_back(left); - new_token_args.push_back(right); - - g_inner.insert(i-1, PreToken::Container(o.into_token(l, new_token_args))); - return Ok(()); } else { - return Ok(()); + let tl = *this.get_line_location(); + return Err(( + LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len}, + ParserError::Syntax + )); + } + } + + + // Precedence of this operator + let this_val = { + let PreToken::PreOperator(l, s) = this else {panic!()}; + let o = Operator::from_string(s); + if o.is_none() { return Err((*l, ParserError::Syntax)); } + o.unwrap() as isize + }; + + // Precedence of the operators contesting our arguments + let left_val = if i > 1 { + let PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; + let o = Operator::from_string(s); + if o.is_none() { return Err((*l, ParserError::Syntax)); } + Some(o.unwrap() as isize) + } else { None }; + + let right_val = if i < g_inner.len()-2 { + let PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; + let o = Operator::from_string(s); + if o.is_none() { return Err((*l, ParserError::Syntax)); } + Some(o.unwrap() as isize) + } else { None }; + + if { + (left_val.is_none() || this_val >= left_val.unwrap()) && + (right_val.is_none() || this_val >= right_val.unwrap()) + } { + // This operator has higher precedence, it takes both arguments + let left_pre = g_inner.remove(i-1).unwrap(); + let this_pre = g_inner.remove(i-1).unwrap(); + let right_pre = g_inner.remove(i-1).unwrap(); + let left: Token; let right: Token; + if let PreToken::PreGroup(_, _) = right_pre { right = treeify(right_pre)?; } else {right = right_pre.to_token()?;} + if let PreToken::PreGroup(_, _) = left_pre { left = treeify(left_pre)?; } else {left = left_pre.to_token()?;} + + let o = { + let PreToken::PreOperator(_, s) = this_pre else {panic!()}; + let o = Operator::from_string(&s); + if o.is_none() { panic!() } + o.unwrap() }; + + let mut new_token_args: VecDeque = VecDeque::with_capacity(2); + new_token_args.push_back(left); + new_token_args.push_back(right); + + g_inner.insert(i-1, PreToken::Container(o.into_token(new_token_args))); + + return Ok(()); + } else { + return Ok(()); }; } @@ -174,14 +190,7 @@ fn treeify_unary( } if prev.is_some() { - if let PreToken::PreOperator(l, s) = prev.unwrap() { - let o = Operator::from_string(s); - if o.is_none() { return Err((*l, ParserError::Syntax)); } - let o = o.unwrap(); - - if o.is_left_associative() && left_associative { - return Err((*l, ParserError::Syntax)); - } + if let PreToken::PreOperator(_,_) = prev.unwrap() { } else { return Err(( *this.get_line_location(), @@ -190,8 +199,6 @@ fn treeify_unary( } } - - if let PreToken::PreOperator(l, _) = next { let tl = *this.get_line_location(); return Err(( @@ -236,20 +243,20 @@ fn treeify_unary( } if let PreToken::PreGroup(_, _) = next_pre { next = treeify(next_pre)?; } else { next = next_pre.to_token()? } - let (l, o) = { - let PreToken::PreOperator(l, s) = this_pre else {panic!()}; + let o = { + let PreToken::PreOperator(_, s) = this_pre else {panic!()}; let o = Operator::from_string(&s); if o.is_none() { panic!() } - (l, o.unwrap()) + o.unwrap() }; let mut new_token_args: VecDeque = VecDeque::with_capacity(3); new_token_args.push_back(next); if left_associative { - g_inner.insert(i-1, PreToken::Container(o.into_token(l, new_token_args))); + g_inner.insert(i-1, PreToken::Container(o.into_token(new_token_args))); } else { - g_inner.insert(i, PreToken::Container(o.into_token(l, new_token_args))); + g_inner.insert(i, PreToken::Container(o.into_token(new_token_args))); } return Ok(()); @@ -300,7 +307,7 @@ pub(in crate::parser) fn treeify( if left_associative { if this_op.is_left_associative() { if this_op.is_binary() { - treeify_binary(i, g_inner, left_associative)?; + treeify_binary(i, g_inner)?; } else { treeify_unary(i, g_inner, left_associative)?; } @@ -309,7 +316,7 @@ pub(in crate::parser) fn treeify( } else { if !this_op.is_left_associative() { if this_op.is_binary() { - treeify_binary(i, g_inner, left_associative)?; + treeify_binary(i, g_inner)?; } else { treeify_unary(i, g_inner, left_associative)?; } diff --git a/src/tokens.rs b/src/tokens.rs index ea515cf..271b999 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,26 +1,15 @@ use std::collections::VecDeque; - -/// Specifies the location of a token in an input string. -/// Used to locate ParserErrors. -#[derive(Debug)] -#[derive(Copy, Clone)] -pub struct LineLocation { - pub pos: usize, - pub len: usize -} - /// Tokens represent logical objects in an expession. /// /// Tokens starting with `Pre*` are intermediate tokens, and /// will never show up in a fully-parsed expression tree. #[derive(Debug)] pub enum Token { - Number(LineLocation, f64), - Constant(LineLocation, f64, String), + Number(f64), + Constant(f64, String), Operator( - LineLocation, Operator, VecDeque ), @@ -30,27 +19,17 @@ impl Token { #[inline(always)] pub fn get_args(&mut self) -> Option<&mut VecDeque> { match self { - Token::Operator(_, _, ref mut a) => Some(a), + Token::Operator(_, ref mut a) => Some(a), _ => None } } - #[inline(always)] - pub fn get_line_location(&self) -> &LineLocation { - match self { - Token::Number(l, _) - | Token::Operator(l, _, _) - | Token::Constant(l, _, _) - => l, - } - } - #[inline(always)] pub fn eval(&self) -> Token { match self { - Token::Number(l,v) => { Token::Number(*l, *v) }, - Token::Constant(l,v,_) => { Token::Number(*l, *v) }, - Token::Operator(_,o,v) => { o.apply(v) } + Token::Number(v) => { Token::Number(*v) }, + Token::Constant(v,_) => { Token::Number(*v) }, + Token::Operator(o,v) => { o.apply(v) } } } @@ -58,8 +37,8 @@ impl Token { #[inline(always)] pub fn as_number(&self) -> Token { match self { - Token::Number(l,v) => { Token::Number(*l, *v) }, - Token::Constant(l,v,_) => { Token::Number(*l, *v) }, + Token::Number(v) => { Token::Number(*v) }, + Token::Constant(v,_) => { Token::Number(*v) }, _ => panic!() } } @@ -79,6 +58,7 @@ pub enum Operator { Modulo, // Mod invoked with % Negative, Power, + Sqrt, Factorial, // Not accessible from prompt @@ -99,6 +79,7 @@ impl Operator { "mod" => {Some( Operator::ModuloLong )}, "^"|"**" => {Some( Operator::Power )}, "!" => {Some( Operator::Factorial )}, + "sqrt"|"rt"|"√" => {Some( Operator::Sqrt )}, _ => None } } @@ -108,6 +89,7 @@ impl Operator { match self { Operator::Negative | Operator::Factorial + | Operator::Sqrt => false, _ => true } @@ -117,6 +99,7 @@ impl Operator { pub fn is_left_associative(&self) -> bool { match self { Operator::Negative + | Operator::Sqrt => false, _ => true } @@ -124,16 +107,16 @@ impl Operator { #[inline(always)] - pub fn into_token(self, l: LineLocation, mut args: VecDeque) -> Token { + pub fn into_token(self, mut args: VecDeque) -> Token { match self { Operator::Subtract => { if args.len() != 2 { panic!() } let a = args.pop_front().unwrap(); let b = args.pop_front().unwrap(); - let b = Token::Operator(l, Operator::Negative, VecDeque::from(vec!(b))); + let b = Token::Operator(Operator::Negative, VecDeque::from(vec!(b))); Token::Operator( - l, Operator::Add, + Operator::Add, VecDeque::from(vec!(a,b)) ) }, @@ -142,19 +125,29 @@ impl Operator { if args.len() != 2 { panic!() } let a = args.pop_front().unwrap(); let b = args.pop_front().unwrap(); - let b = Token::Operator(l, Operator::Flip, VecDeque::from(vec!(b))); + let b = Token::Operator(Operator::Flip, VecDeque::from(vec!(b))); Token::Operator( - l, Operator::Multiply, + Operator::Multiply, VecDeque::from(vec!(a,b)) ) }, + Operator::Sqrt => { + if args.len() != 1 { panic!() } + let a = args.pop_front().unwrap(); + + Token::Operator( + Operator::Power, + VecDeque::from(vec!(a, Token::Number(0.5))) + ) + }, + Operator::ImplicitMultiply - => { Token::Operator(l, Operator::Multiply, args) }, + => { Token::Operator(Operator::Multiply, args) }, Operator::ModuloLong - => { Token::Operator(l, Operator::Modulo, args) }, + => { Token::Operator(Operator::Modulo, args) }, Operator::Factorial | Operator::Negative @@ -163,7 +156,7 @@ impl Operator { | Operator::Multiply | Operator::Modulo | Operator::Power - => { Token::Operator(l, self, args) }, + => { Token::Operator(self, args) }, } } } @@ -172,6 +165,7 @@ impl Operator{ pub fn apply(&self, args: &VecDeque) -> Token { match self { Operator::ImplicitMultiply | + Operator::Sqrt | Operator::ModuloLong | Operator::Divide | Operator::Subtract => { panic!() } @@ -180,8 +174,8 @@ impl Operator{ if args.len() != 1 {panic!()}; let args = args[0].as_number(); - if let Token::Number(l, v) = args { - Token::Number(l, -v) + if let Token::Number(v) = args { + Token::Number(-v) } else { panic!(); } }, @@ -189,51 +183,35 @@ impl Operator{ if args.len() != 1 {panic!()}; let args = args[0].as_number(); - if let Token::Number(l, v) = args { - Token::Number(l, 1f64/v) + if let Token::Number(v) = args { + Token::Number(1f64/v) } else { panic!(); } }, Operator::Add => { let mut sum: f64 = 0f64; - let mut new_pos: usize = 0; - let mut new_len: usize = 0; for i in args.iter() { let j = i.as_number(); - if let Token::Number(l, v) = j { - if new_pos == 0 {new_pos = l.pos}; - new_len = new_len + l.len; + if let Token::Number(v) = j { sum += v; } else { panic!(); } } - - Token::Number( - LineLocation { pos: new_pos, len: new_len }, - sum - ) + Token::Number(sum) }, Operator::Multiply => { let mut prod: f64 = 1f64; - let mut new_pos: usize = 0; - let mut new_len: usize = 0; for i in args.iter() { let j = i.as_number(); - if let Token::Number(l, v) = j { - if new_pos == 0 {new_pos = l.pos}; - new_len = new_len + l.len; + if let Token::Number(v) = j { prod *= v; } else { panic!(); } } - - Token::Number( - LineLocation { pos: new_pos, len: new_len }, - prod - ) + Token::Number(prod) }, Operator::Modulo => { @@ -241,12 +219,9 @@ impl Operator{ let a = args[0].as_number(); let b = args[1].as_number(); - if let Token::Number(la, va) = a { - if let Token::Number(lb, vb) = b { - Token::Number( - LineLocation { pos: la.pos, len: lb.pos - la.pos + lb.len }, - va%vb - ) + if let Token::Number(va) = a { + if let Token::Number(vb) = b { + Token::Number(va%vb) } else { panic!(); } } else { panic!(); } }, @@ -256,12 +231,9 @@ impl Operator{ let a = args[0].as_number(); let b = args[1].as_number(); - if let Token::Number(la, va) = a { - if let Token::Number(lb, vb) = b { - Token::Number( - LineLocation { pos: la.pos, len: lb.pos - la.pos + lb.len }, - va.powf(vb) - ) + if let Token::Number(va) = a { + if let Token::Number(vb) = b { + Token::Number(va.powf(vb)) } else { panic!(); } } else { panic!(); } },