From cafe1c9c64b4c6c60c1029dffffb07499661b4f0 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 24 Mar 2023 20:21:48 -0700 Subject: [PATCH] Added Constants Fixed treeify bug --- src/main.rs | 3 +- src/parser.rs | 64 ++++++++++++++++++------------ src/parser/evaluate.rs | 11 ++++-- src/parser/tokenize.rs | 38 ++++++++++-------- src/parser/treeify.rs | 88 +++++++++++++++++++++--------------------- 5 files changed, 113 insertions(+), 91 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4f009f8..2578b87 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,6 @@ use crate::promptbuffer::PromptBuffer; use crate::parser::Token; //use crate::parser::ParserError; use crate::parser::LineLocation; -use crate::parser::Eval; fn draw_line( @@ -122,7 +121,7 @@ fn main() -> Result<(), std::io::Error> { _ => {} }; }; - + draw_line( &mut stdout, pb.get_contents(), diff --git a/src/parser.rs b/src/parser.rs index d66470f..1d820f3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -14,10 +14,6 @@ use std::collections::VecDeque; /// Tokens starting with `Pre*` are intermediate tokens, and /// will never show up in a fully-parsed expression tree. -pub trait Eval { - fn eval(&self) -> Token; -} - #[derive(Debug)] pub enum Token { @@ -31,14 +27,16 @@ pub enum Token { /// Used only until operators are parsed. /// Each of these will become one of the operators below. - PreOperator(LineLocation, Operators), + PreOperator(LineLocation, Operator), /// Used only until operators are parsed. /// PreGroups aren't needed once we have a tree. PreGroup(LineLocation, VecDeque), - Root(VecDeque), Number(LineLocation, f64), + Constant(LineLocation, f64, String), + + Root(VecDeque), Multiply(VecDeque), Divide(VecDeque), Add(VecDeque), @@ -48,21 +46,35 @@ pub enum Token { Modulo(VecDeque), } -impl Eval for Token { - fn eval(&self) -> Token { +impl Token { + fn as_number(&self) -> Token { + match self { + Token::Number(l,v) => { + Token::Number(*l, *v) + }, + Token::Constant(l,v,_) => { + Token::Number(*l, *v) + }, + _ => panic!() + } + } + + pub fn eval(&self) -> Token { match self { Token::Root(ref v) => { if v.len() != 1 {panic!()}; + let v = v[0].as_number(); - if let Token::Number(l, v) = v[0] { + if let Token::Number(l, v) = v { Token::Number(l, v) } else { panic!(); } }, Token::Negative(ref v) => { if v.len() != 1 {panic!()}; + let v = v[0].as_number(); - if let Token::Number(l, v) = v[0]{ + if let Token::Number(l, v) = v { Token::Number(l, -v) } else { panic!(); } }, @@ -72,8 +84,9 @@ impl Eval for Token { let mut new_pos: usize = 0; let mut new_len: usize = 0; for i in v.iter() { - if let Token::Number(l, v) = i { - let LineLocation{pos, len} = *l; + let j = i.as_number(); + if let Token::Number(l, v) = j { + let LineLocation{pos, len} = l; if new_pos == 0 {new_pos = pos}; new_len = new_len + len; sum += v; @@ -93,8 +106,9 @@ impl Eval for Token { let mut new_pos: usize = 0; let mut new_len: usize = 0; for i in v.iter() { - if let Token::Number(l, v) = i { - let LineLocation{pos, len} = *l; + let j = i.as_number(); + if let Token::Number(l, v) = j { + let LineLocation{pos, len} = l; if new_pos == 0 {new_pos = pos}; new_len = new_len + len; prod *= v; @@ -111,12 +125,12 @@ impl Eval for Token { Token::Divide(ref v) => { if v.len() != 2 {panic!()}; - let a = &v[0]; - let b = &v[1]; + let a = v[0].as_number(); + let b = v[1].as_number(); if let Token::Number(la, va) = a { if let Token::Number(lb, vb) = b { - let LineLocation{pos: posa, ..} = *la; + let LineLocation{pos: posa, ..} = la; let LineLocation{pos: posb, len: lenb} = lb; Token::Number( LineLocation { pos: posa, len: posb - posa + lenb }, @@ -128,12 +142,12 @@ impl Eval for Token { Token::Modulo(ref v) => { if v.len() != 2 {panic!()}; - let a = &v[0]; - let b = &v[1]; + let a = v[0].as_number(); + let b = v[1].as_number(); if let Token::Number(la, va) = a { if let Token::Number(lb, vb) = b { - let LineLocation{pos: posa, ..} = *la; + let LineLocation{pos: posa, ..} = la; let LineLocation{pos: posb, len: lenb} = lb; Token::Number( LineLocation { pos: posa, len: posb - posa + lenb }, @@ -145,16 +159,16 @@ impl Eval for Token { Token::Power(ref v) => { if v.len() != 2 {panic!()}; - let a = &v[0]; - let b = &v[1]; + let a = v[0].as_number(); + let b = v[1].as_number(); if let Token::Number(la, va) = a { if let Token::Number(lb, vb) = b { - let LineLocation{pos: posa, ..} = *la; + let LineLocation{pos: posa, ..} = la; let LineLocation{pos: posb, len: lenb} = lb; Token::Number( LineLocation { pos: posa, len: posb - posa + lenb }, - va.powf(*vb) + va.powf(vb) ) } else { panic!(); } } else { panic!(); } @@ -171,7 +185,7 @@ impl Eval for Token { /// The Null operator MUST be equal to zero. #[derive(Debug)] #[derive(Copy, Clone)] -pub enum Operators { +pub enum Operator { ModuloLong = 0, // Mod invoked with "mod" Subtract, Add, diff --git a/src/parser/evaluate.rs b/src/parser/evaluate.rs index 00ffc20..b495be6 100644 --- a/src/parser/evaluate.rs +++ b/src/parser/evaluate.rs @@ -1,5 +1,4 @@ use crate::parser::Token; -use crate::parser::Eval; use crate::parser::LineLocation; use crate::parser::ParserError; @@ -30,7 +29,6 @@ fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec) -> &'a mut Token { pub fn evaluate( mut g: Token, ) -> Result { - let mut coords: Vec = Vec::with_capacity(16); coords.push(0); @@ -80,12 +78,19 @@ pub fn evaluate( continue 'outer; }, + Token::Constant(_,_,_) | Token::Number(_,_) => { let l = coords.pop().unwrap(); coords.push(l + 1); continue 'outer; } - _ => panic!() + + Token::PreNumber(_,_) | + Token::PreWord(_,_) | + Token::PreOperator(_,_) | + Token::PreGroup(_,_) | + Token::Root(_) + => panic!() }; } diff --git a/src/parser/tokenize.rs b/src/parser/tokenize.rs index 3cb847e..93d4570 100644 --- a/src/parser/tokenize.rs +++ b/src/parser/tokenize.rs @@ -3,7 +3,7 @@ use std::collections::VecDeque; use crate::parser::Token; use crate::parser::LineLocation; use crate::parser::ParserError; -use crate::parser::Operators; +use crate::parser::Operator; /// Updates the length of a Token's LineLocation. /// Run whenever a token is finished. @@ -46,13 +46,18 @@ fn lookback( // Insert ImplicitMultiply (Token::PreGroup(_,_), Token::PreGroup(l ,_)) | (Token::PreGroup(_,_), Token::Number(l,_)) | - (Token::Number(_,_), Token::PreGroup(l,_)) + (Token::Number(_,_), Token::PreGroup(l,_)) | + (Token::Constant(_,_,_), Token::Number(l,_)) | + (Token::Number(_,_), Token::Constant(l,_,_)) | + (Token::Constant(_,_,_), Token::PreGroup(l,_)) | + (Token::PreGroup(_,_), Token::Constant(l,_,_)) | + (Token::Constant(_,_,_), Token::Constant(l,_,_)) => { g.push_back(a); let LineLocation { pos: i, .. } = l; g.push_back(Token::PreOperator( LineLocation{pos: i-1, len: 0}, - Operators::ImplicitMultiply + Operator::ImplicitMultiply )); g.push_back(b); }, @@ -69,11 +74,8 @@ fn lookback( } // The following are fine - (Token::PreOperator(_,_), Token::PreOperator(_,_)) | - (Token::PreOperator(_,_), Token::Number(_,_)) | - (Token::Number(_,_), Token::PreOperator(_,_)) | - (Token::PreOperator(_,_), Token::PreGroup(_,_)) | - (Token::PreGroup(_,_), Token::PreOperator(_,_)) + (Token::PreOperator(_,_), _) | + (_, Token::PreOperator(_,_)) => { g.push_back(a); g.push_back(b); }, // If we get this far, we found a Token @@ -108,7 +110,9 @@ fn push_token( }, Token::PreWord(l, s) => { if s == "mod" { - Token::PreOperator(l, Operators::ModuloLong) + Token::PreOperator(l, Operator::ModuloLong) + } else if s == "pi" { + Token::Constant(l, 3.141592653, String::from("π")) } else { return Err((l, ParserError::Syntax)); } @@ -145,7 +149,7 @@ pub fn tokenize(input: &String) -> Result { push_token(g_now, i, t)?; t = Some(Token::PreOperator( LineLocation{pos: i, len: 1}, - Operators::Factorial + Operator::Factorial )); }, @@ -161,7 +165,7 @@ pub fn tokenize(input: &String) -> Result { Some(Token::PreWord(_, _)) => { t = Some(Token::PreOperator( LineLocation{pos: i, len: 1}, - Operators::Subtract + Operator::Subtract )); }, @@ -169,7 +173,7 @@ pub fn tokenize(input: &String) -> Result { _ => { t = Some(Token::PreOperator( LineLocation{pos: i, len: 1}, - Operators::Negative + Operator::Negative )); } }; @@ -219,11 +223,11 @@ pub fn tokenize(input: &String) -> Result { t = Some(Token::PreOperator( LineLocation{pos: i, len: 1}, match c { - '^' => Operators::Power, - '%' => Operators::Modulo, - '*'|'×' => Operators::Multiply, - '/'|'÷' => Operators::Divide, - '+' => Operators::Add, + '^' => Operator::Power, + '%' => Operator::Modulo, + '*'|'×' => Operator::Multiply, + '/'|'÷' => Operator::Divide, + '+' => Operator::Add, _ => panic!() } )); diff --git a/src/parser/treeify.rs b/src/parser/treeify.rs index 6c9dd2d..e66579c 100644 --- a/src/parser/treeify.rs +++ b/src/parser/treeify.rs @@ -3,7 +3,7 @@ use std::collections::VecDeque; use crate::parser::Token; use crate::parser::LineLocation; use crate::parser::ParserError; -use crate::parser::Operators; +use crate::parser::Operator; #[inline(always)] fn get_line_location(t: &Token) -> &LineLocation { @@ -18,9 +18,9 @@ fn get_line_location(t: &Token) -> &LineLocation { } #[inline(always)] -fn select_op(k: Operators, mut new_token_args: VecDeque) -> Token { +fn select_op(k: Operator, mut new_token_args: VecDeque) -> Token { match k { - Operators::Subtract => { + Operator::Subtract => { let a = new_token_args.pop_front().unwrap(); let b = new_token_args.pop_front().unwrap(); @@ -30,15 +30,15 @@ fn select_op(k: Operators, mut new_token_args: VecDeque) -> Token { Token::Negative(VecDeque::from(vec!(b))) ))) }, - Operators::Add => Token::Add(new_token_args), - Operators::Divide => Token::Divide(new_token_args), - Operators::Multiply => Token::Multiply(new_token_args), - Operators::ImplicitMultiply => Token::Multiply(new_token_args), - Operators::Modulo => Token::Modulo(new_token_args), - Operators::ModuloLong => Token::Modulo(new_token_args), - Operators::Power => Token::Power(new_token_args), - Operators::Negative => Token::Negative(new_token_args), - Operators::Factorial => Token::Factorial(new_token_args) + Operator::Add => Token::Add(new_token_args), + Operator::Divide => Token::Divide(new_token_args), + Operator::Multiply => Token::Multiply(new_token_args), + Operator::ImplicitMultiply => Token::Multiply(new_token_args), + Operator::Modulo => Token::Modulo(new_token_args), + Operator::ModuloLong => Token::Modulo(new_token_args), + Operator::Power => Token::Power(new_token_args), + Operator::Negative => Token::Negative(new_token_args), + Operator::Factorial => Token::Factorial(new_token_args) } } @@ -74,16 +74,16 @@ fn treeify_binary( if let Token::PreOperator(l, o) = right { match o { // Binary operators - Operators::ModuloLong | - Operators::Subtract | - Operators::Add | - Operators::Divide | - Operators::Multiply | - Operators::ImplicitMultiply | - Operators::Modulo | - Operators::Power | + Operator::ModuloLong | + Operator::Subtract | + Operator::Add | + Operator::Divide | + Operator::Multiply | + Operator::ImplicitMultiply | + Operator::Modulo | + Operator::Power | // Right unary operators - Operators::Factorial + Operator::Factorial => { // Binary and right-unary operators cannot // follow a binary operator. @@ -96,7 +96,7 @@ fn treeify_binary( }, // Left unary operators - Operators::Negative => { + Operator::Negative => { i += 1; return Ok(i); } @@ -171,16 +171,16 @@ fn treeify_unaryleft( if let Token::PreOperator(l, o) = right { match o { // Binary operators - Operators::ModuloLong | - Operators::Subtract | - Operators::Add | - Operators::Divide | - Operators::Multiply | - Operators::ImplicitMultiply | - Operators::Modulo | - Operators::Power | + Operator::ModuloLong | + Operator::Subtract | + Operator::Add | + Operator::Divide | + Operator::Multiply | + Operator::ImplicitMultiply | + Operator::Modulo | + Operator::Power | // Right unary operators - Operators::Factorial + Operator::Factorial => { // Binary and right-unary operators cannot // follow a binary operator. @@ -193,7 +193,7 @@ fn treeify_unaryleft( }, // Left unary operators - Operators::Negative => { + Operator::Negative => { i += 1; return Ok(i); } @@ -272,7 +272,7 @@ fn treeify_unaryright( if let Token::PreOperator(l, o) = right.unwrap() { match o { // Left unary operators - Operators::Negative => { + Operator::Negative => { let LineLocation { pos: posa, .. } = *get_line_location(&this); let LineLocation { pos: posb, len: lenb } = *l; return Err(( @@ -358,20 +358,20 @@ fn inner_treeify( }; match this_op { - Operators::ModuloLong | - Operators::Subtract | - Operators::Add | - Operators::Divide | - Operators::Multiply | - Operators::ImplicitMultiply | - Operators::Modulo | - Operators::Power + Operator::ModuloLong | + Operator::Subtract | + Operator::Add | + Operator::Divide | + Operator::Multiply | + Operator::ImplicitMultiply | + Operator::Modulo | + Operator::Power => { i = treeify_binary(i, g_inner)?; }, - Operators::Negative + Operator::Negative => { i = treeify_unaryleft(i, g_inner)?; }, - Operators::Factorial + Operator::Factorial => { i = treeify_unaryright(i, g_inner)?; } }; @@ -386,7 +386,7 @@ fn inner_treeify( return Err((l, ParserError::Syntax)); }, Token::PreGroup(_,_) => { - g = treeify(g)?; + g = inner_treeify(g)?; } _ => {} };