pull/2/head
Mark 2023-06-17 19:08:05 -07:00
parent 1495dcd561
commit 73049eeec4
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
7 changed files with 197 additions and 250 deletions

View File

@ -8,17 +8,7 @@ use crate::context::Context;
pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut Context) -> Result<Option<Expression>, EvalError> { pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut Context) -> Result<Option<Expression>, EvalError> {
match op { match op {
Operator::Function(_) => unreachable!("Functions are handled seperately."),
// Handled seperately in evaluate.rs
Operator::Function(_) |
// These are never evaluated,
// but are converted to one of the following instead.
Operator::ImplicitMultiply |
Operator::Sqrt |
Operator::Divide |
Operator::DivideLong |
Operator::Subtract => { panic!() }
Operator::Define => { Operator::Define => {
if args.len() != 2 { panic!() }; if args.len() != 2 { panic!() };
@ -39,18 +29,6 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut C
} else { return Ok(None); } } else { return Ok(None); }
}, },
Operator::Flip => {
if args.len() != 1 { panic!() };
let args = &args[0];
if let Expression::Quantity(v) = args {
if v.is_zero() { return Err(EvalError::ZeroDivision); }
return Ok(Some(Expression::Quantity(
Quantity::new_rational(1f64).unwrap()/v.clone()
)));
} else { return Ok(None); }
},
Operator::Add => { Operator::Add => {
let mut sum: Quantity; let mut sum: Quantity;
if let Expression::Quantity(s) = &args[0] { if let Expression::Quantity(s) = &args[0] {
@ -73,6 +51,38 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut C
return Ok(Some(Expression::Quantity(sum))); return Ok(Some(Expression::Quantity(sum)));
}, },
Operator::Subtract => {
if args.len() != 2 { panic!() };
let a = &args[0];
let b = &args[1];
if let Expression::Quantity(a) = a {
if let Expression::Quantity(b) = b {
return Ok(Some(Expression::Quantity(a.clone() - b.clone())));
}
}
return Ok(None);
},
Operator::Divide |
Operator::DivideLong => {
if args.len() != 2 { panic!() };
let a = &args[0];
let b = &args[1];
if let Expression::Quantity(a) = a {
if let Expression::Quantity(b) = b {
if b.is_zero() { return Err(EvalError::ZeroDivision); }
return Ok(Some(Expression::Quantity(a.clone() / b.clone())));
}
}
return Ok(None);
},
Operator::ImplicitMultiply |
Operator::Multiply => { Operator::Multiply => {
let mut prod = Quantity::new_rational(1f64).unwrap(); let mut prod = Quantity::new_rational(1f64).unwrap();
for i in args.iter() { for i in args.iter() {
@ -106,8 +116,7 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut C
} else { return Ok(None); } } else { return Ok(None); }
}, },
Operator::UnitConvert Operator::UnitConvert => {
=> {
if args.len() != 2 { panic!() }; if args.len() != 2 { panic!() };
let a = &args[0]; let a = &args[0];
let b = &args[1]; let b = &args[1];
@ -123,6 +132,19 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut C
} else { return Ok(None); } } else { return Ok(None); }
}, },
Operator::Sqrt => {
if args.len() != 1 { panic!() }
let a = &args[0];
if let Expression::Quantity(va) = a {
if va.is_negative() { return Err(EvalError::BadMath); }
let p = va.pow(Quantity::new_rational_from_string("0.5").unwrap());
if p.is_nan() {return Err(EvalError::BadMath);}
return Ok(Some(Expression::Quantity(p)));
} else { return Ok(None); }
},
Operator::Power => { Operator::Power => {
if args.len() != 2 {panic!()}; if args.len() != 2 {panic!()};
let a = &args[0]; let a = &args[0];

View File

@ -1,6 +1,5 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::quantity::Quantity;
use super::Expression; use super::Expression;
use super::Function; use super::Function;
@ -29,9 +28,6 @@ pub enum Operator {
Factorial, Factorial,
Function(Function), Function(Function),
// Not accessible from prompt
Flip,
} }
impl PartialEq for Operator { impl PartialEq for Operator {
@ -111,69 +107,6 @@ impl Operator {
} }
} }
#[inline(always)]
pub fn into_expression(self, mut args: VecDeque<Expression>) -> Expression {
match self {
Operator::Subtract => {
if args.len() != 2 { panic!() }
let a = args.pop_front().unwrap();
let b = args.pop_front().unwrap();
let b_new;
if let Expression::Quantity(q) = b {
b_new = Expression::Quantity(-q);
} else {
b_new = Expression::Operator(Operator::Negative, VecDeque::from(vec!(b)));
}
Expression::Operator(
Operator::Add,
VecDeque::from(vec!(a,b_new))
)
},
Operator::DivideLong |
Operator::Divide => {
if args.len() != 2 { panic!() }
let a = args.pop_front().unwrap();
let b = args.pop_front().unwrap();
let b = Expression::Operator(Operator::Flip, VecDeque::from(vec!(b)));
Expression::Operator(
Operator::Multiply,
VecDeque::from(vec!(a,b))
)
},
Operator::Sqrt => {
if args.len() != 1 { panic!() }
let a = args.pop_front().unwrap();
Expression::Operator(
Operator::Power,
VecDeque::from(vec!(a, Expression::Quantity(Quantity::new_rational_from_string("0.5").unwrap())))
)
},
Operator::ImplicitMultiply
=> { Expression::Operator(Operator::Multiply, args) },
Operator::Function(_)
| Operator::Factorial
| Operator::Negative
| Operator::Flip
| Operator::Add
| Operator::Multiply
| Operator::Modulo
| Operator::Power
| Operator::ModuloLong
| Operator::UnitConvert
| Operator::Define
=> { Expression::Operator(self, args) },
}
}
#[inline(always)] #[inline(always)]
fn add_parens_to_arg(&self, arg: &Expression) -> String { fn add_parens_to_arg(&self, arg: &Expression) -> String {
let mut astr: String = arg.to_string(); let mut astr: String = arg.to_string();
@ -199,11 +132,6 @@ impl Operator {
pub fn print(&self, args: &VecDeque<Expression>) -> String { pub fn print(&self, args: &VecDeque<Expression>) -> String {
match self { match self {
Operator::ImplicitMultiply |
Operator::Sqrt |
Operator::Divide |
Operator::Subtract => { panic!() }
Operator::Define => { Operator::Define => {
return format!( return format!(
"{} = {}", "{} = {}",
@ -212,14 +140,17 @@ impl Operator {
); );
}, },
Operator::Flip => {
return format!("{}⁻¹", Operator::Divide.add_parens_to_arg(&args[0]));
},
Operator::Negative => { Operator::Negative => {
return format!("-{}", self.add_parens_to_arg(&args[0])); return format!("-{}", self.add_parens_to_arg(&args[0]));
}, },
Operator::Sqrt => {
return format!(
"√{}",
self.add_parens_to_arg(&args[0]),
);
},
Operator::ModuloLong => { Operator::ModuloLong => {
return format!( return format!(
"{} mod {}", "{} mod {}",
@ -252,6 +183,14 @@ impl Operator {
); );
}, },
Operator::Subtract => {
return format!(
"{} - {}",
self.add_parens_to_arg(&args[0]),
self.add_parens_to_arg(&args[1])
);
},
Operator::Power => { Operator::Power => {
return format!( return format!(
"{}^{}", "{}^{}",
@ -265,50 +204,17 @@ impl Operator {
}, },
Operator::Add => { Operator::Add => {
let a = &args[0]; return format!(
"{} + {}",
let b; let sub; self.add_parens_to_arg(&args[0]),
if let Expression::Operator(o, ar) = &args[1] { self.add_parens_to_arg(&args[1])
if let Operator::Negative = o { );
sub = true;
b = &ar[0];
} else { sub = false; b = &args[1]; }
} else { sub = false; b = &args[1]; }
if sub {
return format!(
"{} - {}",
self.add_parens_to_arg(a),
self.add_parens_to_arg(b)
);
} else {
return format!(
"{} + {}",
self.add_parens_to_arg(a),
self.add_parens_to_arg(b)
);
}
}, },
Operator::ImplicitMultiply |
Operator::Multiply => { Operator::Multiply => {
let a = &args[0]; let a = &args[0];
let b = &args[1];
let b; let div;
if let Expression::Operator(o, ar) = &args[1] {
if let Operator::Flip = o {
div = true;
b = &ar[0];
} else { div = false; b = &args[1]; }
} else { div = false; b = &args[1]; }
// Division symbol case
if div {
return format!("{} ÷ {}",
self.add_parens_to_arg_strict(a),
self.add_parens_to_arg_strict(b)
);
}
// Omit times sign when we have a number // Omit times sign when we have a number
// multiplied by a unit (like 10 m) // multiplied by a unit (like 10 m)
@ -342,6 +248,24 @@ impl Operator {
} }
}, },
Operator::Divide => {
let a = &args[0];
let b = &args[1];
if let Expression::Quantity(q) = a {
if q.is_one() {
return format!("{}⁻¹",
self.add_parens_to_arg_strict(b)
);
}
}
return format!("{} ÷ {}",
self.add_parens_to_arg_strict(a),
self.add_parens_to_arg_strict(b)
);
},
Operator::Function(s) => { Operator::Function(s) => {
return format!("{}({})", s.to_string(), args[0].to_string()); return format!("{}({})", s.to_string(), args[0].to_string());
} }

View File

@ -26,7 +26,7 @@ pub fn find_subs(
let mut t = g.pop_back().unwrap(); let mut t = g.pop_back().unwrap();
let target: Option<&str> = match &mut t { let target: Option<&str> = match &mut t {
Token::PreOperator(_, s) => { Token::Operator(_, s) => {
let target = match &s[..] { let target = match &s[..] {
"*" => {Some("×")}, "*" => {Some("×")},
"/" => {Some("÷")}, "/" => {Some("÷")},
@ -41,7 +41,7 @@ pub fn find_subs(
target target
}, },
Token::PreWord(_, s) => { Token::Word(_, s) => {
let target = match &s[..] { let target = match &s[..] {
// Greek letters // Greek letters
"alpha" => {Some("α")}, "alpha" => {Some("α")},

View File

@ -19,10 +19,10 @@ fn lookback_signs(
if i == 0 { if i == 0 {
let a: Token = g.remove(i).unwrap(); let a: Token = g.remove(i).unwrap();
match &a { match &a {
Token::PreOperator(l,o) Token::Operator(l,o)
=> { => {
if o == "-" { if o == "-" {
g.insert(i, Token::PreOperator(*l, String::from("neg"))); g.insert(i, Token::Operator(*l, String::from("neg")));
} else if o == "+" { } else if o == "+" {
continue; // We should not increment i if we remove a token continue; // We should not increment i if we remove a token
} else {g.insert(i, a);} } else {g.insert(i, a);}
@ -35,7 +35,7 @@ fn lookback_signs(
let b: Token = g.remove(i-1).unwrap(); let b: Token = g.remove(i-1).unwrap();
match (&a, &b) { match (&a, &b) {
(Token::PreOperator(_, sa), Token::PreOperator(l,sb)) (Token::Operator(_, sa), Token::Operator(l,sb))
=> { => {
if { if {
let o = Operator::from_string(sa); let o = Operator::from_string(sa);
@ -47,7 +47,7 @@ fn lookback_signs(
) )
} { } {
if sb == "-" { if sb == "-" {
g.insert(i-1, Token::PreOperator(*l, String::from("neg"))); g.insert(i-1, Token::Operator(*l, String::from("neg")));
g.insert(i-1, a); g.insert(i-1, a);
} else if sb == "+" { } else if sb == "+" {
g.insert(i-1, a); g.insert(i-1, a);
@ -71,7 +71,7 @@ fn lookback_signs(
let b: Token = g.remove(i-1).unwrap(); let b: Token = g.remove(i-1).unwrap();
match (&a, &b) { match (&a, &b) {
(Token::PreOperator(_,sa), Token::PreOperator(_,sb)) (Token::Operator(_,sa), Token::Operator(_,sb))
=> { => {
if !((sa == "neg") && (sb == "neg")) { if !((sa == "neg") && (sb == "neg")) {
g.insert(i-1, b); g.insert(i-1, b);
@ -108,19 +108,19 @@ fn lookback(
match (&a, &b) { match (&a, &b) {
// Insert ImplicitMultiply // Insert ImplicitMultiply
(Token::PreGroup(_,_), Token::PreGroup(l ,_)) (Token::Group(_,_), Token::Group(l ,_))
| (Token::PreGroup(_,_), Token::PreQuantity(l,_)) | (Token::Group(_,_), Token::Quantity(l,_))
| (Token::PreQuantity(_,_), Token::PreGroup(l,_)) | (Token::Quantity(_,_), Token::Group(l,_))
| (Token::PreGroup(_,_), Token::PreWord(l,_)) | (Token::Group(_,_), Token::Word(l,_))
| (Token::PreWord(_,_), Token::PreGroup(l,_)) | (Token::Word(_,_), Token::Group(l,_))
| (Token::PreQuantity(_,_), Token::PreWord(l,_)) | (Token::Quantity(_,_), Token::Word(l,_))
| (Token::PreWord(_,_), Token::PreQuantity(l,_)) | (Token::Word(_,_), Token::Quantity(l,_))
| (Token::PreWord(_,_), Token::PreWord(l,_)) | (Token::Word(_,_), Token::Word(l,_))
=> { => {
let loc = LineLocation{pos: l.pos-1, len: 0}; let loc = LineLocation{pos: l.pos-1, len: 0};
g.insert(i-1, b); g.insert(i-1, b);
g.insert(i-1, Token::PreOperator( g.insert(i-1, Token::Operator(
loc, loc,
String::from("i*") String::from("i*")
)); ));
@ -128,9 +128,9 @@ fn lookback(
}, },
// Insert implicit multiplications for right-unary operators // Insert implicit multiplications for right-unary operators
(Token::PreQuantity(_,_), Token::PreOperator(l,s)) (Token::Quantity(_,_), Token::Operator(l,s))
| (Token::PreGroup(_,_), Token::PreOperator(l,s)) | (Token::Group(_,_), Token::Operator(l,s))
| (Token::PreWord(_,_), Token::PreOperator(l,s)) | (Token::Word(_,_), Token::Operator(l,s))
=> { => {
let o = Operator::from_string(s); let o = Operator::from_string(s);
let loc = LineLocation{pos: l.pos-1, len: 0}; let loc = LineLocation{pos: l.pos-1, len: 0};
@ -139,7 +139,7 @@ fn lookback(
if o.is_some() { if o.is_some() {
let o = o.unwrap(); let o = o.unwrap();
if (!o.is_binary()) && (!o.is_left_associative()) { if (!o.is_binary()) && (!o.is_left_associative()) {
g.insert(i-1, Token::PreOperator( g.insert(i-1, Token::Operator(
loc, loc,
String::from("i*") String::from("i*")
)); ));
@ -149,9 +149,9 @@ fn lookback(
}, },
// Insert implicit multiplications for left-unary operators. // Insert implicit multiplications for left-unary operators.
(Token::PreOperator(_,s), Token::PreQuantity(l,_)) (Token::Operator(_,s), Token::Quantity(l,_))
| (Token::PreOperator(_,s), Token::PreGroup(l,_)) | (Token::Operator(_,s), Token::Group(l,_))
| (Token::PreOperator(_,s), Token::PreWord(l,_)) | (Token::Operator(_,s), Token::Word(l,_))
=> { => {
let o = Operator::from_string(s); let o = Operator::from_string(s);
let loc = LineLocation{pos: l.pos-1, len: 0}; let loc = LineLocation{pos: l.pos-1, len: 0};
@ -160,7 +160,7 @@ fn lookback(
if o.is_some() { if o.is_some() {
let o = o.unwrap(); let o = o.unwrap();
if (!o.is_binary()) && o.is_left_associative() { if (!o.is_binary()) && o.is_left_associative() {
g.insert(i-1, Token::PreOperator( g.insert(i-1, Token::Operator(
loc, loc,
String::from("i*") String::from("i*")
)); ));
@ -170,7 +170,7 @@ fn lookback(
}, },
// The following are syntax errors // The following are syntax errors
(Token::PreQuantity(la,_), Token::PreQuantity(lb,_)) (Token::Quantity(la,_), Token::Quantity(lb,_))
=> { => {
return Err(( return Err((
LineLocation{pos: la.pos, len: lb.pos - la.pos + lb.len}, LineLocation{pos: la.pos, len: lb.pos - la.pos + lb.len},
@ -206,12 +206,12 @@ pub fn groupify(
let (l_now, v_now) = levels.last_mut().unwrap(); let (l_now, v_now) = levels.last_mut().unwrap();
match t { match t {
Token::PreGroupStart(l) => { Token::GroupStart(l) => {
levels.push((l, VecDeque::with_capacity(8))); levels.push((l, VecDeque::with_capacity(8)));
i_level += 1; i_level += 1;
}, },
Token::PreGroupEnd(l) => { Token::GroupEnd(l) => {
let l = LineLocation { let l = LineLocation {
pos: l_now.pos, pos: l_now.pos,
len: l.len + l.pos - l_now.pos len: l.len + l.pos - l_now.pos
@ -226,7 +226,7 @@ pub fn groupify(
let (_, v_now) = levels.last_mut().unwrap(); let (_, v_now) = levels.last_mut().unwrap();
lookback(&mut v)?; lookback(&mut v)?;
v_now.push_back(Token::PreGroup(l, v)); v_now.push_back(Token::Group(l, v));
}, },
_ => { _ => {
@ -252,12 +252,12 @@ pub fn groupify(
if v.len() == 0 { return Err((l, ParserError::EmptyGroup)) } if v.len() == 0 { return Err((l, ParserError::EmptyGroup)) }
lookback(&mut v)?; lookback(&mut v)?;
v_now.push_back(Token::PreGroup(l, v)); v_now.push_back(Token::Group(l, v));
} }
let (_, mut v) = levels.pop().unwrap(); let (_, mut v) = levels.pop().unwrap();
lookback(&mut v)?; lookback(&mut v)?;
return Ok(Token::PreGroup(LineLocation{pos:0, len:0}, v)); return Ok(Token::Group(LineLocation{pos:0, len:0}, v));
} }

View File

@ -14,11 +14,11 @@ fn push_token(g: &mut VecDeque<Token>, t: Option<Token>, stop_i: usize) {
let mut t = t.unwrap(); let mut t = t.unwrap();
match t { match t {
Token::PreGroupStart(ref mut l) Token::GroupStart(ref mut l)
| Token::PreGroupEnd(ref mut l) | Token::GroupEnd(ref mut l)
| Token::PreOperator(ref mut l, _) | Token::Operator(ref mut l, _)
| Token::PreQuantity(ref mut l, _) | Token::Quantity(ref mut l, _)
| Token::PreWord(ref mut l, _) | Token::Word(ref mut l, _)
=> { => {
*l = LineLocation{ *l = LineLocation{
pos: l.pos, pos: l.pos,
@ -26,7 +26,7 @@ fn push_token(g: &mut VecDeque<Token>, t: Option<Token>, stop_i: usize) {
}; };
}, },
Token::PreGroup(_,_) Token::Group(_,_)
| Token::Container(_) | Token::Container(_)
=> panic!() => panic!()
}; };
@ -34,14 +34,14 @@ fn push_token(g: &mut VecDeque<Token>, t: Option<Token>, stop_i: usize) {
// `2e` isn't exponential notation, it's 2*e. // `2e` isn't exponential notation, it's 2*e.
// If a number ends in `e`, disconnect the `e` and make it a word. // If a number ends in `e`, disconnect the `e` and make it a word.
if let Token::PreQuantity(l, s) = &t { if let Token::Quantity(l, s) = &t {
let last = &s[s.len()-1..]; let last = &s[s.len()-1..];
if last == "e" { if last == "e" {
g.push_back(Token::PreQuantity( g.push_back(Token::Quantity(
LineLocation { pos: l.pos, len: l.len-1 }, LineLocation { pos: l.pos, len: l.len-1 },
String::from(&s[0..s.len()-1]) String::from(&s[0..s.len()-1])
)); ));
g.push_back(Token::PreWord( g.push_back(Token::Word(
LineLocation { pos: l.pos + l.len - 1, len: 1 }, LineLocation { pos: l.pos + l.len - 1, len: 1 },
String::from("e") String::from("e")
)); ));
@ -51,9 +51,9 @@ fn push_token(g: &mut VecDeque<Token>, t: Option<Token>, stop_i: usize) {
} }
// Some operators are written as words. // Some operators are written as words.
if let Token::PreWord(l, s) = &t { if let Token::Word(l, s) = &t {
if Operator::from_string(s).is_some() { if Operator::from_string(s).is_some() {
t = Token::PreOperator(*l, s.clone()); t = Token::Operator(*l, s.clone());
} }
} }
@ -74,7 +74,7 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
match &mut t { match &mut t {
// If we're already building a number, // If we're already building a number,
// append. // append.
Some(Token::PreQuantity(_, val)) => { Some(Token::Quantity(_, val)) => {
val.push(if c == ',' {'.'} else {c}); val.push(if c == ',' {'.'} else {c});
}, },
@ -82,7 +82,7 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
// previous token and start one. // previous token and start one.
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(Token::PreQuantity(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(Token::Quantity(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
}, },
@ -91,12 +91,12 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
// Can be both a word or a number. // Can be both a word or a number.
'e' => { 'e' => {
match &mut t { match &mut t {
Some(Token::PreWord(_, val)) => { val.push(c); }, Some(Token::Word(_, val)) => { val.push(c); },
Some(Token::PreQuantity(_, val)) => { val.push(c); }, Some(Token::Quantity(_, val)) => { val.push(c); },
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(Token::PreWord(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(Token::Word(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
} }
@ -106,7 +106,7 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
// or it can specify a negative exponent. // or it can specify a negative exponent.
'-' | '+' => { '-' | '+' => {
match &mut t { match &mut t {
Some(Token::PreQuantity(_, val)) => { Some(Token::Quantity(_, val)) => {
if &val[val.len()-1..] == "e" { if &val[val.len()-1..] == "e" {
// If the current number ends in an `e`, // If the current number ends in an `e`,
// this negative specifies a negative exponent // this negative specifies a negative exponent
@ -116,7 +116,7 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
// Otherwise, end the number. // Otherwise, end the number.
// We probably have a subtraction. // We probably have a subtraction.
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(Token::PreOperator( t = Some(Token::Operator(
LineLocation{pos: i, len: 1}, LineLocation{pos: i, len: 1},
String::from(c) String::from(c)
)); ));
@ -126,7 +126,7 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
// This may be a negative or a subtraction // This may be a negative or a subtraction
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(Token::PreOperator( t = Some(Token::Operator(
LineLocation{pos: i, len: 1}, LineLocation{pos: i, len: 1},
String::from(c) String::from(c)
)); ));
@ -139,10 +139,10 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
'^'|'!'|'%'|'=' '^'|'!'|'%'|'='
=> { => {
match &mut t { match &mut t {
Some(Token::PreOperator(_, val)) => { val.push(c); }, Some(Token::Operator(_, val)) => { val.push(c); },
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(Token::PreOperator(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(Token::Operator(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
}, },
@ -150,11 +150,11 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
// Group // Group
'(' => { '(' => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(Token::PreGroupStart(LineLocation{pos: i, len: 0})); t = Some(Token::GroupStart(LineLocation{pos: i, len: 0}));
}, },
')' => { ')' => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(Token::PreGroupEnd(LineLocation{pos: i, len: 0})); t = Some(Token::GroupEnd(LineLocation{pos: i, len: 0}));
}, },
// Space. Basic seperator. // Space. Basic seperator.
@ -166,11 +166,11 @@ pub fn tokenize(input: &String) -> VecDeque<Token> {
// Word // Word
_ => { _ => {
match &mut t { match &mut t {
Some(Token::PreWord(_, val)) => { val.push(c); }, Some(Token::Word(_, val)) => { val.push(c); },
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(Token::PreWord(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(Token::Word(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
} }

View File

@ -20,7 +20,7 @@ fn treeify_binary(
if i == 0 { if i == 0 {
// This binary operator is at the end of an expression. // This binary operator is at the end of an expression.
let l = match this { let l = match this {
Token::PreOperator(l, _) => l, Token::Operator(l, _) => l,
_ => panic!() _ => panic!()
}; };
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
@ -32,7 +32,7 @@ fn treeify_binary(
&g_inner[i-1] &g_inner[i-1]
} else { } else {
let l = match this { let l = match this {
Token::PreOperator(l, _) => l, Token::Operator(l, _) => l,
_ => panic!() _ => panic!()
}; };
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
@ -44,7 +44,7 @@ fn treeify_binary(
&g_inner[i+1] &g_inner[i+1]
} else { } else {
let l = match this { let l = match this {
Token::PreOperator(l, _) => l, Token::Operator(l, _) => l,
_ => panic!() _ => panic!()
}; };
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
@ -55,7 +55,7 @@ fn treeify_binary(
if let Token::PreOperator(l, s) = left { if let Token::Operator(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();
@ -74,7 +74,7 @@ fn treeify_binary(
} }
} }
if let Token::PreOperator(l, s) = right { if let Token::Operator(l, s) = right {
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();
@ -96,7 +96,7 @@ fn treeify_binary(
// This operator // This operator
let this_op = { let this_op = {
let Token::PreOperator(l, s) = this else {panic!()}; let Token::Operator(l, s) = this else {panic!()};
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)); }
o.unwrap() o.unwrap()
@ -104,14 +104,14 @@ fn treeify_binary(
// The operators contesting our arguments // The operators contesting our arguments
let left_op = if i > 1 { let left_op = if i > 1 {
let Token::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; let Token::Operator(l, s) = &g_inner[i-2] else {panic!()};
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)); }
Some(o.unwrap()) Some(o.unwrap())
} else { None }; } else { None };
let right_op = if i < g_inner.len()-2 { let right_op = if i < g_inner.len()-2 {
let Token::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; let Token::Operator(l, s) = &g_inner[i+2] else {panic!()};
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)); }
Some(o.unwrap()) Some(o.unwrap())
@ -127,11 +127,11 @@ 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: Expression; let right: Expression; let left: Expression; let right: Expression;
if let Token::PreGroup(_, _) = right_pre { right = treeify(right_pre, context)?; } else {right = right_pre.to_expression(context)?;} if let Token::Group(_, _) = right_pre { right = treeify(right_pre, context)?; } else {right = right_pre.to_expression(context)?;}
if let Token::PreGroup(_, _) = left_pre { left = treeify(left_pre, context)?; } else {left = left_pre.to_expression(context)?;} if let Token::Group(_, _) = left_pre { left = treeify(left_pre, context)?; } else {left = left_pre.to_expression(context)?;}
let o = { let o = {
let Token::PreOperator(_, s) = this_pre else {panic!()}; let Token::Operator(_, 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!() }
o.unwrap() o.unwrap()
@ -141,7 +141,7 @@ fn treeify_binary(
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, Token::Container(o.into_expression(new_token_args))); g_inner.insert(i-1, Token::Container(Expression::Operator(o, new_token_args)));
return Ok(true); return Ok(true);
} else { } else {
@ -164,7 +164,7 @@ fn treeify_unary(
&g_inner[i-1] &g_inner[i-1]
} else { } else {
let l = match this { let l = match this {
Token::PreOperator(l, _) => l, Token::Operator(l, _) => l,
_ => panic!() _ => panic!()
}; };
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
@ -176,7 +176,7 @@ fn treeify_unary(
&g_inner[i+1] &g_inner[i+1]
} else { } else {
let l = match this { let l = match this {
Token::PreOperator(l, _) => l, Token::Operator(l, _) => l,
_ => panic!() _ => panic!()
}; };
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
@ -194,7 +194,7 @@ fn treeify_unary(
} }
if prev.is_some() { if prev.is_some() {
if let Token::PreOperator(_,_) = prev.unwrap() { if let Token::Operator(_,_) = prev.unwrap() {
} else { } else {
return Err(( return Err((
*this.get_line_location(), *this.get_line_location(),
@ -203,7 +203,7 @@ fn treeify_unary(
} }
} }
if let Token::PreOperator(l, _) = next { if let Token::Operator(l, _) = next {
let tl = *this.get_line_location(); let tl = *this.get_line_location();
return Err(( return Err((
LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len}, LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len},
@ -214,7 +214,7 @@ fn treeify_unary(
// This operator // This operator
let this_op = { let this_op = {
let Token::PreOperator(l, s) = this else {panic!()}; let Token::Operator(l, s) = this else {panic!()};
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)); }
o.unwrap() o.unwrap()
@ -223,14 +223,14 @@ fn treeify_unary(
// The operator contesting our argument // The operator contesting our argument
let next_op = if left_associative { let next_op = if left_associative {
if i > 1 { if i > 1 {
let Token::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; let Token::Operator(l, s) = &g_inner[i-2] else {panic!()};
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)); }
Some(o.unwrap()) Some(o.unwrap())
} else { None } } else { None }
} else { } else {
if i < g_inner.len()-2 { if i < g_inner.len()-2 {
let Token::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; let Token::Operator(l, s) = &g_inner[i+2] else {panic!()};
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)); }
Some(o.unwrap()) Some(o.unwrap())
@ -245,10 +245,10 @@ fn treeify_unary(
} else { } else {
next_pre = g_inner.remove(i).unwrap(); next_pre = g_inner.remove(i).unwrap();
} }
if let Token::PreGroup(_, _) = next_pre { next = treeify(next_pre, context)?; } else { next = next_pre.to_expression(context)? } if let Token::Group(_, _) = next_pre { next = treeify(next_pre, context)?; } else { next = next_pre.to_expression(context)? }
let o = { let o = {
let Token::PreOperator(_, s) = this_pre else {panic!()}; let Token::Operator(_, 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!() }
o.unwrap() o.unwrap()
@ -258,9 +258,9 @@ fn treeify_unary(
new_token_args.push_back(next); new_token_args.push_back(next);
if left_associative { if left_associative {
g_inner.insert(i-1, Token::Container(o.into_expression(new_token_args))); g_inner.insert(i-1, Token::Container(Expression::Operator(o, new_token_args)));
} else { } else {
g_inner.insert(i, Token::Container(o.into_expression(new_token_args))); g_inner.insert(i, Token::Container(Expression::Operator(o, new_token_args)));
} }
return Ok(true); return Ok(true);
@ -279,7 +279,7 @@ pub fn treeify(
) -> Result<Expression, (LineLocation, ParserError)> { ) -> Result<Expression, (LineLocation, ParserError)> {
let g_inner: &mut VecDeque<Token> = match g { let g_inner: &mut VecDeque<Token> = match g {
Token::PreGroup(_, ref mut x) => x, Token::Group(_, ref mut x) => x,
_ => panic!() _ => panic!()
}; };
@ -297,10 +297,10 @@ pub fn treeify(
let i = j as usize; let i = j as usize;
// Convert preoperators // Convert operators
// If not an operator, move on. // If not an operator, move on.
let this_op = match &g_inner[i] { let this_op = match &g_inner[i] {
Token::PreOperator(l, s) => { Token::Operator(l, s) => {
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)); }
o.unwrap() o.unwrap()
@ -342,10 +342,10 @@ pub fn treeify(
let g = g_inner.pop_front().unwrap(); let g = g_inner.pop_front().unwrap();
return match g { return match g {
// Catch edge cases // Catch edge cases
Token::PreOperator(l, _) => { Token::Operator(l, _) => {
Err((l, ParserError::Syntax)) Err((l, ParserError::Syntax))
}, },
Token::PreGroup(_,_) => { Token::Group(_,_) => {
treeify(g, context) treeify(g, context)
}, },

View File

@ -13,14 +13,15 @@ use super::{
#[derive(Debug)] #[derive(Debug)]
pub enum Token { pub enum Token {
PreQuantity(LineLocation, String), Quantity(LineLocation, String),
PreWord(LineLocation, String), Word(LineLocation, String),
PreOperator(LineLocation, String), Operator(LineLocation, String),
PreGroupStart(LineLocation), GroupStart(LineLocation),
PreGroupEnd(LineLocation), GroupEnd(LineLocation),
PreGroup(LineLocation, VecDeque<Token>), Group(LineLocation, VecDeque<Token>),
// Never parsed from input, used to build a tree.
Container(Expression) Container(Expression)
} }
@ -28,37 +29,37 @@ impl Token {
#[inline(always)] #[inline(always)]
pub fn get_line_location(&self) -> &LineLocation { pub fn get_line_location(&self) -> &LineLocation {
match self { match self {
Token::PreQuantity(l, _) Token::Quantity(l, _)
| Token::PreWord(l, _) | Token::Word(l, _)
| Token::PreOperator(l, _) | Token::Operator(l, _)
| Token::PreGroupStart(l) | Token::GroupStart(l)
| Token::PreGroupEnd(l) | Token::GroupEnd(l)
| Token::PreGroup(l, _) | Token::Group(l, _)
=> l, => l,
_ => panic!() Token::Container(_) => panic!("Containers do not have a linelocation.")
} }
} }
#[inline(always)] #[inline(always)]
pub fn get_mut_line_location(&mut self) -> &mut LineLocation { pub fn get_mut_line_location(&mut self) -> &mut LineLocation {
match self { match self {
Token::PreQuantity(l, _) Token::Quantity(l, _)
| Token::PreWord(l, _) | Token::Word(l, _)
| Token::PreOperator(l, _) | Token::Operator(l, _)
| Token::PreGroupStart(l) | Token::GroupStart(l)
| Token::PreGroupEnd(l) | Token::GroupEnd(l)
| Token::PreGroup(l, _) | Token::Group(l, _)
=> l, => l,
_ => panic!() Token::Container(_) => panic!("Containers do not have a linelocation.")
} }
} }
#[inline(always)] #[inline(always)]
pub fn to_expression(self, context: &Context) -> Result<Expression, (LineLocation, ParserError)>{ pub fn to_expression(self, context: &Context) -> Result<Expression, (LineLocation, ParserError)>{
match self { match self {
Token::PreQuantity(l, mut s) => { Token::Quantity(l, mut s) => {
// The length check here ensures that // The length check here ensures that
// `.` is not parsed as `0.` // `.` is not parsed as `0.`
@ -76,7 +77,7 @@ impl Token {
return Ok(Expression::Quantity(r.unwrap())); return Ok(Expression::Quantity(r.unwrap()));
}, },
Token::PreWord(_l, s) => { Token::Word(_l, s) => {
let c = Constant::from_string(&s); let c = Constant::from_string(&s);
if c.is_some() { return Ok(Expression::Constant(c.unwrap())); } if c.is_some() { return Ok(Expression::Constant(c.unwrap())); }
@ -91,10 +92,10 @@ impl Token {
Token::Container(v) => { return Ok(v); } Token::Container(v) => { return Ok(v); }
Token::PreOperator(_,_) Token::Operator(_,_)
| Token::PreGroupStart(_) | Token::GroupStart(_)
| Token::PreGroupEnd(_) | Token::GroupEnd(_)
| Token::PreGroup(_, _) | Token::Group(_, _)
=> panic!() => panic!()
}; };
} }