Added Constants

Fixed treeify bug
pull/2/head
Mark 2023-03-24 20:21:48 -07:00
parent 5fc7a7922e
commit cafe1c9c64
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
5 changed files with 113 additions and 91 deletions

View File

@ -13,7 +13,6 @@ use crate::promptbuffer::PromptBuffer;
use crate::parser::Token; use crate::parser::Token;
//use crate::parser::ParserError; //use crate::parser::ParserError;
use crate::parser::LineLocation; use crate::parser::LineLocation;
use crate::parser::Eval;
fn draw_line( fn draw_line(

View File

@ -14,10 +14,6 @@ use std::collections::VecDeque;
/// Tokens starting with `Pre*` are intermediate tokens, and /// Tokens starting with `Pre*` are intermediate tokens, and
/// will never show up in a fully-parsed expression tree. /// will never show up in a fully-parsed expression tree.
pub trait Eval {
fn eval(&self) -> Token;
}
#[derive(Debug)] #[derive(Debug)]
pub enum Token { pub enum Token {
@ -31,14 +27,16 @@ pub enum Token {
/// Used only until operators are parsed. /// Used only until operators are parsed.
/// Each of these will become one of the operators below. /// Each of these will become one of the operators below.
PreOperator(LineLocation, Operators), PreOperator(LineLocation, Operator),
/// Used only until operators are parsed. /// Used only until operators are parsed.
/// PreGroups aren't needed once we have a tree. /// PreGroups aren't needed once we have a tree.
PreGroup(LineLocation, VecDeque<Token>), PreGroup(LineLocation, VecDeque<Token>),
Root(VecDeque<Token>),
Number(LineLocation, f64), Number(LineLocation, f64),
Constant(LineLocation, f64, String),
Root(VecDeque<Token>),
Multiply(VecDeque<Token>), Multiply(VecDeque<Token>),
Divide(VecDeque<Token>), Divide(VecDeque<Token>),
Add(VecDeque<Token>), Add(VecDeque<Token>),
@ -48,21 +46,35 @@ pub enum Token {
Modulo(VecDeque<Token>), Modulo(VecDeque<Token>),
} }
impl Eval for Token { impl Token {
fn eval(&self) -> 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 { match self {
Token::Root(ref v) => { Token::Root(ref v) => {
if v.len() != 1 {panic!()}; 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) Token::Number(l, v)
} else { panic!(); } } else { panic!(); }
}, },
Token::Negative(ref v) => { Token::Negative(ref v) => {
if v.len() != 1 {panic!()}; 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) Token::Number(l, -v)
} else { panic!(); } } else { panic!(); }
}, },
@ -72,8 +84,9 @@ impl Eval for Token {
let mut new_pos: usize = 0; let mut new_pos: usize = 0;
let mut new_len: usize = 0; let mut new_len: usize = 0;
for i in v.iter() { for i in v.iter() {
if let Token::Number(l, v) = i { let j = i.as_number();
let LineLocation{pos, len} = *l; if let Token::Number(l, v) = j {
let LineLocation{pos, len} = l;
if new_pos == 0 {new_pos = pos}; if new_pos == 0 {new_pos = pos};
new_len = new_len + len; new_len = new_len + len;
sum += v; sum += v;
@ -93,8 +106,9 @@ impl Eval for Token {
let mut new_pos: usize = 0; let mut new_pos: usize = 0;
let mut new_len: usize = 0; let mut new_len: usize = 0;
for i in v.iter() { for i in v.iter() {
if let Token::Number(l, v) = i { let j = i.as_number();
let LineLocation{pos, len} = *l; if let Token::Number(l, v) = j {
let LineLocation{pos, len} = l;
if new_pos == 0 {new_pos = pos}; if new_pos == 0 {new_pos = pos};
new_len = new_len + len; new_len = new_len + len;
prod *= v; prod *= v;
@ -111,12 +125,12 @@ impl Eval for Token {
Token::Divide(ref v) => { Token::Divide(ref v) => {
if v.len() != 2 {panic!()}; if v.len() != 2 {panic!()};
let a = &v[0]; let a = v[0].as_number();
let b = &v[1]; let b = v[1].as_number();
if let Token::Number(la, va) = a { if let Token::Number(la, va) = a {
if let Token::Number(lb, vb) = b { if let Token::Number(lb, vb) = b {
let LineLocation{pos: posa, ..} = *la; let LineLocation{pos: posa, ..} = la;
let LineLocation{pos: posb, len: lenb} = lb; let LineLocation{pos: posb, len: lenb} = lb;
Token::Number( Token::Number(
LineLocation { pos: posa, len: posb - posa + lenb }, LineLocation { pos: posa, len: posb - posa + lenb },
@ -128,12 +142,12 @@ impl Eval for Token {
Token::Modulo(ref v) => { Token::Modulo(ref v) => {
if v.len() != 2 {panic!()}; if v.len() != 2 {panic!()};
let a = &v[0]; let a = v[0].as_number();
let b = &v[1]; let b = v[1].as_number();
if let Token::Number(la, va) = a { if let Token::Number(la, va) = a {
if let Token::Number(lb, vb) = b { if let Token::Number(lb, vb) = b {
let LineLocation{pos: posa, ..} = *la; let LineLocation{pos: posa, ..} = la;
let LineLocation{pos: posb, len: lenb} = lb; let LineLocation{pos: posb, len: lenb} = lb;
Token::Number( Token::Number(
LineLocation { pos: posa, len: posb - posa + lenb }, LineLocation { pos: posa, len: posb - posa + lenb },
@ -145,16 +159,16 @@ impl Eval for Token {
Token::Power(ref v) => { Token::Power(ref v) => {
if v.len() != 2 {panic!()}; if v.len() != 2 {panic!()};
let a = &v[0]; let a = v[0].as_number();
let b = &v[1]; let b = v[1].as_number();
if let Token::Number(la, va) = a { if let Token::Number(la, va) = a {
if let Token::Number(lb, vb) = b { if let Token::Number(lb, vb) = b {
let LineLocation{pos: posa, ..} = *la; let LineLocation{pos: posa, ..} = la;
let LineLocation{pos: posb, len: lenb} = lb; let LineLocation{pos: posb, len: lenb} = lb;
Token::Number( Token::Number(
LineLocation { pos: posa, len: posb - posa + lenb }, LineLocation { pos: posa, len: posb - posa + lenb },
va.powf(*vb) va.powf(vb)
) )
} else { panic!(); } } else { panic!(); }
} else { panic!(); } } else { panic!(); }
@ -171,7 +185,7 @@ impl Eval for Token {
/// The Null operator MUST be equal to zero. /// The Null operator MUST be equal to zero.
#[derive(Debug)] #[derive(Debug)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum Operators { pub enum Operator {
ModuloLong = 0, // Mod invoked with "mod" ModuloLong = 0, // Mod invoked with "mod"
Subtract, Subtract,
Add, Add,

View File

@ -1,5 +1,4 @@
use crate::parser::Token; use crate::parser::Token;
use crate::parser::Eval;
use crate::parser::LineLocation; use crate::parser::LineLocation;
use crate::parser::ParserError; use crate::parser::ParserError;
@ -30,7 +29,6 @@ fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec<usize>) -> &'a mut Token {
pub fn evaluate( pub fn evaluate(
mut g: Token, mut g: Token,
) -> Result<Token, (LineLocation, ParserError)> { ) -> Result<Token, (LineLocation, ParserError)> {
let mut coords: Vec<usize> = Vec::with_capacity(16); let mut coords: Vec<usize> = Vec::with_capacity(16);
coords.push(0); coords.push(0);
@ -80,12 +78,19 @@ pub fn evaluate(
continue 'outer; continue 'outer;
}, },
Token::Constant(_,_,_) |
Token::Number(_,_) => { Token::Number(_,_) => {
let l = coords.pop().unwrap(); let l = coords.pop().unwrap();
coords.push(l + 1); coords.push(l + 1);
continue 'outer; continue 'outer;
} }
_ => panic!()
Token::PreNumber(_,_) |
Token::PreWord(_,_) |
Token::PreOperator(_,_) |
Token::PreGroup(_,_) |
Token::Root(_)
=> panic!()
}; };
} }

View File

@ -3,7 +3,7 @@ use std::collections::VecDeque;
use crate::parser::Token; use crate::parser::Token;
use crate::parser::LineLocation; use crate::parser::LineLocation;
use crate::parser::ParserError; use crate::parser::ParserError;
use crate::parser::Operators; use crate::parser::Operator;
/// Updates the length of a Token's LineLocation. /// Updates the length of a Token's LineLocation.
/// Run whenever a token is finished. /// Run whenever a token is finished.
@ -46,13 +46,18 @@ fn lookback(
// Insert ImplicitMultiply // Insert ImplicitMultiply
(Token::PreGroup(_,_), Token::PreGroup(l ,_)) | (Token::PreGroup(_,_), Token::PreGroup(l ,_)) |
(Token::PreGroup(_,_), Token::Number(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); g.push_back(a);
let LineLocation { pos: i, .. } = l; let LineLocation { pos: i, .. } = l;
g.push_back(Token::PreOperator( g.push_back(Token::PreOperator(
LineLocation{pos: i-1, len: 0}, LineLocation{pos: i-1, len: 0},
Operators::ImplicitMultiply Operator::ImplicitMultiply
)); ));
g.push_back(b); g.push_back(b);
}, },
@ -69,11 +74,8 @@ fn lookback(
} }
// The following are fine // The following are fine
(Token::PreOperator(_,_), Token::PreOperator(_,_)) | (Token::PreOperator(_,_), _) |
(Token::PreOperator(_,_), Token::Number(_,_)) | (_, Token::PreOperator(_,_))
(Token::Number(_,_), Token::PreOperator(_,_)) |
(Token::PreOperator(_,_), Token::PreGroup(_,_)) |
(Token::PreGroup(_,_), Token::PreOperator(_,_))
=> { g.push_back(a); g.push_back(b); }, => { g.push_back(a); g.push_back(b); },
// If we get this far, we found a Token // If we get this far, we found a Token
@ -108,7 +110,9 @@ fn push_token(
}, },
Token::PreWord(l, s) => { Token::PreWord(l, s) => {
if s == "mod" { 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 { } else {
return Err((l, ParserError::Syntax)); return Err((l, ParserError::Syntax));
} }
@ -145,7 +149,7 @@ pub fn tokenize(input: &String) -> Result<Token, (LineLocation, ParserError)> {
push_token(g_now, i, t)?; push_token(g_now, i, t)?;
t = Some(Token::PreOperator( t = Some(Token::PreOperator(
LineLocation{pos: i, len: 1}, LineLocation{pos: i, len: 1},
Operators::Factorial Operator::Factorial
)); ));
}, },
@ -161,7 +165,7 @@ pub fn tokenize(input: &String) -> Result<Token, (LineLocation, ParserError)> {
Some(Token::PreWord(_, _)) => { Some(Token::PreWord(_, _)) => {
t = Some(Token::PreOperator( t = Some(Token::PreOperator(
LineLocation{pos: i, len: 1}, LineLocation{pos: i, len: 1},
Operators::Subtract Operator::Subtract
)); ));
}, },
@ -169,7 +173,7 @@ pub fn tokenize(input: &String) -> Result<Token, (LineLocation, ParserError)> {
_ => { _ => {
t = Some(Token::PreOperator( t = Some(Token::PreOperator(
LineLocation{pos: i, len: 1}, LineLocation{pos: i, len: 1},
Operators::Negative Operator::Negative
)); ));
} }
}; };
@ -219,11 +223,11 @@ pub fn tokenize(input: &String) -> Result<Token, (LineLocation, ParserError)> {
t = Some(Token::PreOperator( t = Some(Token::PreOperator(
LineLocation{pos: i, len: 1}, LineLocation{pos: i, len: 1},
match c { match c {
'^' => Operators::Power, '^' => Operator::Power,
'%' => Operators::Modulo, '%' => Operator::Modulo,
'*'|'×' => Operators::Multiply, '*'|'×' => Operator::Multiply,
'/'|'÷' => Operators::Divide, '/'|'÷' => Operator::Divide,
'+' => Operators::Add, '+' => Operator::Add,
_ => panic!() _ => panic!()
} }
)); ));

View File

@ -3,7 +3,7 @@ use std::collections::VecDeque;
use crate::parser::Token; use crate::parser::Token;
use crate::parser::LineLocation; use crate::parser::LineLocation;
use crate::parser::ParserError; use crate::parser::ParserError;
use crate::parser::Operators; use crate::parser::Operator;
#[inline(always)] #[inline(always)]
fn get_line_location(t: &Token) -> &LineLocation { fn get_line_location(t: &Token) -> &LineLocation {
@ -18,9 +18,9 @@ fn get_line_location(t: &Token) -> &LineLocation {
} }
#[inline(always)] #[inline(always)]
fn select_op(k: Operators, mut new_token_args: VecDeque<Token>) -> Token { fn select_op(k: Operator, mut new_token_args: VecDeque<Token>) -> Token {
match k { match k {
Operators::Subtract => { Operator::Subtract => {
let a = new_token_args.pop_front().unwrap(); let a = new_token_args.pop_front().unwrap();
let b = 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 {
Token::Negative(VecDeque::from(vec!(b))) Token::Negative(VecDeque::from(vec!(b)))
))) )))
}, },
Operators::Add => Token::Add(new_token_args), Operator::Add => Token::Add(new_token_args),
Operators::Divide => Token::Divide(new_token_args), Operator::Divide => Token::Divide(new_token_args),
Operators::Multiply => Token::Multiply(new_token_args), Operator::Multiply => Token::Multiply(new_token_args),
Operators::ImplicitMultiply => Token::Multiply(new_token_args), Operator::ImplicitMultiply => Token::Multiply(new_token_args),
Operators::Modulo => Token::Modulo(new_token_args), Operator::Modulo => Token::Modulo(new_token_args),
Operators::ModuloLong => Token::Modulo(new_token_args), Operator::ModuloLong => Token::Modulo(new_token_args),
Operators::Power => Token::Power(new_token_args), Operator::Power => Token::Power(new_token_args),
Operators::Negative => Token::Negative(new_token_args), Operator::Negative => Token::Negative(new_token_args),
Operators::Factorial => Token::Factorial(new_token_args) Operator::Factorial => Token::Factorial(new_token_args)
} }
} }
@ -74,16 +74,16 @@ fn treeify_binary(
if let Token::PreOperator(l, o) = right { if let Token::PreOperator(l, o) = right {
match o { match o {
// Binary operators // Binary operators
Operators::ModuloLong | Operator::ModuloLong |
Operators::Subtract | Operator::Subtract |
Operators::Add | Operator::Add |
Operators::Divide | Operator::Divide |
Operators::Multiply | Operator::Multiply |
Operators::ImplicitMultiply | Operator::ImplicitMultiply |
Operators::Modulo | Operator::Modulo |
Operators::Power | Operator::Power |
// Right unary operators // Right unary operators
Operators::Factorial Operator::Factorial
=> { => {
// Binary and right-unary operators cannot // Binary and right-unary operators cannot
// follow a binary operator. // follow a binary operator.
@ -96,7 +96,7 @@ fn treeify_binary(
}, },
// Left unary operators // Left unary operators
Operators::Negative => { Operator::Negative => {
i += 1; i += 1;
return Ok(i); return Ok(i);
} }
@ -171,16 +171,16 @@ fn treeify_unaryleft(
if let Token::PreOperator(l, o) = right { if let Token::PreOperator(l, o) = right {
match o { match o {
// Binary operators // Binary operators
Operators::ModuloLong | Operator::ModuloLong |
Operators::Subtract | Operator::Subtract |
Operators::Add | Operator::Add |
Operators::Divide | Operator::Divide |
Operators::Multiply | Operator::Multiply |
Operators::ImplicitMultiply | Operator::ImplicitMultiply |
Operators::Modulo | Operator::Modulo |
Operators::Power | Operator::Power |
// Right unary operators // Right unary operators
Operators::Factorial Operator::Factorial
=> { => {
// Binary and right-unary operators cannot // Binary and right-unary operators cannot
// follow a binary operator. // follow a binary operator.
@ -193,7 +193,7 @@ fn treeify_unaryleft(
}, },
// Left unary operators // Left unary operators
Operators::Negative => { Operator::Negative => {
i += 1; i += 1;
return Ok(i); return Ok(i);
} }
@ -272,7 +272,7 @@ fn treeify_unaryright(
if let Token::PreOperator(l, o) = right.unwrap() { if let Token::PreOperator(l, o) = right.unwrap() {
match o { match o {
// Left unary operators // Left unary operators
Operators::Negative => { Operator::Negative => {
let LineLocation { pos: posa, .. } = *get_line_location(&this); let LineLocation { pos: posa, .. } = *get_line_location(&this);
let LineLocation { pos: posb, len: lenb } = *l; let LineLocation { pos: posb, len: lenb } = *l;
return Err(( return Err((
@ -358,20 +358,20 @@ fn inner_treeify(
}; };
match this_op { match this_op {
Operators::ModuloLong | Operator::ModuloLong |
Operators::Subtract | Operator::Subtract |
Operators::Add | Operator::Add |
Operators::Divide | Operator::Divide |
Operators::Multiply | Operator::Multiply |
Operators::ImplicitMultiply | Operator::ImplicitMultiply |
Operators::Modulo | Operator::Modulo |
Operators::Power Operator::Power
=> { i = treeify_binary(i, g_inner)?; }, => { i = treeify_binary(i, g_inner)?; },
Operators::Negative Operator::Negative
=> { i = treeify_unaryleft(i, g_inner)?; }, => { i = treeify_unaryleft(i, g_inner)?; },
Operators::Factorial Operator::Factorial
=> { i = treeify_unaryright(i, g_inner)?; } => { i = treeify_unaryright(i, g_inner)?; }
}; };
@ -386,7 +386,7 @@ fn inner_treeify(
return Err((l, ParserError::Syntax)); return Err((l, ParserError::Syntax));
}, },
Token::PreGroup(_,_) => { Token::PreGroup(_,_) => {
g = treeify(g)?; g = inner_treeify(g)?;
} }
_ => {} _ => {}
}; };