pull/2/head
Mark 2023-04-10 18:46:46 -07:00
parent 7c86ba070f
commit fbc0a6557e
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
6 changed files with 150 additions and 151 deletions

View File

@ -12,9 +12,7 @@ use termion::{
}; };
use super::promptbuffer::PromptBuffer; use super::promptbuffer::PromptBuffer;
use crate::parser; use crate::parser;
use crate::evaluate;
#[inline(always)] #[inline(always)]
fn draw_greeter(stdout: &mut RawTerminal<std::io::Stdout>) -> Result<(), std::io::Error> { fn draw_greeter(stdout: &mut RawTerminal<std::io::Stdout>) -> Result<(), std::io::Error> {
@ -82,7 +80,7 @@ pub fn main() -> Result<(), std::io::Error> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::suspend_raw_mode(&stdout)?; RawTerminal::suspend_raw_mode(&stdout)?;
let out_str = g.to_string(); let out_str = g.to_string();
let g = evaluate::evaluate(g); let g = g.evaluate();
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::activate_raw_mode(&stdout)?; RawTerminal::activate_raw_mode(&stdout)?;

View File

@ -1,62 +0,0 @@
use crate::tokens::Token;
#[inline(always)]
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 = h.get_args_mut().unwrap();
h = &mut inner[*t];
}
return h;
}
pub fn evaluate(
mut g: Token,
) -> Result<Token, ()> {
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 = h.get_args_mut();
if inner.is_none() || *t >= inner.as_ref().unwrap().len() {
coords.pop();
let p = get_at_coords(&mut g, &coords);
let e = p.eval()?;
*p = e;
if coords.len() == 0 { break 'outer; }
let l = coords.pop().unwrap();
coords.push(l + 1);
continue 'outer;
}
h = &mut inner.unwrap()[*t];
}
match h {
Token::Operator(_,_)
=> {
coords.push(0);
continue 'outer;
},
Token::Constant(_,_) |
Token::Number(_) => {
let l = coords.pop().unwrap();
coords.push(l + 1);
continue 'outer;
}
};
}
return Ok(g);
}

View File

@ -1,6 +1,5 @@
pub mod tokens; pub mod tokens;
pub mod parser; pub mod parser;
pub mod evaluate;
pub mod quantity; pub mod quantity;
//use crate::tokens::Token; //use crate::tokens::Token;

View File

@ -1,6 +1,5 @@
// Many of these have been borrowed from insect. // Many of these have been borrowed from insect.
use crate::parser; use crate::parser;
use crate::evaluate;
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(&String::from(s)) {
@ -9,7 +8,7 @@ fn eval_to_str(s: &str) -> Result<String, ()> {
}; };
//let out_str = g.print(); //let out_str = g.print();
return match evaluate::evaluate(g) { return match g.evaluate() {
Ok(x) => Ok(x.to_string_outer()), Ok(x) => Ok(x.to_string_outer()),
Err(_) => Err(()) Err(_) => Err(())
}; };

View File

@ -1,87 +1,7 @@
use std::collections::VecDeque;
mod function; mod function;
mod operator; mod operator;
mod token;
pub use crate::tokens::token::Token;
pub use crate::tokens::function::Function; pub use crate::tokens::function::Function;
pub use crate::tokens::operator::Operator; pub use crate::tokens::operator::Operator;
use crate::quantity::Quantity;
/// 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)]
#[derive(Clone)]
pub enum Token {
Number(Quantity),
Constant(Quantity, String),
Operator(
Operator,
VecDeque<Token>
),
}
impl ToString for Token {
fn to_string(&self) -> String {
match self {
Token::Number(v) => v.to_string(),
Token::Constant(_, s) => s.clone(),
Token::Operator(o,a) => o.print(a)
}
}
}
impl Token {
// This is called only when this is the outermost token.
// This sometimes leads to different--usually more verbose--behavior.
pub fn to_string_outer(&self) -> String {
match self {
Token::Number(v) => v.to_string_outer(),
Token::Constant(_, s) => s.clone(),
Token::Operator(o,a) => o.print(a)
}
}
#[inline(always)]
pub fn get_args(&self) -> Option<&VecDeque<Token>> {
match self {
Token::Operator(_, ref a) => Some(a),
_ => None
}
}
#[inline(always)]
pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Token>> {
match self {
Token::Operator(_, ref mut a) => Some(a),
_ => None
}
}
#[inline(always)]
pub fn eval(&self) -> Result<Token, ()> {
Ok(match self {
Token::Number(_) => { self.clone() },
Token::Constant(v,_) => { Token::Number(v.clone()) },
Token::Operator(o,v) => { o.apply(&v)? }
})
}
// Temporary solution
#[inline(always)]
pub fn as_number(&self) -> Token {
match self {
Token::Number(v) => { Token::Number(v.clone()) },
Token::Constant(v,_) => { Token::Number(v.clone()) },
_ => panic!()
}
}
}

145
src/tokens/token.rs Normal file
View File

@ -0,0 +1,145 @@
use std::collections::VecDeque;
use crate::tokens::Operator;
use crate::quantity::Quantity;
/// 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)]
#[derive(Clone)]
pub enum Token {
Number(Quantity),
Constant(Quantity, String),
Operator(
Operator,
VecDeque<Token>
),
}
impl ToString for Token {
fn to_string(&self) -> String {
match self {
Token::Number(v) => v.to_string(),
Token::Constant(_, s) => s.clone(),
Token::Operator(o,a) => o.print(a)
}
}
}
impl Token {
// This is called only when this is the outermost token.
// This sometimes leads to different--usually more verbose--behavior.
pub fn to_string_outer(&self) -> String {
match self {
Token::Number(v) => v.to_string_outer(),
Token::Constant(_, s) => s.clone(),
Token::Operator(o,a) => o.print(a)
}
}
#[inline(always)]
pub fn get_args(&self) -> Option<&VecDeque<Token>> {
match self {
Token::Operator(_, ref a) => Some(a),
_ => None
}
}
#[inline(always)]
pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Token>> {
match self {
Token::Operator(_, ref mut a) => Some(a),
_ => None
}
}
#[inline(always)]
pub fn eval(&self) -> Result<Token, ()> {
Ok(match self {
Token::Number(_) => { self.clone() },
Token::Constant(v,_) => { Token::Number(v.clone()) },
Token::Operator(o,v) => { o.apply(&v)? }
})
}
// Temporary solution
#[inline(always)]
pub fn as_number(&self) -> Token {
match self {
Token::Number(v) => { Token::Number(v.clone()) },
Token::Constant(v,_) => { Token::Number(v.clone()) },
_ => panic!()
}
}
}
// Evaluate
impl Token {
#[inline(always)]
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 = h.get_args_mut().unwrap();
h = &mut inner[*t];
}
return h;
}
pub fn evaluate(&self) -> Result<Token, ()> {
let mut g = self.clone();
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 = h.get_args_mut();
if inner.is_none() || *t >= inner.as_ref().unwrap().len() {
coords.pop();
let p = Token::get_at_coords(&mut g, &coords);
let e = p.eval()?;
*p = e;
if coords.len() == 0 { break 'outer; }
let l = coords.pop().unwrap();
coords.push(l + 1);
continue 'outer;
}
h = &mut inner.unwrap()[*t];
}
match h {
Token::Operator(_,_)
=> {
coords.push(0);
continue 'outer;
},
Token::Constant(_,_) |
Token::Number(_) => {
let l = coords.pop().unwrap();
coords.push(l + 1);
continue 'outer;
}
};
}
return Ok(g);
}
}