Renamed token and pretoken

pull/2/head
Mark 2023-06-16 12:58:06 -07:00
parent 081dc1b7ab
commit 1495dcd561
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
17 changed files with 280 additions and 281 deletions

View File

@ -93,7 +93,7 @@ pub fn write(target: &Path) {
writeln!(file, writeln!(file,
concat!( concat!(
"\tpub fn value(&self) -> Token {{\n", "\tpub fn value(&self) -> Expression {{\n",
"\t\tmatch self {{" "\t\tmatch self {{"
) )
).unwrap(); ).unwrap();

View File

@ -1,10 +1,10 @@
use crate::parser::Token; use crate::parser::Expression;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]
pub struct Context { pub struct Context {
history: Vec<Token>, history: Vec<Expression>,
variables: HashMap<String, Token> variables: HashMap<String, Expression>
} }
impl Context { impl Context {
@ -12,13 +12,13 @@ impl Context {
Context{ history: Vec::new(), variables: HashMap::new() } Context{ history: Vec::new(), variables: HashMap::new() }
} }
pub fn push_hist(&mut self, t: Token) { self.history.push(t); } pub fn push_hist(&mut self, t: Expression) { self.history.push(t); }
pub fn push_var(&mut self, s: String, t: Token) { self.variables.insert(s, t); } pub fn push_var(&mut self, s: String, t: Expression) { 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<Expression> {
let v: Option<&Token>; let v: Option<&Expression>;
if s == "ans" { if s == "ans" {
v = self.history.last(); v = self.history.last();

View File

@ -25,7 +25,7 @@ fn do_expression(
stdout: &mut RawTerminal<std::io::Stdout>, stdout: &mut RawTerminal<std::io::Stdout>,
s: &String, s: &String,
context: &mut Context context: &mut Context
) -> Result<parser::Token, ()> { ) -> Result<parser::Expression, ()> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
RawTerminal::suspend_raw_mode(&stdout).unwrap(); RawTerminal::suspend_raw_mode(&stdout).unwrap();
let g = parser::parse(&s, context); let g = parser::parse(&s, context);

View File

@ -1,4 +1,4 @@
use crate::parser::Token; use crate::parser::Expression;
use crate::parser::Operator; use crate::parser::Operator;
use crate::context::Context; use crate::context::Context;
@ -7,9 +7,9 @@ use super::operator::eval_operator;
use super::function::eval_function; use super::function::eval_function;
use super::EvalError; use super::EvalError;
pub fn evaluate(t: &Token, context: &mut Context) -> Result<Token, EvalError> { pub fn evaluate(t: &Expression, context: &mut Context) -> Result<Expression, EvalError> {
// Keeps track of our position in the token tree. // Keeps track of our position in the expression tree.
// For example, the coordinates [0, 2, 1] are interpreted as follows: // For example, the coordinates [0, 2, 1] are interpreted as follows:
// Start at the root node, // Start at the root node,
// then move to that node's 0th child, // then move to that node's 0th child,
@ -40,12 +40,12 @@ pub fn evaluate(t: &Token, context: &mut Context) -> Result<Token, EvalError> {
let new = match g { let new = match g {
Token::Quantity(_) => None, Expression::Quantity(_) => None,
Token::Constant(c) => { Some(evaluate(&c.value(), context).unwrap()) }, Expression::Constant(c) => { Some(evaluate(&c.value(), context).unwrap()) },
Token::Variable(s) => { context.get_variable(&s) }, Expression::Variable(s) => { context.get_variable(&s) },
Token::Operator(Operator::Function(f), v) => { Some(eval_function(&f, &v)?) }, Expression::Operator(Operator::Function(f), v) => { Some(eval_function(&f, &v)?) },
Token::Operator(o, v) => { eval_operator(&o, &v, context)? }, Expression::Operator(o, v) => { eval_operator(&o, &v, context)? },
}; };
if new.is_some() { *g = new.unwrap()} if new.is_some() { *g = new.unwrap()}
@ -63,7 +63,7 @@ pub fn evaluate(t: &Token, context: &mut Context) -> Result<Token, EvalError> {
let n = root.get_at_coords(&coords[..]); let n = root.get_at_coords(&coords[..]);
if let Some(n) = n { if let Some(n) = n {
if let Token::Operator(Operator::Define, _) = n { if let Expression::Operator(Operator::Define, _) = n {
*coords.last_mut().unwrap() += 1; *coords.last_mut().unwrap() += 1;
} }
} }

View File

@ -1,19 +1,19 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::parser::Token; use crate::parser::Expression;
use crate::parser::Function; use crate::parser::Function;
use super::EvalError; use super::EvalError;
pub fn eval_function(f: &Function, args: &VecDeque<Token>) -> Result<Token, EvalError> { pub fn eval_function(f: &Function, args: &VecDeque<Expression>) -> Result<Expression, EvalError> {
if args.len() != 1 {panic!()}; if args.len() != 1 {panic!()};
let a = &args[0]; let a = &args[0];
let Token::Quantity(q) = a else {panic!()}; let Expression::Quantity(q) = a else {panic!()};
match f { match f {
Function::NoUnit => { return Ok(Token::Quantity(q.without_unit())); } Function::NoUnit => { return Ok(Expression::Quantity(q.without_unit())); }
Function::ToBase => { return Ok(Token::Quantity(q.convert_to_base())); } Function::ToBase => { return Ok(Expression::Quantity(q.convert_to_base())); }
_ => {} _ => {}
} }
@ -22,35 +22,35 @@ pub fn eval_function(f: &Function, args: &VecDeque<Token>) -> Result<Token, Eval
} }
match f { match f {
Function::Abs => { return Ok(Token::Quantity(q.abs())); }, Function::Abs => { return Ok(Expression::Quantity(q.abs())); },
Function::Floor => { return Ok(Token::Quantity(q.floor())); }, Function::Floor => { return Ok(Expression::Quantity(q.floor())); },
Function::Ceil => { return Ok(Token::Quantity(q.ceil())); }, Function::Ceil => { return Ok(Expression::Quantity(q.ceil())); },
Function::Round => { return Ok(Token::Quantity(q.round())); }, Function::Round => { return Ok(Expression::Quantity(q.round())); },
Function::NaturalLog => { return Ok(Token::Quantity(q.ln())); }, Function::NaturalLog => { return Ok(Expression::Quantity(q.ln())); },
Function::TenLog => { return Ok(Token::Quantity(q.log10())); }, Function::TenLog => { return Ok(Expression::Quantity(q.log10())); },
Function::Sin => { return Ok(Token::Quantity(q.sin())); }, Function::Sin => { return Ok(Expression::Quantity(q.sin())); },
Function::Cos => { return Ok(Token::Quantity(q.cos())); }, Function::Cos => { return Ok(Expression::Quantity(q.cos())); },
Function::Tan => { return Ok(Token::Quantity(q.tan())); }, Function::Tan => { return Ok(Expression::Quantity(q.tan())); },
Function::Asin => { return Ok(Token::Quantity(q.asin())); }, Function::Asin => { return Ok(Expression::Quantity(q.asin())); },
Function::Acos => { return Ok(Token::Quantity(q.acos())); }, Function::Acos => { return Ok(Expression::Quantity(q.acos())); },
Function::Atan => { return Ok(Token::Quantity(q.atan())); }, Function::Atan => { return Ok(Expression::Quantity(q.atan())); },
Function::Csc => { return Ok(Token::Quantity(q.csc())); }, Function::Csc => { return Ok(Expression::Quantity(q.csc())); },
Function::Sec => { return Ok(Token::Quantity(q.sec())); }, Function::Sec => { return Ok(Expression::Quantity(q.sec())); },
Function::Cot => { return Ok(Token::Quantity(q.cot())); }, Function::Cot => { return Ok(Expression::Quantity(q.cot())); },
Function::Sinh => { return Ok(Token::Quantity(q.sinh())); }, Function::Sinh => { return Ok(Expression::Quantity(q.sinh())); },
Function::Cosh => { return Ok(Token::Quantity(q.cosh())); }, Function::Cosh => { return Ok(Expression::Quantity(q.cosh())); },
Function::Tanh => { return Ok(Token::Quantity(q.tanh())); }, Function::Tanh => { return Ok(Expression::Quantity(q.tanh())); },
Function::Asinh => { return Ok(Token::Quantity(q.asinh())); }, Function::Asinh => { return Ok(Expression::Quantity(q.asinh())); },
Function::Acosh => { return Ok(Token::Quantity(q.acosh())); }, Function::Acosh => { return Ok(Expression::Quantity(q.acosh())); },
Function::Atanh => { return Ok(Token::Quantity(q.atanh())); }, Function::Atanh => { return Ok(Expression::Quantity(q.atanh())); },
Function::Csch => { return Ok(Token::Quantity(q.csch())); }, Function::Csch => { return Ok(Expression::Quantity(q.csch())); },
Function::Sech => { return Ok(Token::Quantity(q.sech())); }, Function::Sech => { return Ok(Expression::Quantity(q.sech())); },
Function::Coth => { return Ok(Token::Quantity(q.coth())); }, Function::Coth => { return Ok(Expression::Quantity(q.coth())); },
Function::ToBase Function::ToBase
| Function::NoUnit | Function::NoUnit

View File

@ -2,11 +2,11 @@ use std::collections::VecDeque;
use crate::quantity::Quantity; use crate::quantity::Quantity;
use crate::parser::Operator; use crate::parser::Operator;
use crate::parser::Token; use crate::parser::Expression;
use super::EvalError; use super::EvalError;
use crate::context::Context; use crate::context::Context;
pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Context) -> Result<Option<Token>, EvalError> { pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut Context) -> Result<Option<Expression>, EvalError> {
match op { match op {
// Handled seperately in evaluate.rs // Handled seperately in evaluate.rs
@ -24,7 +24,7 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
if args.len() != 2 { panic!() }; if args.len() != 2 { panic!() };
let b = &args[1]; let b = &args[1];
if let Token::Variable(s) = &args[0] { if let Expression::Variable(s) = &args[0] {
context.push_var(s.clone(), b.clone()); context.push_var(s.clone(), b.clone());
return Ok(Some(b.clone())); return Ok(Some(b.clone()));
} else { return Err(EvalError::BadDefineName); } } else { return Err(EvalError::BadDefineName); }
@ -34,8 +34,8 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
if args.len() != 1 { panic!() }; if args.len() != 1 { panic!() };
let args = &args[0]; let args = &args[0];
if let Token::Quantity(v) = args { if let Expression::Quantity(v) = args {
return Ok(Some(Token::Quantity(-v.clone()))); return Ok(Some(Expression::Quantity(-v.clone())));
} else { return Ok(None); } } else { return Ok(None); }
}, },
@ -43,9 +43,9 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
if args.len() != 1 { panic!() }; if args.len() != 1 { panic!() };
let args = &args[0]; let args = &args[0];
if let Token::Quantity(v) = args { if let Expression::Quantity(v) = args {
if v.is_zero() { return Err(EvalError::ZeroDivision); } if v.is_zero() { return Err(EvalError::ZeroDivision); }
return Ok(Some(Token::Quantity( return Ok(Some(Expression::Quantity(
Quantity::new_rational(1f64).unwrap()/v.clone() Quantity::new_rational(1f64).unwrap()/v.clone()
))); )));
} else { return Ok(None); } } else { return Ok(None); }
@ -53,14 +53,14 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
Operator::Add => { Operator::Add => {
let mut sum: Quantity; let mut sum: Quantity;
if let Token::Quantity(s) = &args[0] { if let Expression::Quantity(s) = &args[0] {
sum = s.clone(); sum = s.clone();
} else { return Ok(None); }; } else { return Ok(None); };
let mut i: usize = 1; let mut i: usize = 1;
while i < args.len() { while i < args.len() {
let j = &args[i]; let j = &args[i];
if let Token::Quantity(v) = j { if let Expression::Quantity(v) = j {
if !sum.unit.compatible_with(&v.unit) { if !sum.unit.compatible_with(&v.unit) {
return Err(EvalError::IncompatibleUnit); return Err(EvalError::IncompatibleUnit);
@ -70,18 +70,18 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
} else { return Ok(None); } } else { return Ok(None); }
i += 1; i += 1;
} }
return Ok(Some(Token::Quantity(sum))); return Ok(Some(Expression::Quantity(sum)));
}, },
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() {
let j = i; let j = i;
if let Token::Quantity(v) = j { if let Expression::Quantity(v) = j {
prod *= v.clone(); prod *= v.clone();
} else { return Ok(None); } } else { return Ok(None); }
} }
return Ok(Some(Token::Quantity(prod))); return Ok(Some(Expression::Quantity(prod)));
}, },
Operator::ModuloLong Operator::ModuloLong
@ -90,8 +90,8 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
let a = &args[0]; let a = &args[0];
let b = &args[1]; let b = &args[1];
if let Token::Quantity(va) = a { if let Expression::Quantity(va) = a {
if let Token::Quantity(vb) = b { if let Expression::Quantity(vb) = b {
if !(va.unitless() && vb.unitless()) { if !(va.unitless() && vb.unitless()) {
return Err(EvalError::IncompatibleUnit); return Err(EvalError::IncompatibleUnit);
@ -101,7 +101,7 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
if va.fract() != Quantity::new_rational(0f64).unwrap() { return Err(EvalError::BadMath); } if va.fract() != Quantity::new_rational(0f64).unwrap() { return Err(EvalError::BadMath); }
if vb.fract() != Quantity::new_rational(0f64).unwrap() { return Err(EvalError::BadMath); } if vb.fract() != Quantity::new_rational(0f64).unwrap() { return Err(EvalError::BadMath); }
return Ok(Some(Token::Quantity(va.clone() % vb.clone()))); return Ok(Some(Expression::Quantity(va.clone() % vb.clone())));
} else { return Ok(None); } } else { return Ok(None); }
} else { return Ok(None); } } else { return Ok(None); }
}, },
@ -112,13 +112,13 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
let a = &args[0]; let a = &args[0];
let b = &args[1]; let b = &args[1];
if let Token::Quantity(va) = a { if let Expression::Quantity(va) = a {
if let Token::Quantity(vb) = b { if let Expression::Quantity(vb) = b {
let n = va.clone().convert_to(vb.clone()); let n = va.clone().convert_to(vb.clone());
if n.is_none() { if n.is_none() {
return Err(EvalError::IncompatibleUnit); return Err(EvalError::IncompatibleUnit);
} }
return Ok(Some(Token::Quantity(n.unwrap()))); return Ok(Some(Expression::Quantity(n.unwrap())));
} else { return Ok(None); } } else { return Ok(None); }
} else { return Ok(None); } } else { return Ok(None); }
}, },
@ -128,8 +128,8 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
let a = &args[0]; let a = &args[0];
let b = &args[1]; let b = &args[1];
if let Token::Quantity(va) = a { if let Expression::Quantity(va) = a {
if let Token::Quantity(vb) = b { if let Expression::Quantity(vb) = b {
if !vb.unitless() { if !vb.unitless() {
return Err(EvalError::IncompatibleUnit); return Err(EvalError::IncompatibleUnit);
@ -141,7 +141,7 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
let p = va.pow(vb.clone()); let p = va.pow(vb.clone());
if p.is_nan() {return Err(EvalError::BadMath);} if p.is_nan() {return Err(EvalError::BadMath);}
return Ok(Some(Token::Quantity(p))); return Ok(Some(Expression::Quantity(p)));
} else { return Ok(None); } } else { return Ok(None); }
} else { return Ok(None); } } else { return Ok(None); }
}, },
@ -150,7 +150,7 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
if args.len() != 1 {panic!()}; if args.len() != 1 {panic!()};
let args = &args[0]; let args = &args[0];
if let Token::Quantity(v) = args { if let Expression::Quantity(v) = args {
if !v.unitless() { if !v.unitless() {
return Err(EvalError::IncompatibleUnit); return Err(EvalError::IncompatibleUnit);
@ -166,7 +166,7 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Token>, context: &mut Contex
u = u - Quantity::new_rational(1f64).unwrap(); u = u - Quantity::new_rational(1f64).unwrap();
} }
return Ok(Some(Token::Quantity(prod))); return Ok(Some(Expression::Quantity(prod)));
} else { return Ok(None); } } else { return Ok(None); }
} }
}; };

View File

@ -4,64 +4,64 @@ use crate::quantity::Quantity;
use super::Operator; use super::Operator;
use super::Constant; use super::Constant;
/// Tokens represent logical objects in an expession. /// Expressions represent logical objects in an expession.
#[derive(Debug)] #[derive(Debug)]
#[derive(Clone)] #[derive(Clone)]
pub enum Token { pub enum Expression {
Variable(String), Variable(String),
Quantity(Quantity), Quantity(Quantity),
Constant(Constant), Constant(Constant),
Operator(Operator, VecDeque<Token>), Operator(Operator, VecDeque<Expression>),
} }
impl ToString for Token { impl ToString for Expression {
fn to_string(&self) -> String { fn to_string(&self) -> String {
match self { match self {
Token::Quantity(v) => v.to_string(), Expression::Quantity(v) => v.to_string(),
Token::Constant(c) => c.to_string(), Expression::Constant(c) => c.to_string(),
Token::Variable(s) => s.clone(), Expression::Variable(s) => s.clone(),
Token::Operator(o,a) => o.print(a) Expression::Operator(o,a) => o.print(a)
} }
} }
} }
impl Token { impl Expression {
// This is called only when this is the outermost token. // This is called only when this is the outermost Expression.
// This sometimes leads to different--usually more verbose--behavior. // This sometimes leads to different--usually more verbose--behavior.
pub fn to_string_outer(&self) -> String { pub fn to_string_outer(&self) -> String {
match self { match self {
Token::Quantity(v) => v.to_string_outer(), Expression::Quantity(v) => v.to_string_outer(),
Token::Constant(c) => c.to_string(), Expression::Constant(c) => c.to_string(),
Token::Variable(s) => s.clone(), Expression::Variable(s) => s.clone(),
Token::Operator(o,a) => o.print(a) Expression::Operator(o,a) => o.print(a)
} }
} }
pub fn is_quantity(&self) -> bool { pub fn is_quantity(&self) -> bool {
match self { match self {
Token::Quantity(_) => true, Expression::Quantity(_) => true,
_ => false _ => false
} }
} }
#[inline(always)] #[inline(always)]
pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Token>> { pub fn get_args_mut(&mut self) -> Option<&mut VecDeque<Expression>> {
match self { match self {
Token::Operator(_, ref mut a) => Some(a), Expression::Operator(_, ref mut a) => Some(a),
_ => None _ => None
} }
} }
#[inline(always)] #[inline(always)]
pub fn get_args(&self) -> Option<&VecDeque<Token>> { pub fn get_args(&self) -> Option<&VecDeque<Expression>> {
match self { match self {
Token::Operator(_, ref a) => Some(a), Expression::Operator(_, ref a) => Some(a),
_ => None _ => None
} }
} }
#[inline(always)] #[inline(always)]
pub fn get_at_coords<'a, 'b, I>(&'a self, coords: I) -> Option<&'a Token> pub fn get_at_coords<'a, 'b, I>(&'a self, coords: I) -> Option<&'a Expression>
where I: IntoIterator<Item = &'b usize> + Sized { where I: IntoIterator<Item = &'b usize> + Sized {
let mut g = self; let mut g = self;
for t in coords.into_iter() { for t in coords.into_iter() {
@ -73,7 +73,7 @@ impl Token {
} }
#[inline(always)] #[inline(always)]
pub fn get_at_coords_mut<'a, 'b, I>(&'a mut self, coords: I) -> Option<&'a mut Token> pub fn get_at_coords_mut<'a, 'b, I>(&'a mut self, coords: I) -> Option<&'a mut Expression>
where I: IntoIterator<Item = &'b usize> + Sized { where I: IntoIterator<Item = &'b usize> + Sized {
let mut g = self; let mut g = self;
for t in coords.into_iter() { for t in coords.into_iter() {

View File

@ -1,10 +1,10 @@
mod operator; mod operator;
mod function; mod function;
mod token; mod expression;
pub use self::operator::Operator; pub use self::operator::Operator;
pub use self::function::Function; pub use self::function::Function;
pub use self::token::Token; pub use self::expression::Expression;
use super::parse_no_context; use super::parse_no_context;

View File

@ -2,7 +2,7 @@ use std::cmp::Ordering;
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::quantity::Quantity; use crate::quantity::Quantity;
use super::Token; use super::Expression;
use super::Function; use super::Function;
@ -112,7 +112,7 @@ impl Operator {
} }
#[inline(always)] #[inline(always)]
pub fn into_token(self, mut args: VecDeque<Token>) -> Token { pub fn into_expression(self, mut args: VecDeque<Expression>) -> Expression {
match self { match self {
Operator::Subtract => { Operator::Subtract => {
if args.len() != 2 { panic!() } if args.len() != 2 { panic!() }
@ -120,13 +120,13 @@ impl Operator {
let b = args.pop_front().unwrap(); let b = args.pop_front().unwrap();
let b_new; let b_new;
if let Token::Quantity(q) = b { if let Expression::Quantity(q) = b {
b_new = Token::Quantity(-q); b_new = Expression::Quantity(-q);
} else { } else {
b_new = Token::Operator(Operator::Negative, VecDeque::from(vec!(b))); b_new = Expression::Operator(Operator::Negative, VecDeque::from(vec!(b)));
} }
Token::Operator( Expression::Operator(
Operator::Add, Operator::Add,
VecDeque::from(vec!(a,b_new)) VecDeque::from(vec!(a,b_new))
) )
@ -137,9 +137,9 @@ 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(Operator::Flip, VecDeque::from(vec!(b))); let b = Expression::Operator(Operator::Flip, VecDeque::from(vec!(b)));
Token::Operator( Expression::Operator(
Operator::Multiply, Operator::Multiply,
VecDeque::from(vec!(a,b)) VecDeque::from(vec!(a,b))
) )
@ -149,14 +149,14 @@ impl Operator {
if args.len() != 1 { panic!() } if args.len() != 1 { panic!() }
let a = args.pop_front().unwrap(); let a = args.pop_front().unwrap();
Token::Operator( Expression::Operator(
Operator::Power, Operator::Power,
VecDeque::from(vec!(a, Token::Quantity(Quantity::new_rational_from_string("0.5").unwrap()))) VecDeque::from(vec!(a, Expression::Quantity(Quantity::new_rational_from_string("0.5").unwrap())))
) )
}, },
Operator::ImplicitMultiply Operator::ImplicitMultiply
=> { Token::Operator(Operator::Multiply, args) }, => { Expression::Operator(Operator::Multiply, args) },
Operator::Function(_) Operator::Function(_)
| Operator::Factorial | Operator::Factorial
@ -169,15 +169,15 @@ impl Operator {
| Operator::ModuloLong | Operator::ModuloLong
| Operator::UnitConvert | Operator::UnitConvert
| Operator::Define | Operator::Define
=> { Token::Operator(self, args) }, => { Expression::Operator(self, args) },
} }
} }
#[inline(always)] #[inline(always)]
fn add_parens_to_arg(&self, arg: &Token) -> String { fn add_parens_to_arg(&self, arg: &Expression) -> String {
let mut astr: String = arg.to_string(); let mut astr: String = arg.to_string();
if let Token::Operator(o,_) = arg { if let Expression::Operator(o,_) = arg {
if o < self { if o < self {
astr = format!("({})", astr); astr = format!("({})", astr);
} }
@ -186,9 +186,9 @@ impl Operator {
} }
#[inline(always)] #[inline(always)]
fn add_parens_to_arg_strict(&self, arg: &Token) -> String { fn add_parens_to_arg_strict(&self, arg: &Expression) -> String {
let mut astr: String = arg.to_string(); let mut astr: String = arg.to_string();
if let Token::Operator(o,_) = arg { if let Expression::Operator(o,_) = arg {
if o <= self { if o <= self {
astr = format!("({})", astr); astr = format!("({})", astr);
} }
@ -197,7 +197,7 @@ impl Operator {
} }
pub fn print(&self, args: &VecDeque<Token>) -> String { pub fn print(&self, args: &VecDeque<Expression>) -> String {
match self { match self {
Operator::ImplicitMultiply | Operator::ImplicitMultiply |
Operator::Sqrt | Operator::Sqrt |
@ -268,7 +268,7 @@ impl Operator {
let a = &args[0]; let a = &args[0];
let b; let sub; let b; let sub;
if let Token::Operator(o, ar) = &args[1] { if let Expression::Operator(o, ar) = &args[1] {
if let Operator::Negative = o { if let Operator::Negative = o {
sub = true; sub = true;
b = &ar[0]; b = &ar[0];
@ -294,7 +294,7 @@ impl Operator {
let a = &args[0]; let a = &args[0];
let b; let div; let b; let div;
if let Token::Operator(o, ar) = &args[1] { if let Expression::Operator(o, ar) = &args[1] {
if let Operator::Flip = o { if let Operator::Flip = o {
div = true; div = true;
b = &ar[0]; b = &ar[0];
@ -314,15 +314,15 @@ impl Operator {
// multiplied by a unit (like 10 m) // multiplied by a unit (like 10 m)
// Times sign should stay in all other cases. // Times sign should stay in all other cases.
let no_times = { let no_times = {
if let Token::Quantity(p) = a { if let Expression::Quantity(p) = a {
if let Token::Quantity(q) = b { if let Expression::Quantity(q) = b {
p.unitless() && !q.unitless() p.unitless() && !q.unitless()
} else {false} } else {false}
} else {false} } else {false}
}; };
if no_times { if no_times {
let Token::Quantity(u) = b else {panic!()}; let Expression::Quantity(u) = b else {panic!()};
if u.unit.no_space() { if u.unit.no_space() {
return format!("{}{}", return format!("{}{}",
self.add_parens_to_arg_strict(a), self.add_parens_to_arg_strict(a),

View File

@ -1,20 +1,20 @@
mod stage; mod stage;
mod pretoken;
mod parsererror;
mod token; mod token;
mod parsererror;
mod expression;
use self::{ use self::{
pretoken::PreToken, token::Token,
parsererror::ParserError, parsererror::ParserError,
parsererror::LineLocation parsererror::LineLocation
}; };
pub use self::{ pub use self::{
token::Token, expression::Expression,
token::Constant, expression::Constant,
token::Operator, expression::Operator,
token::Function, expression::Function,
}; };
use crate::context::Context; use crate::context::Context;
@ -22,18 +22,18 @@ use crate::context::Context;
pub fn parse( pub fn parse(
s: &String, context: &Context s: &String, context: &Context
) -> Result<Token, (LineLocation, ParserError)> { ) -> Result<Expression, (LineLocation, ParserError)> {
let tokens = stage::tokenize(s); let expressions = stage::tokenize(s);
let (_, tokens) = stage::find_subs(tokens); let (_, expressions) = stage::find_subs(expressions);
let g = stage::groupify(tokens)?; let g = stage::groupify(expressions)?;
let g = stage::treeify(g, context)?; let g = stage::treeify(g, context)?;
return Ok(g); return Ok(g);
} }
pub fn parse_no_context(s: &String) -> Result<Token, (LineLocation, ParserError)> { pub fn parse_no_context(s: &String) -> Result<Expression, (LineLocation, ParserError)> {
parse(s, &Context::new()) parse(s, &Context::new())
} }
@ -49,8 +49,8 @@ pub fn substitute(
let mut new_s = s.clone(); let mut new_s = s.clone();
let l = s.chars().count(); let l = s.chars().count();
let tokens = stage::tokenize(s); let expressions = stage::tokenize(s);
let (subs, _) = stage::find_subs(tokens); let (subs, _) = stage::find_subs(expressions);
let mut new_c = l - c; let mut new_c = l - c;
for r in subs.iter() { for r in subs.iter() {

View File

@ -1,5 +1,4 @@
/// Specifies the location of a token in an input string. /// Specifies the location of a token in an input string.
/// Used to locate ParserErrors.
#[derive(Debug)] #[derive(Debug)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct LineLocation { pub struct LineLocation {

View File

@ -1,23 +1,23 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use super::super::{ use super::super::{
PreToken, Token,
LineLocation LineLocation
}; };
pub fn find_subs( pub fn find_subs(
mut g: VecDeque<PreToken>, mut g: VecDeque<Token>,
) -> ( ) -> (
Vec<(LineLocation, String)>, Vec<(LineLocation, String)>,
VecDeque<PreToken> VecDeque<Token>
) { ) {
// Array of replacements // Array of replacements
let mut r: Vec<(LineLocation, String)> = Vec::with_capacity(8); let mut r: Vec<(LineLocation, String)> = Vec::with_capacity(8);
// New token array, with updated locations // New token array, with updated locations
let mut n: VecDeque<PreToken> = VecDeque::with_capacity(g.len()); let mut n: VecDeque<Token> = VecDeque::with_capacity(g.len());
let mut offset: usize = 0; let mut offset: usize = 0;
@ -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 {
PreToken::PreOperator(_, s) => { Token::PreOperator(_, s) => {
let target = match &s[..] { let target = match &s[..] {
"*" => {Some("×")}, "*" => {Some("×")},
"/" => {Some("÷")}, "/" => {Some("÷")},
@ -41,7 +41,7 @@ pub fn find_subs(
target target
}, },
PreToken::PreWord(_, s) => { Token::PreWord(_, s) => {
let target = match &s[..] { let target = match &s[..] {
// Greek letters // Greek letters
"alpha" => {Some("α")}, "alpha" => {Some("α")},

View File

@ -1,7 +1,7 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use super::super::{ use super::super::{
PreToken, Token,
LineLocation, LineLocation,
ParserError, ParserError,
Operator Operator
@ -9,7 +9,7 @@ use super::super::{
fn lookback_signs( fn lookback_signs(
g: &mut VecDeque<PreToken> g: &mut VecDeque<Token>
) -> Result<(), (LineLocation, ParserError)> { ) -> Result<(), (LineLocation, ParserError)> {
// Convert `-` operators to `neg` operators // Convert `-` operators to `neg` operators
@ -17,12 +17,12 @@ fn lookback_signs(
let mut i: usize = 0; let mut i: usize = 0;
while i < g.len() { while i < g.len() {
if i == 0 { if i == 0 {
let a: PreToken = g.remove(i).unwrap(); let a: Token = g.remove(i).unwrap();
match &a { match &a {
PreToken::PreOperator(l,o) Token::PreOperator(l,o)
=> { => {
if o == "-" { if o == "-" {
g.insert(i, PreToken::PreOperator(*l, String::from("neg"))); g.insert(i, Token::PreOperator(*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);}
@ -31,11 +31,11 @@ fn lookback_signs(
}; };
} else { } else {
let a: PreToken = g.remove(i-1).unwrap(); let a: Token = g.remove(i-1).unwrap();
let b: PreToken = g.remove(i-1).unwrap(); let b: Token = g.remove(i-1).unwrap();
match (&a, &b) { match (&a, &b) {
(PreToken::PreOperator(_, sa), PreToken::PreOperator(l,sb)) (Token::PreOperator(_, sa), Token::PreOperator(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, PreToken::PreOperator(*l, String::from("neg"))); g.insert(i-1, Token::PreOperator(*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);
@ -67,11 +67,11 @@ fn lookback_signs(
// Delete consecutive `neg`s // Delete consecutive `neg`s
let mut i: usize = 1; let mut i: usize = 1;
while i < g.len() { while i < g.len() {
let a: PreToken = g.remove(i-1).unwrap(); let a: Token = g.remove(i-1).unwrap();
let b: PreToken = g.remove(i-1).unwrap(); let b: Token = g.remove(i-1).unwrap();
match (&a, &b) { match (&a, &b) {
(PreToken::PreOperator(_,sa), PreToken::PreOperator(_,sb)) (Token::PreOperator(_,sa), Token::PreOperator(_,sb))
=> { => {
if !((sa == "neg") && (sb == "neg")) { if !((sa == "neg") && (sb == "neg")) {
g.insert(i-1, b); g.insert(i-1, b);
@ -95,7 +95,7 @@ fn lookback_signs(
// Inserts implicit operators // Inserts implicit operators
fn lookback( fn lookback(
g: &mut VecDeque<PreToken> g: &mut VecDeque<Token>
) -> Result<(), (LineLocation, ParserError)> { ) -> Result<(), (LineLocation, ParserError)> {
lookback_signs(g)?; lookback_signs(g)?;
@ -103,24 +103,24 @@ fn lookback(
let mut i: usize = 0; let mut i: usize = 0;
while i < g.len() { while i < g.len() {
if i >= 1 { if i >= 1 {
let a: PreToken = g.remove(i-1).unwrap(); let a: Token = g.remove(i-1).unwrap();
let b: PreToken = g.remove(i-1).unwrap(); let b: Token = g.remove(i-1).unwrap();
match (&a, &b) { match (&a, &b) {
// Insert ImplicitMultiply // Insert ImplicitMultiply
(PreToken::PreGroup(_,_), PreToken::PreGroup(l ,_)) (Token::PreGroup(_,_), Token::PreGroup(l ,_))
| (PreToken::PreGroup(_,_), PreToken::PreQuantity(l,_)) | (Token::PreGroup(_,_), Token::PreQuantity(l,_))
| (PreToken::PreQuantity(_,_), PreToken::PreGroup(l,_)) | (Token::PreQuantity(_,_), Token::PreGroup(l,_))
| (PreToken::PreGroup(_,_), PreToken::PreWord(l,_)) | (Token::PreGroup(_,_), Token::PreWord(l,_))
| (PreToken::PreWord(_,_), PreToken::PreGroup(l,_)) | (Token::PreWord(_,_), Token::PreGroup(l,_))
| (PreToken::PreQuantity(_,_), PreToken::PreWord(l,_)) | (Token::PreQuantity(_,_), Token::PreWord(l,_))
| (PreToken::PreWord(_,_), PreToken::PreQuantity(l,_)) | (Token::PreWord(_,_), Token::PreQuantity(l,_))
| (PreToken::PreWord(_,_), PreToken::PreWord(l,_)) | (Token::PreWord(_,_), Token::PreWord(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, PreToken::PreOperator( g.insert(i-1, Token::PreOperator(
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
(PreToken::PreQuantity(_,_), PreToken::PreOperator(l,s)) (Token::PreQuantity(_,_), Token::PreOperator(l,s))
| (PreToken::PreGroup(_,_), PreToken::PreOperator(l,s)) | (Token::PreGroup(_,_), Token::PreOperator(l,s))
| (PreToken::PreWord(_,_), PreToken::PreOperator(l,s)) | (Token::PreWord(_,_), Token::PreOperator(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, PreToken::PreOperator( g.insert(i-1, Token::PreOperator(
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.
(PreToken::PreOperator(_,s), PreToken::PreQuantity(l,_)) (Token::PreOperator(_,s), Token::PreQuantity(l,_))
| (PreToken::PreOperator(_,s), PreToken::PreGroup(l,_)) | (Token::PreOperator(_,s), Token::PreGroup(l,_))
| (PreToken::PreOperator(_,s), PreToken::PreWord(l,_)) | (Token::PreOperator(_,s), Token::PreWord(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, PreToken::PreOperator( g.insert(i-1, Token::PreOperator(
loc, loc,
String::from("i*") String::from("i*")
)); ));
@ -170,7 +170,7 @@ fn lookback(
}, },
// The following are syntax errors // The following are syntax errors
(PreToken::PreQuantity(la,_), PreToken::PreQuantity(lb,_)) (Token::PreQuantity(la,_), Token::PreQuantity(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},
@ -189,13 +189,13 @@ fn lookback(
pub fn groupify( pub fn groupify(
mut g: VecDeque<PreToken> mut g: VecDeque<Token>
) -> Result< ) -> Result<
PreToken, Token,
(LineLocation, ParserError) (LineLocation, ParserError)
> { > {
// Vector of grouping levels // Vector of grouping levels
let mut levels: Vec<(LineLocation, VecDeque<PreToken>)> = Vec::with_capacity(8); let mut levels: Vec<(LineLocation, VecDeque<Token>)> = Vec::with_capacity(8);
levels.push((LineLocation{pos: 0, len: 0}, VecDeque::with_capacity(8))); levels.push((LineLocation{pos: 0, len: 0}, VecDeque::with_capacity(8)));
// Makes sure parenthesis are matched // Makes sure parenthesis are matched
@ -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 {
PreToken::PreGroupStart(l) => { Token::PreGroupStart(l) => {
levels.push((l, VecDeque::with_capacity(8))); levels.push((l, VecDeque::with_capacity(8)));
i_level += 1; i_level += 1;
}, },
PreToken::PreGroupEnd(l) => { Token::PreGroupEnd(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(PreToken::PreGroup(l, v)); v_now.push_back(Token::PreGroup(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(PreToken::PreGroup(l, v)); v_now.push_back(Token::PreGroup(l, v));
} }
let (_, mut v) = levels.pop().unwrap(); let (_, mut v) = levels.pop().unwrap();
lookback(&mut v)?; lookback(&mut v)?;
return Ok(PreToken::PreGroup(LineLocation{pos:0, len:0}, v)); return Ok(Token::PreGroup(LineLocation{pos:0, len:0}, v));
} }

View File

@ -1,24 +1,24 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use super::super::{ use super::super::{
PreToken, Token,
LineLocation, LineLocation,
Operator Operator
}; };
// Called whenever a token is finished. // Called whenever a token is finished.
#[inline(always)] #[inline(always)]
fn push_token(g: &mut VecDeque<PreToken>, t: Option<PreToken>, stop_i: usize) { fn push_token(g: &mut VecDeque<Token>, t: Option<Token>, stop_i: usize) {
if t.is_none() { return } if t.is_none() { return }
let mut t = t.unwrap(); let mut t = t.unwrap();
match t { match t {
PreToken::PreGroupStart(ref mut l) Token::PreGroupStart(ref mut l)
| PreToken::PreGroupEnd(ref mut l) | Token::PreGroupEnd(ref mut l)
| PreToken::PreOperator(ref mut l, _) | Token::PreOperator(ref mut l, _)
| PreToken::PreQuantity(ref mut l, _) | Token::PreQuantity(ref mut l, _)
| PreToken::PreWord(ref mut l, _) | Token::PreWord(ref mut l, _)
=> { => {
*l = LineLocation{ *l = LineLocation{
pos: l.pos, pos: l.pos,
@ -26,22 +26,22 @@ fn push_token(g: &mut VecDeque<PreToken>, t: Option<PreToken>, stop_i: usize) {
}; };
}, },
PreToken::PreGroup(_,_) Token::PreGroup(_,_)
| PreToken::Container(_) | Token::Container(_)
=> panic!() => panic!()
}; };
// `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 PreToken::PreQuantity(l, s) = &t { if let Token::PreQuantity(l, s) = &t {
let last = &s[s.len()-1..]; let last = &s[s.len()-1..];
if last == "e" { if last == "e" {
g.push_back(PreToken::PreQuantity( g.push_back(Token::PreQuantity(
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(PreToken::PreWord( g.push_back(Token::PreWord(
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<PreToken>, t: Option<PreToken>, stop_i: usize) {
} }
// Some operators are written as words. // Some operators are written as words.
if let PreToken::PreWord(l, s) = &t { if let Token::PreWord(l, s) = &t {
if Operator::from_string(s).is_some() { if Operator::from_string(s).is_some() {
t = PreToken::PreOperator(*l, s.clone()); t = Token::PreOperator(*l, s.clone());
} }
} }
@ -61,9 +61,9 @@ fn push_token(g: &mut VecDeque<PreToken>, t: Option<PreToken>, stop_i: usize) {
} }
/// Turns a string into Tokens. First stage of parsing. /// Turns a string into Tokens. First stage of parsing.
pub fn tokenize(input: &String) -> VecDeque<PreToken> { pub fn tokenize(input: &String) -> VecDeque<Token> {
let mut t: Option<PreToken> = None; // The current token we're reading let mut t: Option<Token> = None; // The current token we're reading
let mut g: VecDeque<PreToken> = VecDeque::with_capacity(32); let mut g: VecDeque<Token> = VecDeque::with_capacity(32);
for (i, c) in input.chars().enumerate() { for (i, c) in input.chars().enumerate() {
@ -74,7 +74,7 @@ pub fn tokenize(input: &String) -> VecDeque<PreToken> {
match &mut t { match &mut t {
// If we're already building a number, // If we're already building a number,
// append. // append.
Some(PreToken::PreQuantity(_, val)) => { Some(Token::PreQuantity(_, val)) => {
val.push(if c == ',' {'.'} else {c}); val.push(if c == ',' {'.'} else {c});
}, },
@ -82,7 +82,7 @@ pub fn tokenize(input: &String) -> VecDeque<PreToken> {
// previous token and start one. // previous token and start one.
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(PreToken::PreQuantity(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(Token::PreQuantity(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
}, },
@ -91,12 +91,12 @@ pub fn tokenize(input: &String) -> VecDeque<PreToken> {
// 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(PreToken::PreWord(_, val)) => { val.push(c); }, Some(Token::PreWord(_, val)) => { val.push(c); },
Some(PreToken::PreQuantity(_, val)) => { val.push(c); }, Some(Token::PreQuantity(_, val)) => { val.push(c); },
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(PreToken::PreWord(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(Token::PreWord(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
} }
@ -106,7 +106,7 @@ pub fn tokenize(input: &String) -> VecDeque<PreToken> {
// or it can specify a negative exponent. // or it can specify a negative exponent.
'-' | '+' => { '-' | '+' => {
match &mut t { match &mut t {
Some(PreToken::PreQuantity(_, val)) => { Some(Token::PreQuantity(_, 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<PreToken> {
// 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(PreToken::PreOperator( t = Some(Token::PreOperator(
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<PreToken> {
// 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(PreToken::PreOperator( t = Some(Token::PreOperator(
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<PreToken> {
'^'|'!'|'%'|'=' '^'|'!'|'%'|'='
=> { => {
match &mut t { match &mut t {
Some(PreToken::PreOperator(_, val)) => { val.push(c); }, Some(Token::PreOperator(_, val)) => { val.push(c); },
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(PreToken::PreOperator(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(Token::PreOperator(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
}, },
@ -150,11 +150,11 @@ pub fn tokenize(input: &String) -> VecDeque<PreToken> {
// Group // Group
'(' => { '(' => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(PreToken::PreGroupStart(LineLocation{pos: i, len: 0})); t = Some(Token::PreGroupStart(LineLocation{pos: i, len: 0}));
}, },
')' => { ')' => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(PreToken::PreGroupEnd(LineLocation{pos: i, len: 0})); t = Some(Token::PreGroupEnd(LineLocation{pos: i, len: 0}));
}, },
// Space. Basic seperator. // Space. Basic seperator.
@ -166,11 +166,11 @@ pub fn tokenize(input: &String) -> VecDeque<PreToken> {
// Word // Word
_ => { _ => {
match &mut t { match &mut t {
Some(PreToken::PreWord(_, val)) => { val.push(c); }, Some(Token::PreWord(_, val)) => { val.push(c); },
_ => { _ => {
push_token(&mut g, t, i); push_token(&mut g, t, i);
t = Some(PreToken::PreWord(LineLocation{pos: i, len: 0}, String::from(c))); t = Some(Token::PreWord(LineLocation{pos: i, len: 0}, String::from(c)));
} }
}; };
} }

View File

@ -2,25 +2,25 @@ use std::collections::VecDeque;
use crate::context::Context; use crate::context::Context;
use super::super::{ use super::super::{
PreToken, Token,
ParserError, ParserError,
LineLocation, LineLocation,
Token, Expression,
Operator Operator
}; };
fn treeify_binary( fn treeify_binary(
i: usize, i: usize,
g_inner: &mut VecDeque<PreToken>, g_inner: &mut VecDeque<Token>,
context: &Context context: &Context
) -> Result<bool, (LineLocation, ParserError)> { ) -> Result<bool, (LineLocation, ParserError)> {
let this: &PreToken = &g_inner[i]; let this: &Token = &g_inner[i];
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 {
PreToken::PreOperator(l, _) => l, Token::PreOperator(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 {
PreToken::PreOperator(l, _) => l, Token::PreOperator(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 {
PreToken::PreOperator(l, _) => l, Token::PreOperator(l, _) => l,
_ => panic!() _ => panic!()
}; };
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
@ -55,7 +55,7 @@ fn treeify_binary(
if let PreToken::PreOperator(l, s) = left { if let Token::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();
@ -74,7 +74,7 @@ fn treeify_binary(
} }
} }
if let PreToken::PreOperator(l, s) = right { if let Token::PreOperator(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 PreToken::PreOperator(l, s) = this else {panic!()}; let Token::PreOperator(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 PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; let Token::PreOperator(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 PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; let Token::PreOperator(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())
@ -126,22 +126,22 @@ fn treeify_binary(
let left_pre = g_inner.remove(i-1).unwrap(); let left_pre = g_inner.remove(i-1).unwrap();
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: Expression; let right: Expression;
if let PreToken::PreGroup(_, _) = right_pre { right = treeify(right_pre, context)?; } else {right = right_pre.to_token(context)?;} if let Token::PreGroup(_, _) = right_pre { right = treeify(right_pre, context)?; } else {right = right_pre.to_expression(context)?;}
if let PreToken::PreGroup(_, _) = left_pre { left = treeify(left_pre, context)?; } else {left = left_pre.to_token(context)?;} if let Token::PreGroup(_, _) = left_pre { left = treeify(left_pre, context)?; } else {left = left_pre.to_expression(context)?;}
let o = { let o = {
let PreToken::PreOperator(_, s) = this_pre else {panic!()}; let Token::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!() }
o.unwrap() o.unwrap()
}; };
let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(2); let mut new_token_args: VecDeque<Expression> = 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(new_token_args))); g_inner.insert(i-1, Token::Container(o.into_expression(new_token_args)));
return Ok(true); return Ok(true);
} else { } else {
@ -151,20 +151,20 @@ fn treeify_binary(
fn treeify_unary( fn treeify_unary(
i: usize, i: usize,
g_inner: &mut VecDeque<PreToken>, g_inner: &mut VecDeque<Token>,
left_associative: bool, left_associative: bool,
context: &Context context: &Context
) -> Result<bool, (LineLocation, ParserError)> { ) -> Result<bool, (LineLocation, ParserError)> {
let this: &PreToken = &g_inner[i]; let this: &Token = &g_inner[i];
let next: &PreToken; let next: &Token;
if left_associative { if left_associative {
next = { next = {
if i > 0 { if i > 0 {
&g_inner[i-1] &g_inner[i-1]
} else { } else {
let l = match this { let l = match this {
PreToken::PreOperator(l, _) => l, Token::PreOperator(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 {
PreToken::PreOperator(l, _) => l, Token::PreOperator(l, _) => l,
_ => panic!() _ => panic!()
}; };
return Err((*l, ParserError::Syntax)); return Err((*l, ParserError::Syntax));
@ -186,7 +186,7 @@ fn treeify_unary(
// We need to check the element after unary operators too. // We need to check the element after unary operators too.
// Bad syntax like `3!3` won't be caught otherwise. // Bad syntax like `3!3` won't be caught otherwise.
let prev: Option<&PreToken>; let prev: Option<&Token>;
if left_associative { if left_associative {
prev = if i < g_inner.len()-1 { Some(&g_inner[i+1]) } else {None}; prev = if i < g_inner.len()-1 { Some(&g_inner[i+1]) } else {None};
} else { } else {
@ -194,7 +194,7 @@ fn treeify_unary(
} }
if prev.is_some() { if prev.is_some() {
if let PreToken::PreOperator(_,_) = prev.unwrap() { if let Token::PreOperator(_,_) = 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 PreToken::PreOperator(l, _) = next { if let Token::PreOperator(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 PreToken::PreOperator(l, s) = this else {panic!()}; let Token::PreOperator(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 PreToken::PreOperator(l, s) = &g_inner[i-2] else {panic!()}; let Token::PreOperator(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 PreToken::PreOperator(l, s) = &g_inner[i+2] else {panic!()}; let Token::PreOperator(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())
@ -239,28 +239,28 @@ fn treeify_unary(
if next_op.is_none() || this_op > next_op.unwrap() { if next_op.is_none() || this_op > next_op.unwrap() {
let this_pre = g_inner.remove(i).unwrap(); let this_pre = g_inner.remove(i).unwrap();
let next_pre: PreToken; let next: Token; let next_pre: Token; let next: Expression;
if left_associative { if left_associative {
next_pre = g_inner.remove(i-1).unwrap(); next_pre = g_inner.remove(i-1).unwrap();
} 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, context)?; } else { next = next_pre.to_token(context)? } if let Token::PreGroup(_, _) = next_pre { next = treeify(next_pre, context)?; } else { next = next_pre.to_expression(context)? }
let o = { let o = {
let PreToken::PreOperator(_, s) = this_pre else {panic!()}; let Token::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!() }
o.unwrap() o.unwrap()
}; };
let mut new_token_args: VecDeque<Token> = VecDeque::with_capacity(3); let mut new_token_args: VecDeque<Expression> = 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(new_token_args))); g_inner.insert(i-1, Token::Container(o.into_expression(new_token_args)));
} else { } else {
g_inner.insert(i, PreToken::Container(o.into_token(new_token_args))); g_inner.insert(i, Token::Container(o.into_expression(new_token_args)));
} }
return Ok(true); return Ok(true);
@ -274,12 +274,12 @@ fn treeify_unary(
pub fn treeify( pub fn treeify(
mut g: PreToken, mut g: Token,
context: &Context context: &Context
) -> Result<Token, (LineLocation, ParserError)> { ) -> Result<Expression, (LineLocation, ParserError)> {
let g_inner: &mut VecDeque<PreToken> = match g { let g_inner: &mut VecDeque<Token> = match g {
PreToken::PreGroup(_, ref mut x) => x, Token::PreGroup(_, ref mut x) => x,
_ => panic!() _ => panic!()
}; };
@ -300,7 +300,7 @@ pub fn treeify(
// Convert preoperators // Convert preoperators
// 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] {
PreToken::PreOperator(l, s) => { Token::PreOperator(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,13 +342,13 @@ 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
PreToken::PreOperator(l, _) => { Token::PreOperator(l, _) => {
Err((l, ParserError::Syntax)) Err((l, ParserError::Syntax))
}, },
PreToken::PreGroup(_,_) => { Token::PreGroup(_,_) => {
treeify(g, context) treeify(g, context)
}, },
_ => { Ok(g.to_token(context)?) } _ => { Ok(g.to_expression(context)?) }
}; };
} }

View File

@ -6,34 +6,34 @@ use crate::context::Context;
use super::{ use super::{
LineLocation, LineLocation,
ParserError, ParserError,
Token, Expression,
Constant Constant
}; };
#[derive(Debug)] #[derive(Debug)]
pub enum PreToken { pub enum Token {
PreQuantity(LineLocation, String), PreQuantity(LineLocation, String),
PreWord(LineLocation, String), PreWord(LineLocation, String),
PreOperator(LineLocation, String), PreOperator(LineLocation, String),
PreGroupStart(LineLocation), PreGroupStart(LineLocation),
PreGroupEnd(LineLocation), PreGroupEnd(LineLocation),
PreGroup(LineLocation, VecDeque<PreToken>), PreGroup(LineLocation, VecDeque<Token>),
Container(Token) Container(Expression)
} }
impl PreToken { impl Token {
#[inline(always)] #[inline(always)]
pub fn get_line_location(&self) -> &LineLocation { pub fn get_line_location(&self) -> &LineLocation {
match self { match self {
PreToken::PreQuantity(l, _) Token::PreQuantity(l, _)
| PreToken::PreWord(l, _) | Token::PreWord(l, _)
| PreToken::PreOperator(l, _) | Token::PreOperator(l, _)
| PreToken::PreGroupStart(l) | Token::PreGroupStart(l)
| PreToken::PreGroupEnd(l) | Token::PreGroupEnd(l)
| PreToken::PreGroup(l, _) | Token::PreGroup(l, _)
=> l, => l,
_ => panic!() _ => panic!()
@ -43,12 +43,12 @@ impl PreToken {
#[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 {
PreToken::PreQuantity(l, _) Token::PreQuantity(l, _)
| PreToken::PreWord(l, _) | Token::PreWord(l, _)
| PreToken::PreOperator(l, _) | Token::PreOperator(l, _)
| PreToken::PreGroupStart(l) | Token::PreGroupStart(l)
| PreToken::PreGroupEnd(l) | Token::PreGroupEnd(l)
| PreToken::PreGroup(l, _) | Token::PreGroup(l, _)
=> l, => l,
_ => panic!() _ => panic!()
@ -56,9 +56,9 @@ impl PreToken {
} }
#[inline(always)] #[inline(always)]
pub fn to_token(self, context: &Context) -> Result<Token, (LineLocation, ParserError)>{ pub fn to_expression(self, context: &Context) -> Result<Expression, (LineLocation, ParserError)>{
match self { match self {
PreToken::PreQuantity(l, mut s) => { Token::PreQuantity(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.`
@ -73,28 +73,28 @@ impl PreToken {
return Err((l, ParserError::BadNumber)) return Err((l, ParserError::BadNumber))
} }
return Ok(Token::Quantity(r.unwrap())); return Ok(Expression::Quantity(r.unwrap()));
}, },
PreToken::PreWord(_l, s) => { Token::PreWord(_l, s) => {
let c = Constant::from_string(&s); let c = Constant::from_string(&s);
if c.is_some() { return Ok(Token::Constant(c.unwrap())); } if c.is_some() { return Ok(Expression::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(Expression::Quantity(c.unwrap())); }
let c = context.get_variable(&s); let c = context.get_variable(&s);
if c.is_some() { return Ok(Token::Variable(s)); } if c.is_some() { return Ok(Expression::Variable(s)); }
return Ok(Token::Variable(s)); return Ok(Expression::Variable(s));
} }
PreToken::Container(v) => { return Ok(v); } Token::Container(v) => { return Ok(v); }
PreToken::PreOperator(_,_) Token::PreOperator(_,_)
| PreToken::PreGroupStart(_) | Token::PreGroupStart(_)
| PreToken::PreGroupEnd(_) | Token::PreGroupEnd(_)
| PreToken::PreGroup(_, _) | Token::PreGroup(_, _)
=> panic!() => panic!()
}; };
} }