Added basic evaluation

This commit is contained in:
2023-03-24 13:16:58 -07:00
parent 8bbe880bd4
commit 1f9bcccab4
3 changed files with 264 additions and 16 deletions

95
src/parser/evaluate.rs Normal file
View File

@ -0,0 +1,95 @@
use std::collections::VecDeque;
use crate::parser::Token;
use crate::parser::Eval;
use crate::parser::LineLocation;
use crate::parser::ParserError;
fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec<usize>) -> &'a mut Token {
let mut h = &mut *g;
for t in coords.iter() {
let inner = match h {
Token::Multiply(ref mut v) => v,
Token::Divide(ref mut v) => v,
Token::Add(ref mut v) => v,
Token::Factorial(ref mut v) => v,
Token::Negative(ref mut v) => v,
Token::Power(ref mut v) => v,
Token::Modulo(ref mut v) => v,
Token::Root(ref mut v) => v,
_ => panic!()
};
h = &mut inner[*t];
}
return h;
}
pub fn evaluate(
mut g: Token,
) -> Result<Token, (LineLocation, ParserError)> {
let mut coords: Vec<usize> = Vec::with_capacity(16);
coords.push(0);
'outer: loop {
let mut h = &mut g;
for t in coords.iter() {
let inner = match h {
Token::Multiply(ref mut v) => v,
Token::Divide(ref mut v) => v,
Token::Add(ref mut v) => v,
Token::Factorial(ref mut v) => v,
Token::Negative(ref mut v) => v,
Token::Power(ref mut v) => v,
Token::Modulo(ref mut v) => v,
Token::Root(ref mut v) => v,
_ => panic!()
};
if *t >= inner.len() {
coords.pop();
if coords.len() == 0 { break 'outer; }
let p = get_at_coords(&mut g, &coords);
let e = p.eval();
*p = e;
let l = coords.pop().unwrap();
coords.push(l + 1);
continue 'outer;
}
h = &mut inner[*t];
}
match h {
Token::Multiply(v) |
Token::Divide(v) |
Token::Add(v) |
Token::Factorial(v) |
Token::Negative(v) |
Token::Power(v) |
Token::Modulo(v)
=> {
coords.push(0);
continue 'outer;
},
Token::Number(_,_) => {
let l = coords.pop().unwrap();
coords.push(l + 1);
continue 'outer;
}
_ => panic!()
};
}
return Ok(g);
}

View File

@ -18,9 +18,18 @@ fn get_line_location(t: &Token) -> &LineLocation {
}
#[inline(always)]
fn select_op(k: Operators, new_token_args: VecDeque<Token>) -> Token {
fn select_op(k: Operators, mut new_token_args: VecDeque<Token>) -> Token {
match k {
Operators::Subtract => Token::Subtract(new_token_args),
Operators::Subtract => {
let a = new_token_args.pop_front().unwrap();
let b = new_token_args.pop_front().unwrap();
Token::Add(
VecDeque::from(vec!(
a,
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),
@ -114,8 +123,8 @@ fn treeify_binary(
let mut left = g_inner.remove(i-1).unwrap();
let this = g_inner.remove(i-1).unwrap();
let mut right = g_inner.remove(i-1).unwrap();
if let Token::PreGroup(_, _) = right { treeify(&mut right)?; }
if let Token::PreGroup(_, _) = left { treeify(&mut left)?; }
if let Token::PreGroup(_, _) = right { right = inner_treeify(right)?; }
if let Token::PreGroup(_, _) = left { left = inner_treeify(left)?; }
let k = match this {
Token::PreOperator(_, k) => k,
@ -209,7 +218,7 @@ fn treeify_unaryleft(
if right_val.is_none() || this_val > right_val.unwrap() {
let this = g_inner.remove(i).unwrap();
let mut right = g_inner.remove(i).unwrap();
if let Token::PreGroup(_, _) = right { treeify(&mut right)?; }
if let Token::PreGroup(_, _) = right { right = inner_treeify(right)?; }
let k = match this {
Token::PreOperator(_, k) => k,
@ -309,7 +318,7 @@ fn treeify_unaryright(
if left_val.is_none() || this_val > left_val.unwrap() {
let this = g_inner.remove(i).unwrap();
let mut left = g_inner.remove(i-1).unwrap();
if let Token::PreGroup(_, _) = left { treeify(&mut left)?; }
if let Token::PreGroup(_, _) = left { left = inner_treeify(left)?; }
let k = match this {
Token::PreOperator(_, k) => k,
@ -332,9 +341,9 @@ fn treeify_unaryright(
};
}
pub fn treeify(
g: &mut Token,
) -> Result<(), (LineLocation, ParserError)> {
fn inner_treeify(
mut g: Token,
) -> Result<Token, (LineLocation, ParserError)> {
let g_inner: &mut VecDeque<Token> = match g {
Token::PreGroup(_, ref mut x) => x,
@ -368,19 +377,28 @@ pub fn treeify(
};
}
*g = g_inner.pop_front().unwrap();
g = g_inner.pop_front().unwrap();
// Catch the edge case where the entire group we're given
// consists of one operator. This is always a syntax error.
match g {
Token::PreOperator(l, _) => {
return Err((*l, ParserError::Syntax));
return Err((l, ParserError::Syntax));
},
Token::PreGroup(_,_) => {
treeify(g)?;
g = treeify(g)?;
}
_ => {}
};
return Ok(());
return Ok(g);
}
pub fn treeify(
mut g: Token,
) -> Result<Token, (LineLocation, ParserError)> {
let mut v: VecDeque<Token> = VecDeque::new();
v.push_back(inner_treeify(g)?);
g = Token::Root(v);
return Ok(g);
}