Reorganized variable code

pull/2/head
Mark 2023-06-14 16:15:51 -07:00
parent 5ffad0cc4e
commit 00a421756d
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
10 changed files with 39 additions and 47 deletions

View File

@ -100,7 +100,7 @@ pub fn write(target: &Path) {
for c in constants { for c in constants {
writeln!(file, writeln!(file,
"\t\t\tConstant::{e} => parse(&String::from(\"{s}\")).unwrap(),", "\t\t\tConstant::{e} => parse_no_context(&String::from(\"{s}\")).unwrap(),",
e = c["enum_name"].as_str().unwrap(), e = c["enum_name"].as_str().unwrap(),
s = c["value"].as_str().unwrap() s = c["value"].as_str().unwrap()
).unwrap(); ).unwrap();

View File

@ -16,14 +16,14 @@ impl Context {
pub fn push_var(&mut self, s: String, t: Token) { self.variables.insert(s, t); } pub fn push_var(&mut self, s: String, t: Token) { self.variables.insert(s, t); }
pub fn del_var(&mut self, s: &String) { self.variables.remove(s); } pub fn del_var(&mut self, s: &String) { self.variables.remove(s); }
pub fn get_variable(&self, s: String) -> Option<Token> { pub fn get_variable(&self, s: &String) -> Option<Token> {
let v: Option<&Token>; let v: Option<&Token>;
if s == "ans" { if s == "ans" {
v = self.history.last(); v = self.history.last();
} else { } else {
v = self.variables.get(&s); v = self.variables.get(s);
} }
if v.is_some() { Some(v.unwrap().clone()) } else { None } if v.is_some() { Some(v.unwrap().clone()) } else { None }

View File

@ -28,7 +28,7 @@ fn do_expression(
) -> Result<parser::Token, ()> { ) -> Result<parser::Token, ()> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::suspend_raw_mode(&stdout).unwrap(); RawTerminal::suspend_raw_mode(&stdout).unwrap();
let g = parser::parse(&s); let g = parser::parse(&s, context);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::activate_raw_mode(&stdout).unwrap(); RawTerminal::activate_raw_mode(&stdout).unwrap();
@ -118,16 +118,6 @@ fn do_expression(
style::Reset, style::Reset,
color::Fg(color::Reset), color::Fg(color::Reset),
).unwrap(); ).unwrap();
},
Err(EvalError::NoHistory) => {
write!(
stdout, "\n {}{}Evaluation Error: {}There is no previous answer to reference{}\r\n\n",
style::Bold,
color::Fg(color::Red),
style::Reset,
color::Fg(color::Reset),
).unwrap();
} }
} }
} }

View File

@ -35,11 +35,7 @@ pub fn evaluate(t: &Token, context: &Context) -> Result<Token, EvalError> {
Token::Constant(c) => { evaluate(&c.value(), context).unwrap() }, Token::Constant(c) => { evaluate(&c.value(), context).unwrap() },
Token::Operator(Operator::Function(f), v) => { eval_function(&f, &v)? }, Token::Operator(Operator::Function(f), v) => { eval_function(&f, &v)? },
Token::Operator(o, v) => { eval_operator(&o, &v)? }, Token::Operator(o, v) => { eval_operator(&o, &v)? },
Token::Variable(s) => { Token::Variable(s) => { context.get_variable(&s).unwrap() }
if let Some(t) = context.get_variable(s) { t } else {
return Err(EvalError::NoHistory);
}
}
}; };
} }

View File

@ -9,6 +9,5 @@ pub enum EvalError {
BadMath, BadMath,
TooBig, TooBig,
ZeroDivision, ZeroDivision,
IncompatibleUnit, IncompatibleUnit
NoHistory
} }

View File

