Added square root, fixed many parser bugs

pull/2/head
Mark 2023-03-28 10:46:29 -07:00
parent 6db5137b56
commit 71d9aaa039
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
7 changed files with 277 additions and 239 deletions

View File

@ -43,14 +43,14 @@ pub fn evaluate(
} }
match h { match h {
Token::Operator(_,_,_) Token::Operator(_,_)
=> { => {
coords.push(0); coords.push(0);
continue 'outer; continue 'outer;
}, },
Token::Constant(_,_,_) | 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;

View File

@ -1,7 +1,7 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::parser::PreToken; use crate::parser::PreToken;
use crate::tokens::LineLocation; use crate::parser::LineLocation;
pub(in crate::parser) fn find_subs( pub(in crate::parser) fn find_subs(
@ -64,7 +64,10 @@ pub(in crate::parser) fn find_subs(
"chi" => {Some("χ")}, "chi" => {Some("χ")},
"psi" => {Some("ψ")}, "psi" => {Some("ψ")},
"omega" => {Some("ω")}, "omega" => {Some("ω")},
// Operators
"sqrt" => {Some("")}, "sqrt" => {Some("")},
"rt" => {Some("")},
_ => {None} _ => {None}
}; };

View File

@ -1,16 +1,28 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::tokens::LineLocation;
use crate::tokens::Operator;
use crate::parser::PreToken; use crate::parser::PreToken;
use crate::parser::LineLocation;
use crate::parser::ParserError; use crate::parser::ParserError;
use crate::tokens::Operator;
// Inserts implicit operators // Inserts implicit operators
fn lookback( fn lookback(
g: &mut VecDeque<PreToken> g: &mut VecDeque<PreToken>
) -> Result<(), (LineLocation, ParserError)> { ) -> Result<(), (LineLocation, ParserError)> {
if g.len() >= 2 { if g.len() == 1 {
let a: PreToken = g.pop_back().unwrap();
match &a {
PreToken::PreOperator(l,o)
=> {
if o == "-" {
g.push_back(PreToken::PreOperator(*l, String::from("neg")));
} else { g.push_back(a); }
},
_ => { g.push_back(a); }
};
} else {
let b: PreToken = g.pop_back().unwrap(); let b: PreToken = g.pop_back().unwrap();
let a: PreToken = g.pop_back().unwrap(); let a: PreToken = g.pop_back().unwrap();
@ -42,10 +54,58 @@ fn lookback(
)); ));
} }
// The following are fine (PreToken::PreOperator(_, sa), PreToken::PreOperator(l,sb))
(PreToken::PreOperator(_,_), _) | => {
(_, PreToken::PreOperator(_,_)) if sb == "-" && {
=> { g.push_back(a); g.push_back(b); }, let o = Operator::from_string(sa);
o.is_some() &&
(
o.unwrap().is_binary() ||
!o.unwrap().is_left_associative()
)
} {
g.push_back(a);
g.push_back(PreToken::PreOperator(*l, String::from("neg")));
} else { g.push_back(a); g.push_back(b); }
}
// Insert implicit multiplications for unary operators
(PreToken::PreNumber(_,_), PreToken::PreOperator(l,s))
| (PreToken::PreGroup(_,_), PreToken::PreOperator(l,s))
| (PreToken::PreWord(_,_), PreToken::PreOperator(l,s))
=> {
let o = Operator::from_string(s);
g.push_back(a);
if o.is_some() {
let o = o.unwrap();
if (!o.is_binary()) && (!o.is_left_associative()) {
g.push_back(PreToken::PreOperator(
LineLocation{pos: l.pos-1, len: 0},
String::from("i*")
));
}
}
g.push_back(b);
},
(PreToken::PreOperator(_,s), PreToken::PreNumber(l,_))
| (PreToken::PreOperator(_,s), PreToken::PreGroup(l,_))
| (PreToken::PreOperator(_,s), PreToken::PreWord(l,_))
=> {
let o = Operator::from_string(s);
g.push_back(a);
if o.is_some() {
let o = o.unwrap();
if (!o.is_binary()) && o.is_left_associative() {
g.push_back(PreToken::PreOperator(
LineLocation{pos: l.pos-1, len: 0},
String::from("i*")
));
}
}
g.push_back(b);
},
// This shouldn't ever happen. // This shouldn't ever happen.
(PreToken::PreGroupStart(_), _) (PreToken::PreGroupStart(_), _)
@ -102,16 +162,6 @@ pub(in crate::parser) fn groupify(
lookback(v_now)?; lookback(v_now)?;
}, },
PreToken::PreWord(ref l, ref s) => {
let o = Operator::from_string(&s[..]);
if o.is_some() {
v_now.push_back(PreToken::PreOperator(*l, s.clone()));
} else {
v_now.push_back(t);
}
lookback(v_now)?;
}
_ => { _ => {
v_now.push_back(t); v_now.push_back(t);
lookback(v_now)?; lookback(v_now)?;

View File

@ -12,9 +12,17 @@ use crate::parser::groupify::groupify;
use crate::parser::treeify::treeify; use crate::parser::treeify::treeify;
use crate::parser::find_subs::find_subs; use crate::parser::find_subs::find_subs;
use crate::tokens::LineLocation;
use crate::tokens::Token; use crate::tokens::Token;
/// Specifies the location of a token in an input string.
/// Used to locate ParserErrors.
#[derive(Debug)]
#[derive(Copy, Clone)]
pub struct LineLocation {
pub pos: usize,
pub len: usize
}
#[derive(Debug)] #[derive(Debug)]
enum PreToken { enum PreToken {
PreNumber(LineLocation, String), PreNumber(LineLocation, String),
@ -67,14 +75,14 @@ impl PreToken {
Ok(n) => n, Ok(n) => n,
Err(_) => return Err((l, ParserError::BadNumber)) Err(_) => return Err((l, ParserError::BadNumber))
}; };
return Ok(Token::Number(l, n)); return Ok(Token::Number(n));
}, },
PreToken::PreWord(l, s) => { PreToken::PreWord(l, s) => {
return Ok(match &s[..] { return Ok(match &s[..] {
// Mathematical constants // Mathematical constants
"π"|"pi" => { Token::Constant(l, 3.141592653, String::from("pi")) }, "π"|"pi" => { Token::Constant(3.141592653, String::from("pi")) },
"e" => { Token::Constant(l, 2.71828, String::from("e")) }, "e" => { Token::Constant(2.71828, String::from("e")) },
"phi"|"φ" => { Token::Constant(l, 1.61803, String::from("phi")) }, "phi"|"φ" => { Token::Constant(1.61803, String::from("phi")) },
_ => { return Err((l, ParserError::Undefined(s))); } _ => { return Err((l, ParserError::Undefined(s))); }
}); });
} }

View File

@ -1,28 +1,44 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::parser::PreToken; use crate::parser::PreToken;
use crate::tokens::LineLocation; use crate::parser::LineLocation;
/// Updates the length of a Token's LineLocation. use crate::tokens::Operator;
/// Run whenever a token is finished.
// Called whenever a token is finished.
#[inline(always)] #[inline(always)]
fn update_line_location(mut t: PreToken, stop_i: usize) -> PreToken { fn push_token(g: &mut VecDeque<PreToken>, t: Option<PreToken>, stop_i: usize) {
if t.is_none() { return }
let mut t = t.unwrap();
match t { match t {
PreToken::PreGroupStart(ref mut l) | PreToken::PreGroupStart(ref mut l)
PreToken::PreGroupEnd(ref mut l) | | PreToken::PreGroupEnd(ref mut l)
PreToken::PreOperator(ref mut l, _) | | PreToken::PreOperator(ref mut l, _)
PreToken::PreNumber(ref mut l, _) | | PreToken::PreNumber(ref mut l, _)
PreToken::PreWord(ref mut l, _) | PreToken::PreWord(ref mut l, _)
=> { => {
*l = LineLocation{ *l = LineLocation{
pos: l.pos, pos: l.pos,
len: stop_i - l.pos, len: stop_i - l.pos,
}; };
}, },
_ => panic!()
PreToken::PreGroup(_,_)
| PreToken::Container(_)
=> panic!()
}; };
return t;
if let PreToken::PreWord(l, s) = &t {
let o = Operator::from_string(s);
if o.is_some() {
t = PreToken::PreOperator(*l, s.clone());
}
}
g.push_back(t);
} }
/// Turns a string into Tokens. First stage of parsing. /// Turns a string into Tokens. First stage of parsing.
@ -36,29 +52,13 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque<PreToken> {
// The minus sign can be both a Negative and an Operator. // The minus sign can be both a Negative and an Operator.
// Needs special treatment. // Needs special treatment.
'-' => { '-' => {
if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } push_token(&mut g, t, i);
match g.back().as_ref() {
// If previous token was any of the following,
// this is the "minus" operator
Some(PreToken::PreNumber(_, _)) |
Some(PreToken::PreGroupEnd(_)) |
Some(PreToken::PreWord(_, _)) => {
t = Some(PreToken::PreOperator( t = Some(PreToken::PreOperator(
LineLocation{pos: i, len: 1}, LineLocation{pos: i, len: 1},
String::from("-") String::from("-")
)); ));
}, },
// Otherwise, this is a negative sign.
_ => {
t = Some(PreToken::PreOperator(
LineLocation{pos: i, len: 1},
String::from("neg")
));
}
};
},
// Number // Number
// Commas act just like dots. // Commas act just like dots.
',' | '.' | '0'..='9' => { ',' | '.' | '0'..='9' => {
@ -72,7 +72,7 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque<PreToken> {
// If we're not building a number, finalize // If we're not building a number, finalize
// previous token and start one. // previous token and start one.
_ => { _ => {
if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } push_token(&mut g, t, i);
t = Some(PreToken::PreNumber(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(PreToken::PreNumber(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
@ -85,7 +85,7 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque<PreToken> {
match &mut t { match &mut t {
Some(PreToken::PreOperator(_, val)) => { val.push(c); }, Some(PreToken::PreOperator(_, val)) => { val.push(c); },
_ => { _ => {
if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } push_token(&mut g, t, i);
t = Some(PreToken::PreOperator(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(PreToken::PreOperator(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
@ -93,21 +93,19 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque<PreToken> {
// Group // Group
'(' => { '(' => {
if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } push_token(&mut g, t, i);
t = Some(PreToken::PreGroupStart(LineLocation{pos: i, len: 0})); t = Some(PreToken::PreGroupStart(LineLocation{pos: i, len: 0}));
}, },
')' => { ')' => {
if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } push_token(&mut g, t, i);
t = Some(PreToken::PreGroupEnd(LineLocation{pos: i, len: 0})); t = Some(PreToken::PreGroupEnd(LineLocation{pos: i, len: 0}));
}, },
// Space. Basic seperator. // Space. Basic seperator.
' ' => { ' ' => {
if t.is_some() { push_token(&mut g, t, i);
g.push_back(update_line_location(t.unwrap(), i));
t = None; t = None;
} }
}
// Word // Word
_ => { _ => {
@ -115,7 +113,7 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque<PreToken> {
Some(PreToken::PreWord(_, val)) => { val.push(c); }, Some(PreToken::PreWord(_, val)) => { val.push(c); },
_ => { _ => {
if t.is_some() { g.push_back(update_line_location(t.unwrap(), i)); } push_token(&mut g, t, i);
t = Some(PreToken::PreWord(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(PreToken::PreWord(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
@ -123,7 +121,7 @@ pub(in crate::parser) fn tokenize(input: &String) -> VecDeque<PreToken> {
}; };
} }
if t.is_some() { g.push_back(update_line_location(t.unwrap(), input.chars().count())); } push_token(&mut g, t, input.chars().count());
return g; return g;
} }

View File

@ -3,17 +3,14 @@ use std::collections::VecDeque;
use crate::parser::PreToken; use crate::parser::PreToken;
use crate::parser::ParserError; use crate::parser::ParserError;
use crate::parser::LineLocation;
use crate::tokens::Token; use crate::tokens::Token;
use crate::tokens::Operator; use crate::tokens::Operator;
use crate::tokens::LineLocation;
fn treeify_binary( fn treeify_binary(
i: usize, i: usize,
g_inner: &mut VecDeque<PreToken>, g_inner: &mut VecDeque<PreToken>
left_associative: bool
) -> Result<(), (LineLocation, ParserError)> { ) -> Result<(), (LineLocation, ParserError)> {
let this: &PreToken = &g_inner[i]; let this: &PreToken = &g_inner[i];
@ -27,21 +24,8 @@ fn treeify_binary(
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
} }
let next: &PreToken;
if left_associative { let left = {
next = {
if i < g_inner.len()-1 {
&g_inner[i+1]
} else {
let l = match this {
PreToken::PreOperator(l, _) => l,
_ => panic!()
};
return Err((*l, ParserError::Syntax));
}
};
} else {
next = {
if i > 0 { if i > 0 {
&g_inner[i-1] &g_inner[i-1]
} else { } else {
@ -52,20 +36,32 @@ fn treeify_binary(
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
} }
}; };
let right = {
if i < g_inner.len()-1 {
&g_inner[i+1]
} else {
let l = match this {
PreToken::PreOperator(l, _) => l,
_ => panic!()
};
return Err((*l, ParserError::Syntax));
} }
};
if let PreToken::PreOperator(l, s) = next {
if let PreToken::PreOperator(l, s) = left {
let o = Operator::from_string(s); let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); } if o.is_none() { return Err((*l, ParserError::Syntax)); }
let o = o.unwrap(); let o = o.unwrap();
if { if {
(!o.is_binary()) && (!o.is_binary()) &&
!(o.is_left_associative() && left_associative) o.is_left_associative()
} { } {
// Only right-associative unary operators can follow a binary operator
return Ok(()); return Ok(());
} else { } else {
let tl = *this.get_line_location(); let tl = *this.get_line_location();
@ -74,7 +70,28 @@ fn treeify_binary(
ParserError::Syntax ParserError::Syntax
)); ));
} }
}
if let PreToken::PreOperator(l, s) = right {
let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); }
let o = o.unwrap();
if {
(!o.is_binary()) &&
!o.is_left_associative()
} {
return Ok(());
} else { } else {
let tl = *this.get_line_location();
return Err((
LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len},
ParserError::Syntax
));
}
}
// Precedence of this operator // Precedence of this operator
let this_val = { let this_val = {
let PreToken::PreOperator(l, s) = this else {panic!()}; let PreToken::PreOperator(l, s) = this else {panic!()};
@ -110,24 +127,23 @@ fn treeify_binary(
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)?; } else {right = right_pre.to_token()?;}
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)?; } else {left = left_pre.to_token()?;}
let (l, o) = { let o = {
let PreToken::PreOperator(l, s) = this_pre else {panic!()}; let PreToken::PreOperator(_, s) = this_pre else {panic!()};
let o = Operator::from_string(&s); let o = Operator::from_string(&s);
if o.is_none() { panic!() } if o.is_none() { panic!() }
(l, o.unwrap()) o.unwrap()
}; };
let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(2); let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(2);
new_token_args.push_back(left); new_token_args.push_back(left);
new_token_args.push_back(right); new_token_args.push_back(right);
g_inner.insert(i-1, PreToken::Container(o.into_token(l, new_token_args))); g_inner.insert(i-1, PreToken::Container(o.into_token(new_token_args)));
return Ok(()); return Ok(());
} else { } else {
return Ok(()); return Ok(());
}; };
};
} }
fn treeify_unary( fn treeify_unary(
@ -174,14 +190,7 @@ fn treeify_unary(
} }
if prev.is_some() { if prev.is_some() {
if let PreToken::PreOperator(l, s) = prev.unwrap() { if let PreToken::PreOperator(_,_) = prev.unwrap() {
let o = Operator::from_string(s);
if o.is_none() { return Err((*l, ParserError::Syntax)); }
let o = o.unwrap();
if o.is_left_associative() && left_associative {
return Err((*l, ParserError::Syntax));
}
} else { } else {
return Err(( return Err((
*this.get_line_location(), *this.get_line_location(),
@ -190,8 +199,6 @@ fn treeify_unary(
} }
} }
if let PreToken::PreOperator(l, _) = next { if let PreToken::PreOperator(l, _) = next {
let tl = *this.get_line_location(); let tl = *this.get_line_location();
return Err(( return Err((
@ -236,20 +243,20 @@ fn treeify_unary(
} }
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)?; } else { next = next_pre.to_token()? }
let (l, o) = { let o = {
let PreToken::PreOperator(l, s) = this_pre else {panic!()}; let PreToken::PreOperator(_, s) = this_pre else {panic!()};
let o = Operator::from_string(&s); let o = Operator::from_string(&s);
if o.is_none() { panic!() } if o.is_none() { panic!() }
(l, o.unwrap()) o.unwrap()
}; };
let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(3); let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(3);
new_token_args.push_back(next); new_token_args.push_back(next);
if left_associative { if left_associative {
g_inner.insert(i-1, PreToken::Container(o.into_token(l, new_token_args))); g_inner.insert(i-1, PreToken::Container(o.into_token(new_token_args)));
} else { } else {
g_inner.insert(i, PreToken::Container(o.into_token(l, new_token_args))); g_inner.insert(i, PreToken::Container(o.into_token(new_token_args)));
} }
return Ok(()); return Ok(());
@ -300,7 +307,7 @@ pub(in crate::parser) fn treeify(
if left_associative { if left_associative {
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, left_associative)?; treeify_binary(i, g_inner)?;
} else { } else {
treeify_unary(i, g_inner, left_associative)?; treeify_unary(i, g_inner, left_associative)?;
} }
@ -309,7 +316,7 @@ pub(in crate::parser) 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, left_associative)?; treeify_binary(i, g_inner)?;
} else { } else {
treeify_unary(i, g_inner, left_associative)?; treeify_unary(i, g_inner, left_associative)?;
} }

View File

@ -1,26 +1,15 @@
use std::collections::VecDeque; use std::collections::VecDeque;
/// Specifies the location of a token in an input string.
/// Used to locate ParserErrors.
#[derive(Debug)]
#[derive(Copy, Clone)]
pub struct LineLocation {
pub pos: usize,
pub len: usize
}
/// Tokens represent logical objects in an expession. /// Tokens represent logical objects in an expession.
/// ///
/// 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.
#[derive(Debug)] #[derive(Debug)]
pub enum Token { pub enum Token {
Number(LineLocation, f64), Number(f64),
Constant(LineLocation, f64, String), Constant(f64, String),
Operator( Operator(
LineLocation,
Operator, Operator,
VecDeque<Token> VecDeque<Token>
), ),
@ -30,27 +19,17 @@ impl Token {
#[inline(always)] #[inline(always)]
pub fn get_args(&mut self) -> Option<&mut VecDeque<Token>> { pub fn get_args(&mut self) -> Option<&mut VecDeque<Token>> {
match self { match self {
Token::Operator(_, _, ref mut a) => Some(a), Token::Operator(_, ref mut a) => Some(a),
_ => None _ => None
} }
} }
#[inline(always)]
pub fn get_line_location(&self) -> &LineLocation {
match self {
Token::Number(l, _)
| Token::Operator(l, _, _)
| Token::Constant(l, _, _)
=> l,
}
}
#[inline(always)] #[inline(always)]
pub fn eval(&self) -> Token { pub fn eval(&self) -> Token {
match self { match self {
Token::Number(l,v) => { Token::Number(*l, *v) }, Token::Number(v) => { Token::Number(*v) },
Token::Constant(l,v,_) => { Token::Number(*l, *v) }, Token::Constant(v,_) => { Token::Number(*v) },
Token::Operator(_,o,v) => { o.apply(v) } Token::Operator(o,v) => { o.apply(v) }
} }
} }
@ -58,8 +37,8 @@ impl Token {
#[inline(always)] #[inline(always)]
pub fn as_number(&self) -> Token { pub fn as_number(&self) -> Token {
match self { match self {
Token::Number(l,v) => { Token::Number(*l, *v) }, Token::Number(v) => { Token::Number(*v) },
Token::Constant(l,v,_) => { Token::Number(*l, *v) }, Token::Constant(v,_) => { Token::Number(*v) },
_ => panic!() _ => panic!()
} }
} }
@ -79,6 +58,7 @@ pub enum Operator {
Modulo, // Mod invoked with % Modulo, // Mod invoked with %
Negative, Negative,
Power, Power,
Sqrt,
Factorial, Factorial,
// Not accessible from prompt // Not accessible from prompt
@ -99,6 +79,7 @@ impl Operator {
"mod" => {Some( Operator::ModuloLong )}, "mod" => {Some( Operator::ModuloLong )},
"^"|"**" => {Some( Operator::Power )}, "^"|"**" => {Some( Operator::Power )},
"!" => {Some( Operator::Factorial )}, "!" => {Some( Operator::Factorial )},
"sqrt"|"rt"|"" => {Some( Operator::Sqrt )},
_ => None _ => None
} }
} }
@ -108,6 +89,7 @@ impl Operator {
match self { match self {
Operator::Negative Operator::Negative
| Operator::Factorial | Operator::Factorial
| Operator::Sqrt
=> false, => false,
_ => true _ => true
} }
@ -117,6 +99,7 @@ impl Operator {
pub fn is_left_associative(&self) -> bool { pub fn is_left_associative(&self) -> bool {
match self { match self {
Operator::Negative Operator::Negative
| Operator::Sqrt
=> false, => false,
_ => true _ => true
} }
@ -124,16 +107,16 @@ impl Operator {
#[inline(always)] #[inline(always)]
pub fn into_token(self, l: LineLocation, mut args: VecDeque<Token>) -> Token { pub fn into_token(self, mut args: VecDeque<Token>) -> Token {
match self { match self {
Operator::Subtract => { Operator::Subtract => {
if args.len() != 2 { panic!() } if args.len() != 2 { panic!() }
let a = args.pop_front().unwrap(); let a = args.pop_front().unwrap();
let b = args.pop_front().unwrap(); let b = args.pop_front().unwrap();
let b = Token::Operator(l, Operator::Negative, VecDeque::from(vec!(b))); let b = Token::Operator(Operator::Negative, VecDeque::from(vec!(b)));
Token::Operator( Token::Operator(
l, Operator::Add, Operator::Add,
VecDeque::from(vec!(a,b)) VecDeque::from(vec!(a,b))
) )
}, },
@ -142,19 +125,29 @@ impl Operator {
if args.len() != 2 { panic!() } if args.len() != 2 { panic!() }
let a = args.pop_front().unwrap(); let a = args.pop_front().unwrap();
let b = args.pop_front().unwrap(); let b = args.pop_front().unwrap();
let b = Token::Operator(l, Operator::Flip, VecDeque::from(vec!(b))); let b = Token::Operator(Operator::Flip, VecDeque::from(vec!(b)));
Token::Operator( Token::Operator(
l, Operator::Multiply, Operator::Multiply,
VecDeque::from(vec!(a,b)) VecDeque::from(vec!(a,b))
) )
}, },
Operator::Sqrt => {
if args.len() != 1 { panic!() }
let a = args.pop_front().unwrap();
Token::Operator(
Operator::Power,
VecDeque::from(vec!(a, Token::Number(0.5)))
)
},
Operator::ImplicitMultiply Operator::ImplicitMultiply
=> { Token::Operator(l, Operator::Multiply, args) }, => { Token::Operator(Operator::Multiply, args) },
Operator::ModuloLong Operator::ModuloLong
=> { Token::Operator(l, Operator::Modulo, args) }, => { Token::Operator(Operator::Modulo, args) },
Operator::Factorial Operator::Factorial
| Operator::Negative | Operator::Negative
@ -163,7 +156,7 @@ impl Operator {
| Operator::Multiply | Operator::Multiply
| Operator::Modulo | Operator::Modulo
| Operator::Power | Operator::Power
=> { Token::Operator(l, self, args) }, => { Token::Operator(self, args) },
} }
} }
} }
@ -172,6 +165,7 @@ impl Operator{
pub fn apply(&self, args: &VecDeque<Token>) -> Token { pub fn apply(&self, args: &VecDeque<Token>) -> Token {
match self { match self {
Operator::ImplicitMultiply | Operator::ImplicitMultiply |
Operator::Sqrt |
Operator::ModuloLong | Operator::ModuloLong |
Operator::Divide | Operator::Divide |
Operator::Subtract => { panic!() } Operator::Subtract => { panic!() }
@ -180,8 +174,8 @@ impl Operator{
if args.len() != 1 {panic!()}; if args.len() != 1 {panic!()};
let args = args[0].as_number(); let args = args[0].as_number();
if let Token::Number(l, v) = args { if let Token::Number(v) = args {
Token::Number(l, -v) Token::Number(-v)
} else { panic!(); } } else { panic!(); }
}, },
@ -189,51 +183,35 @@ impl Operator{
if args.len() != 1 {panic!()}; if args.len() != 1 {panic!()};
let args = args[0].as_number(); let args = args[0].as_number();
if let Token::Number(l, v) = args { if let Token::Number(v) = args {
Token::Number(l, 1f64/v) Token::Number(1f64/v)
} else { panic!(); } } else { panic!(); }
}, },
Operator::Add => { Operator::Add => {
let mut sum: f64 = 0f64; let mut sum: f64 = 0f64;
let mut new_pos: usize = 0;
let mut new_len: usize = 0;
for i in args.iter() { for i in args.iter() {
let j = i.as_number(); let j = i.as_number();
if let Token::Number(l, v) = j { if let Token::Number(v) = j {
if new_pos == 0 {new_pos = l.pos};
new_len = new_len + l.len;
sum += v; sum += v;
} else { } else {
panic!(); panic!();
} }
} }
Token::Number(sum)
Token::Number(
LineLocation { pos: new_pos, len: new_len },
sum
)
}, },
Operator::Multiply => { Operator::Multiply => {
let mut prod: f64 = 1f64; let mut prod: f64 = 1f64;
let mut new_pos: usize = 0;
let mut new_len: usize = 0;
for i in args.iter() { for i in args.iter() {
let j = i.as_number(); let j = i.as_number();
if let Token::Number(l, v) = j { if let Token::Number(v) = j {
if new_pos == 0 {new_pos = l.pos};
new_len = new_len + l.len;
prod *= v; prod *= v;
} else { } else {
panic!(); panic!();
} }
} }
Token::Number(prod)
Token::Number(
LineLocation { pos: new_pos, len: new_len },
prod
)
}, },
Operator::Modulo => { Operator::Modulo => {
@ -241,12 +219,9 @@ impl Operator{
let a = args[0].as_number(); let a = args[0].as_number();
let b = args[1].as_number(); let b = args[1].as_number();
if let Token::Number(la, va) = a { if let Token::Number(va) = a {
if let Token::Number(lb, vb) = b { if let Token::Number(vb) = b {
Token::Number( Token::Number(va%vb)
LineLocation { pos: la.pos, len: lb.pos - la.pos + lb.len },
va%vb
)
} else { panic!(); } } else { panic!(); }
} else { panic!(); } } else { panic!(); }
}, },
@ -256,12 +231,9 @@ impl Operator{
let a = args[0].as_number(); let a = args[0].as_number();
let b = args[1].as_number(); let b = args[1].as_number();
if let Token::Number(la, va) = a { if let Token::Number(va) = a {
if let Token::Number(lb, vb) = b { if let Token::Number(vb) = b {
Token::Number( Token::Number(va.powf(vb))
LineLocation { pos: la.pos, len: lb.pos - la.pos + lb.len },
va.powf(vb)
)
} else { panic!(); } } else { panic!(); }
} else { panic!(); } } else { panic!(); }
}, },