@ -17,22 +17,26 @@ pub use self::{
token::Function, token::Function,
}; };
use crate::context::Context;
pub fn parse( pub fn parse(
s: &String s: &String, context: &Context
) -> Result< ) -> Result<Token, (LineLocation, ParserError)> {
Token,
(LineLocation, ParserError)
> {
let tokens = stage::tokenize(s); let tokens = stage::tokenize(s);
let (_, tokens) = stage::find_subs(tokens); let (_, tokens) = stage::find_subs(tokens);
let g = stage::groupify(tokens)?; let g = stage::groupify(tokens)?;
let g = stage::treeify(g)?;
let g = stage::treeify(g, context)?;
return Ok(g); return Ok(g);
} }
pub fn parse_no_context(s: &String) -> Result<Token, (LineLocation, ParserError)> {
parse(s, &Context::new())
}
pub fn substitute( pub fn substitute(
s: &String, // The string to substitute s: &String, // The string to substitute

View File

@ -1,6 +1,7 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::quantity::Unit; use crate::quantity::Unit;
use crate::quantity::Quantity; use crate::quantity::Quantity;
use crate::context::Context;
use super::{ use super::{
LineLocation, LineLocation,
@ -55,7 +56,7 @@ impl PreToken {
} }
#[inline(always)] #[inline(always)]
pub fn to_token(self) -> Result<Token, (LineLocation, ParserError)>{ pub fn to_token(self, context: &Context) -> Result<Token, (LineLocation, ParserError)>{
match self { match self {
PreToken::PreQuantity(l, mut s) => { PreToken::PreQuantity(l, mut s) => {
@ -74,17 +75,15 @@ impl PreToken {
}, },
PreToken::PreWord(l, s) => { PreToken::PreWord(l, s) => {
let c = Constant::from_string(&s);
if c.is_some() { let c = Constant::from_string(&s);
return Ok(Token::Constant(c.unwrap())); if c.is_some() { return Ok(Token::Constant(c.unwrap())); }
}
let c = Unit::from_string(&s); let c = Unit::from_string(&s);
if c.is_some() { return Ok(Token::Quantity(c.unwrap())); } if c.is_some() { return Ok(Token::Quantity(c.unwrap())); }
let c = context.get_variable(&s);
if s == "ans" { return Ok(Token::Variable(String::from("ans"))); } if c.is_some() { return Ok(Token::Variable(s)); }
return Err((l, ParserError::Undefined(s))); return Err((l, ParserError::Undefined(s)));
} }

View File

@ -1,4 +1,5 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::context::Context;
use super::super::{ use super::super::{
PreToken, PreToken,
@ -10,7 +11,8 @@ use super::super::{
fn treeify_binary( fn treeify_binary(
i: usize, i: usize,
g_inner: &mut VecDeque<PreToken> g_inner: &mut VecDeque<PreToken>,
context: &Context
) -> Result<bool, (LineLocation, ParserError)> { ) -> Result<bool, (LineLocation, ParserError)> {
let this: &PreToken = &g_inner[i]; let this: &PreToken = &g_inner[i];
@ -125,8 +127,8 @@ fn treeify_binary(
let this_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 right_pre = g_inner.remove(i-1).unwrap();
let left: Token; let right: Token; 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(_, _) = right_pre { right = treeify(right_pre, context)?; } else {right = right_pre.to_token(context)?;}
if let PreToken::PreGroup(_, _) = left_pre { left = treeify(left_pre)?; } else {left = left_pre.to_token()?;} if let PreToken::PreGroup(_, _) = left_pre { left = treeify(left_pre, context)?; } else {left = left_pre.to_token(context)?;}
let o = { let o = {
let PreToken::PreOperator(_, s) = this_pre else {panic!()}; let PreToken::PreOperator(_, s) = this_pre else {panic!()};
@ -150,7 +152,8 @@ fn treeify_binary(
fn treeify_unary( fn treeify_unary(
i: usize, i: usize,
g_inner: &mut VecDeque<PreToken>, g_inner: &mut VecDeque<PreToken>,
left_associative: bool left_associative: bool,
context: &Context
) -> Result<bool, (LineLocation, ParserError)> { ) -> Result<bool, (LineLocation, ParserError)> {
let this: &PreToken = &g_inner[i]; let this: &PreToken = &g_inner[i];
@ -242,7 +245,7 @@ fn treeify_unary(
} else { } else {
next_pre = g_inner.remove(i).unwrap(); next_pre = g_inner.remove(i).unwrap();
} }
if let PreToken::PreGroup(_, _) = next_pre { next = treeify(next_pre)?; } else { next = next_pre.to_token()? } if let PreToken::PreGroup(_, _) = next_pre { next = treeify(next_pre, context)?; } else { next = next_pre.to_token(context)? }
let o = { let o = {
let PreToken::PreOperator(_, s) = this_pre else {panic!()}; let PreToken::PreOperator(_, s) = this_pre else {panic!()};
@ -272,6 +275,7 @@ fn treeify_unary(
pub fn treeify( pub fn treeify(
mut g: PreToken, mut g: PreToken,
context: &Context
) -> Result<Token, (LineLocation, ParserError)> { ) -> Result<Token, (LineLocation, ParserError)> {
let g_inner: &mut VecDeque<PreToken> = match g { let g_inner: &mut VecDeque<PreToken> = match g {
@ -311,9 +315,9 @@ pub fn treeify(
let mut changed = false; let mut changed = false;
if this_op.is_left_associative() { if this_op.is_left_associative() {
if this_op.is_binary() { if this_op.is_binary() {
changed = treeify_binary(i, g_inner)?; changed = treeify_binary(i, g_inner, context)?;
} else { } else {
changed = treeify_unary(i, g_inner, left_associative)?; changed = treeify_unary(i, g_inner, left_associative, context)?;
} }
} }
@ -325,9 +329,9 @@ pub fn treeify(
} else { } else {
if !this_op.is_left_associative() { if !this_op.is_left_associative() {
if this_op.is_binary() { if this_op.is_binary() {
treeify_binary(i, g_inner)?; treeify_binary(i, g_inner, context)?;
} else { } else {
treeify_unary(i, g_inner, left_associative)?; treeify_unary(i, g_inner, left_associative, context)?;
} }
} }
j -= 1 j -= 1
@ -342,9 +346,9 @@ pub fn treeify(
Err((l, ParserError::Syntax)) Err((l, ParserError::Syntax))
}, },
PreToken::PreGroup(_,_) => { PreToken::PreGroup(_,_) => {
treeify(g) treeify(g, context)
}, },
_ => { Ok(g.to_token()?) } _ => { Ok(g.to_token(context)?) }
}; };
} }

View File

@ -7,5 +7,5 @@ pub use self::function::Function;
pub use self::token::Token; pub use self::token::Token;
use super::parse; use super::parse_no_context;
include!(concat!(env!("OUT_DIR"), "/constants.rs")); include!(concat!(env!("OUT_DIR"), "/constants.rs"));

View File

@ -4,7 +4,7 @@ use crate::evaluate::evaluate;
use crate::context::Context; use crate::context::Context;
fn eval_to_str(s: &str) -> Result<String, ()> { fn eval_to_str(s: &str) -> Result<String, ()> {
let g = match parser::parse(&String::from(s)) { let g = match parser::parse_no_context(&String::from(s)) {
Ok(x) => x, Ok(x) => x,
Err(_) => return Err(()) Err(_) => return Err(())
}; };