mirror of
				https://github.com/rm-dr/daisy
				synced 2025-10-30 22:14:55 -07:00 
			
		
		
		
	Cleanup
This commit is contained in:
		| @ -8,17 +8,7 @@ use crate::context::Context; | ||||
|  | ||||
| pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut Context) -> Result<Option<Expression>, EvalError> { | ||||
| 	match op { | ||||
|  | ||||
| 		// 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::Function(_) => unreachable!("Functions are handled seperately."), | ||||
|  | ||||
| 		Operator::Define => { | ||||
| 			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); } | ||||
| 		}, | ||||
|  | ||||
| 		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 => { | ||||
| 			let mut sum: Quantity; | ||||
| 			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))); | ||||
| 		}, | ||||
|  | ||||
| 		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 => { | ||||
| 			let mut prod = Quantity::new_rational(1f64).unwrap(); | ||||
| 			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); } | ||||
| 		}, | ||||
|  | ||||
| 		Operator::UnitConvert | ||||
| 		=> { | ||||
| 		Operator::UnitConvert => { | ||||
| 			if args.len() != 2 { panic!() }; | ||||
| 			let a = &args[0]; | ||||
| 			let b = &args[1]; | ||||
| @ -123,6 +132,19 @@ pub fn eval_operator(op: &Operator, args: &VecDeque<Expression>, context: &mut C | ||||
| 			} 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 => { | ||||
| 			if args.len() != 2 {panic!()}; | ||||
| 			let a = &args[0]; | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| use std::cmp::Ordering; | ||||
| use std::collections::VecDeque; | ||||
| use crate::quantity::Quantity; | ||||
|  | ||||
| use super::Expression; | ||||
| use super::Function; | ||||
| @ -29,9 +28,6 @@ pub enum Operator { | ||||
| 	Factorial, | ||||
|  | ||||
| 	Function(Function), | ||||
|  | ||||
| 	// Not accessible from prompt | ||||
| 	Flip, | ||||
| } | ||||
|  | ||||
| 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)] | ||||
| 	fn add_parens_to_arg(&self, arg: &Expression) -> String { | ||||
| 		let mut astr: String = arg.to_string(); | ||||
| @ -199,11 +132,6 @@ impl Operator { | ||||
|  | ||||
| 	pub fn print(&self, args: &VecDeque<Expression>) -> String { | ||||
| 		match self { | ||||
| 			Operator::ImplicitMultiply | | ||||
| 			Operator::Sqrt | | ||||
| 			Operator::Divide | | ||||
| 			Operator::Subtract => { panic!() } | ||||
|  | ||||
| 			Operator::Define => { | ||||
| 				return format!( | ||||
| 					"{} = {}", | ||||
| @ -212,14 +140,17 @@ impl Operator { | ||||
| 				); | ||||
| 			}, | ||||
|  | ||||
| 			Operator::Flip => { | ||||
| 				return format!("{}⁻¹", Operator::Divide.add_parens_to_arg(&args[0])); | ||||
| 			}, | ||||
|  | ||||
| 			Operator::Negative => { | ||||
| 				return format!("-{}", self.add_parens_to_arg(&args[0])); | ||||
| 			}, | ||||
|  | ||||
| 			Operator::Sqrt => { | ||||
| 				return format!( | ||||
| 					"√{}", | ||||
| 					self.add_parens_to_arg(&args[0]), | ||||
| 				); | ||||
| 			}, | ||||
|  | ||||
| 			Operator::ModuloLong => { | ||||
| 				return format!( | ||||
| 					"{} 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 => { | ||||
| 				return format!( | ||||
| 					"{}^{}", | ||||
| @ -265,50 +204,17 @@ impl Operator { | ||||
| 			}, | ||||
|  | ||||
| 			Operator::Add => { | ||||
| 				let a = &args[0]; | ||||
|  | ||||
| 				let b; let sub; | ||||
| 				if let Expression::Operator(o, ar) = &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) | ||||
| 					); | ||||
| 				} | ||||
| 				return format!( | ||||
| 					"{} + {}", | ||||
| 					self.add_parens_to_arg(&args[0]), | ||||
| 					self.add_parens_to_arg(&args[1]) | ||||
| 				); | ||||
| 			}, | ||||
|  | ||||
| 			Operator::ImplicitMultiply | | ||||
| 			Operator::Multiply => { | ||||
| 				let a = &args[0]; | ||||
|  | ||||
| 				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) | ||||
| 					); | ||||
| 				} | ||||
|  | ||||
| 				let b = &args[1]; | ||||
|  | ||||
| 				// Omit times sign when we have a number | ||||
| 				// 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) => { | ||||
| 				return format!("{}({})", s.to_string(), args[0].to_string()); | ||||
| 			} | ||||
|  | ||||
| @ -26,7 +26,7 @@ pub fn find_subs( | ||||
| 		let mut t = g.pop_back().unwrap(); | ||||
|  | ||||
| 		let target: Option<&str> = match &mut t { | ||||
| 			Token::PreOperator(_, s) => { | ||||
| 			Token::Operator(_, s) => { | ||||
| 				let target = match &s[..] { | ||||
| 					"*" => {Some("×")}, | ||||
| 					"/" => {Some("÷")}, | ||||
| @ -41,7 +41,7 @@ pub fn find_subs( | ||||
| 				target | ||||
| 			}, | ||||
|  | ||||
| 			Token::PreWord(_, s) => { | ||||
| 			Token::Word(_, s) => { | ||||
| 				let target = match &s[..] { | ||||
| 					// Greek letters | ||||
| 					"alpha"   => {Some("α")}, | ||||
|  | ||||
| @ -19,10 +19,10 @@ fn lookback_signs( | ||||
| 		if i == 0 { | ||||
| 			let a: Token = g.remove(i).unwrap(); | ||||
| 			match &a { | ||||
| 				Token::PreOperator(l,o) | ||||
| 				Token::Operator(l,o) | ||||
| 				=> { | ||||
| 					if o == "-" { | ||||
| 						g.insert(i, Token::PreOperator(*l, String::from("neg"))); | ||||
| 						g.insert(i, Token::Operator(*l, String::from("neg"))); | ||||
| 					} else if o == "+" { | ||||
| 						continue; // We should not increment i if we remove a token | ||||
| 					} else {g.insert(i, a);} | ||||
| @ -35,7 +35,7 @@ fn lookback_signs( | ||||
| 			let b: Token = g.remove(i-1).unwrap(); | ||||
|  | ||||
| 			match (&a, &b) { | ||||
| 				(Token::PreOperator(_, sa), Token::PreOperator(l,sb)) | ||||
| 				(Token::Operator(_, sa), Token::Operator(l,sb)) | ||||
| 				=> { | ||||
| 					if { | ||||
| 						let o = Operator::from_string(sa); | ||||
| @ -47,7 +47,7 @@ fn lookback_signs( | ||||
| 						) | ||||
| 					} { | ||||
| 						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); | ||||
| 						} else if sb == "+" { | ||||
| 							g.insert(i-1, a); | ||||
| @ -71,7 +71,7 @@ fn lookback_signs( | ||||
| 		let b: Token = g.remove(i-1).unwrap(); | ||||
|  | ||||
| 		match (&a, &b) { | ||||
| 			(Token::PreOperator(_,sa), Token::PreOperator(_,sb)) | ||||
| 			(Token::Operator(_,sa), Token::Operator(_,sb)) | ||||
| 			=> { | ||||
| 				if !((sa == "neg") && (sb == "neg")) { | ||||
| 					g.insert(i-1, b); | ||||
| @ -108,19 +108,19 @@ fn lookback( | ||||
|  | ||||
| 			match (&a, &b) { | ||||
| 				// Insert ImplicitMultiply | ||||
| 				(Token::PreGroup(_,_), Token::PreGroup(l ,_)) | ||||
| 				| (Token::PreGroup(_,_), Token::PreQuantity(l,_)) | ||||
| 				| (Token::PreQuantity(_,_), Token::PreGroup(l,_)) | ||||
| 				| (Token::PreGroup(_,_), Token::PreWord(l,_)) | ||||
| 				| (Token::PreWord(_,_), Token::PreGroup(l,_)) | ||||
| 				| (Token::PreQuantity(_,_), Token::PreWord(l,_)) | ||||
| 				| (Token::PreWord(_,_), Token::PreQuantity(l,_)) | ||||
| 				| (Token::PreWord(_,_), Token::PreWord(l,_)) | ||||
| 				(Token::Group(_,_), Token::Group(l ,_)) | ||||
| 				| (Token::Group(_,_), Token::Quantity(l,_)) | ||||
| 				| (Token::Quantity(_,_), Token::Group(l,_)) | ||||
| 				| (Token::Group(_,_), Token::Word(l,_)) | ||||
| 				| (Token::Word(_,_), Token::Group(l,_)) | ||||
| 				| (Token::Quantity(_,_), Token::Word(l,_)) | ||||
| 				| (Token::Word(_,_), Token::Quantity(l,_)) | ||||
| 				| (Token::Word(_,_), Token::Word(l,_)) | ||||
| 				=> { | ||||
| 					let loc = LineLocation{pos: l.pos-1, len: 0}; | ||||
|  | ||||
| 					g.insert(i-1, b); | ||||
| 					g.insert(i-1, Token::PreOperator( | ||||
| 					g.insert(i-1, Token::Operator( | ||||
| 						loc, | ||||
| 						String::from("i*") | ||||
| 					)); | ||||
| @ -128,9 +128,9 @@ fn lookback( | ||||
| 				}, | ||||
|  | ||||
| 				// Insert implicit multiplications for right-unary operators | ||||
| 				(Token::PreQuantity(_,_), Token::PreOperator(l,s)) | ||||
| 				| (Token::PreGroup(_,_), Token::PreOperator(l,s)) | ||||
| 				| (Token::PreWord(_,_), Token::PreOperator(l,s)) | ||||
| 				(Token::Quantity(_,_), Token::Operator(l,s)) | ||||
| 				| (Token::Group(_,_), Token::Operator(l,s)) | ||||
| 				| (Token::Word(_,_), Token::Operator(l,s)) | ||||
| 				=> { | ||||
| 					let o = Operator::from_string(s); | ||||
| 					let loc = LineLocation{pos: l.pos-1, len: 0}; | ||||
| @ -139,7 +139,7 @@ fn lookback( | ||||
| 					if o.is_some() { | ||||
| 						let o = o.unwrap(); | ||||
| 						if (!o.is_binary()) && (!o.is_left_associative()) { | ||||
| 							g.insert(i-1, Token::PreOperator( | ||||
| 							g.insert(i-1, Token::Operator( | ||||
| 								loc, | ||||
| 								String::from("i*") | ||||
| 							)); | ||||
| @ -149,9 +149,9 @@ fn lookback( | ||||
| 				}, | ||||
|  | ||||
| 				// Insert implicit multiplications for left-unary operators. | ||||
| 				(Token::PreOperator(_,s), Token::PreQuantity(l,_)) | ||||
| 				| (Token::PreOperator(_,s), Token::PreGroup(l,_)) | ||||
| 				| (Token::PreOperator(_,s), Token::PreWord(l,_)) | ||||
| 				(Token::Operator(_,s), Token::Quantity(l,_)) | ||||
| 				| (Token::Operator(_,s), Token::Group(l,_)) | ||||
| 				| (Token::Operator(_,s), Token::Word(l,_)) | ||||
| 				=> { | ||||
| 					let o = Operator::from_string(s); | ||||
| 					let loc = LineLocation{pos: l.pos-1, len: 0}; | ||||
| @ -160,7 +160,7 @@ fn lookback( | ||||
| 					if o.is_some() { | ||||
| 						let o = o.unwrap(); | ||||
| 						if (!o.is_binary()) && o.is_left_associative() { | ||||
| 							g.insert(i-1, Token::PreOperator( | ||||
| 							g.insert(i-1, Token::Operator( | ||||
| 								loc, | ||||
| 								String::from("i*") | ||||
| 							)); | ||||
| @ -170,7 +170,7 @@ fn lookback( | ||||
| 				}, | ||||
|  | ||||
| 				// The following are syntax errors | ||||
| 				(Token::PreQuantity(la,_), Token::PreQuantity(lb,_)) | ||||
| 				(Token::Quantity(la,_), Token::Quantity(lb,_)) | ||||
| 				=> { | ||||
| 					return Err(( | ||||
| 						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(); | ||||
|  | ||||
| 		match t { | ||||
| 			Token::PreGroupStart(l) => { | ||||
| 			Token::GroupStart(l) => { | ||||
| 				levels.push((l, VecDeque::with_capacity(8))); | ||||
| 				i_level += 1; | ||||
| 			}, | ||||
|  | ||||
| 			Token::PreGroupEnd(l) => { | ||||
| 			Token::GroupEnd(l) => { | ||||
| 				let l = LineLocation { | ||||
| 					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(); | ||||
| 				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)) } | ||||
| 		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(); | ||||
| 	lookback(&mut v)?; | ||||
|  | ||||
| 	return Ok(Token::PreGroup(LineLocation{pos:0, len:0}, v)); | ||||
| 	return Ok(Token::Group(LineLocation{pos:0, len:0}, v)); | ||||
| } | ||||
| @ -14,11 +14,11 @@ fn push_token(g: &mut VecDeque<Token>, t: Option<Token>, stop_i: usize) { | ||||
| 	let mut t = t.unwrap(); | ||||
|  | ||||
| 	match t { | ||||
| 		Token::PreGroupStart(ref mut l) | ||||
| 		| Token::PreGroupEnd(ref mut l) | ||||
| 		| Token::PreOperator(ref mut l, _) | ||||
| 		| Token::PreQuantity(ref mut l, _) | ||||
| 		| Token::PreWord(ref mut l, _) | ||||
| 		Token::GroupStart(ref mut l) | ||||
| 		| Token::GroupEnd(ref mut l) | ||||
| 		| Token::Operator(ref mut l, _) | ||||
| 		| Token::Quantity(ref mut l, _) | ||||
| 		| Token::Word(ref mut l, _) | ||||
| 		=> { | ||||
| 			*l = LineLocation{ | ||||
| 				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(_) | ||||
| 		=> 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. | ||||
| 	// 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..]; | ||||
| 		if last == "e" { | ||||
| 			g.push_back(Token::PreQuantity( | ||||
| 			g.push_back(Token::Quantity( | ||||
| 				LineLocation { pos: l.pos, len: l.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 }, | ||||
| 				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. | ||||
| 	if let Token::PreWord(l, s) = &t { | ||||
| 	if let Token::Word(l, s) = &t { | ||||
| 		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 { | ||||
| 					// If we're already building a number, | ||||
| 					// append. | ||||
| 					Some(Token::PreQuantity(_, val)) => { | ||||
| 					Some(Token::Quantity(_, val)) => { | ||||
| 						val.push(if c == ',' {'.'} else {c}); | ||||
| 					}, | ||||
|  | ||||
| @ -82,7 +82,7 @@ pub fn tokenize(input: &String) -> VecDeque<Token> { | ||||
| 					// previous token and start one. | ||||
| 					_ => { | ||||
| 						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. | ||||
| 			'e' => { | ||||
| 				match &mut t { | ||||
| 					Some(Token::PreWord(_, val)) => { val.push(c); }, | ||||
| 					Some(Token::PreQuantity(_, val)) => { val.push(c); }, | ||||
| 					Some(Token::Word(_, val)) => { val.push(c); }, | ||||
| 					Some(Token::Quantity(_, val)) => { val.push(c); }, | ||||
|  | ||||
| 					_ => { | ||||
| 						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. | ||||
| 			'-' | '+' => { | ||||
| 				match &mut t { | ||||
| 					Some(Token::PreQuantity(_, val)) => { | ||||
| 					Some(Token::Quantity(_, val)) => { | ||||
| 						if &val[val.len()-1..] == "e" { | ||||
| 							// If the current number ends in an `e`, | ||||
| 							// this negative specifies a negative exponent | ||||
| @ -116,7 +116,7 @@ pub fn tokenize(input: &String) -> VecDeque<Token> { | ||||
| 							// Otherwise, end the number. | ||||
| 							// We probably have a subtraction. | ||||
| 							push_token(&mut g, t, i); | ||||
| 							t = Some(Token::PreOperator( | ||||
| 							t = Some(Token::Operator( | ||||
| 								LineLocation{pos: i, len: 1}, | ||||
| 								String::from(c) | ||||
| 							)); | ||||
| @ -126,7 +126,7 @@ pub fn tokenize(input: &String) -> VecDeque<Token> { | ||||
| 					// This may be a negative or a subtraction | ||||
| 					_ => { | ||||
| 						push_token(&mut g, t, i); | ||||
| 						t = Some(Token::PreOperator( | ||||
| 						t = Some(Token::Operator( | ||||
| 							LineLocation{pos: i, len: 1}, | ||||
| 							String::from(c) | ||||
| 						)); | ||||
| @ -139,10 +139,10 @@ pub fn tokenize(input: &String) -> VecDeque<Token> { | ||||
| 			'^'|'!'|'%'|'=' | ||||
| 			=> { | ||||
| 				match &mut t { | ||||
| 					Some(Token::PreOperator(_, val)) => { val.push(c); }, | ||||
| 					Some(Token::Operator(_, val)) => { val.push(c); }, | ||||
| 					_ => { | ||||
| 						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 | ||||
| 			'(' => { | ||||
| 				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); | ||||
| 				t = Some(Token::PreGroupEnd(LineLocation{pos: i, len: 0})); | ||||
| 				t = Some(Token::GroupEnd(LineLocation{pos: i, len: 0})); | ||||
| 			}, | ||||
|  | ||||
| 			// Space. Basic seperator. | ||||
| @ -166,11 +166,11 @@ pub fn tokenize(input: &String) -> VecDeque<Token> { | ||||
| 			// Word | ||||
| 			_ => { | ||||
| 				match &mut t { | ||||
| 					Some(Token::PreWord(_, val)) => { val.push(c); }, | ||||
| 					Some(Token::Word(_, val)) => { val.push(c); }, | ||||
|  | ||||
| 					_ => { | ||||
| 						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))); | ||||
| 					} | ||||
| 				}; | ||||
| 			} | ||||
|  | ||||
| @ -20,7 +20,7 @@ fn treeify_binary( | ||||
| 	if i == 0 { | ||||
| 		// This binary operator is at the end of an expression. | ||||
| 		let l = match this { | ||||
| 			Token::PreOperator(l, _) => l, | ||||
| 			Token::Operator(l, _) => l, | ||||
| 			_ => panic!() | ||||
| 		}; | ||||
| 		return Err((*l, ParserError::Syntax)); | ||||
| @ -32,7 +32,7 @@ fn treeify_binary( | ||||
| 			&g_inner[i-1] | ||||
| 		} else { | ||||
| 			let l = match this { | ||||
| 				Token::PreOperator(l, _) => l, | ||||
| 				Token::Operator(l, _) => l, | ||||
| 				_ => panic!() | ||||
| 			}; | ||||
| 			return Err((*l, ParserError::Syntax)); | ||||
| @ -44,7 +44,7 @@ fn treeify_binary( | ||||
| 			&g_inner[i+1] | ||||
| 		} else { | ||||
| 			let l = match this { | ||||
| 				Token::PreOperator(l, _) => l, | ||||
| 				Token::Operator(l, _) => l, | ||||
| 				_ => panic!() | ||||
| 			}; | ||||
| 			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); | ||||
| 		if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 		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); | ||||
| 		if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 		let o = o.unwrap(); | ||||
| @ -96,7 +96,7 @@ fn treeify_binary( | ||||
|  | ||||
| 	// This operator | ||||
| 	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); | ||||
| 		if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 		o.unwrap() | ||||
| @ -104,14 +104,14 @@ fn treeify_binary( | ||||
|  | ||||
| 	// The operators contesting our arguments | ||||
| 	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); | ||||
| 		if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 		Some(o.unwrap()) | ||||
| 	} else { None }; | ||||
|  | ||||
| 	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); | ||||
| 		if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 		Some(o.unwrap()) | ||||
| @ -127,11 +127,11 @@ fn treeify_binary( | ||||
| 		let this_pre = g_inner.remove(i-1).unwrap(); | ||||
| 		let right_pre = g_inner.remove(i-1).unwrap(); | ||||
| 		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::PreGroup(_, _) = left_pre { left = treeify(left_pre, context)?; } else {left = left_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::Group(_, _) = left_pre { left = treeify(left_pre, context)?; } else {left = left_pre.to_expression(context)?;} | ||||
|  | ||||
| 		let o = { | ||||
| 			let Token::PreOperator(_, s) = this_pre else {panic!()}; | ||||
| 			let Token::Operator(_, s) = this_pre else {panic!()}; | ||||
| 			let o = Operator::from_string(&s); | ||||
| 			if o.is_none() { panic!() } | ||||
| 			o.unwrap() | ||||
| @ -141,7 +141,7 @@ fn treeify_binary( | ||||
| 		new_token_args.push_back(left); | ||||
| 		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); | ||||
| 	} else { | ||||
| @ -164,7 +164,7 @@ fn treeify_unary( | ||||
| 				&g_inner[i-1] | ||||
| 			} else { | ||||
| 				let l = match this { | ||||
| 					Token::PreOperator(l, _) => l, | ||||
| 					Token::Operator(l, _) => l, | ||||
| 					_ => panic!() | ||||
| 				}; | ||||
| 				return Err((*l, ParserError::Syntax)); | ||||
| @ -176,7 +176,7 @@ fn treeify_unary( | ||||
| 				&g_inner[i+1] | ||||
| 			} else { | ||||
| 				let l = match this { | ||||
| 					Token::PreOperator(l, _) => l, | ||||
| 					Token::Operator(l, _) => l, | ||||
| 					_ => panic!() | ||||
| 				}; | ||||
| 				return Err((*l, ParserError::Syntax)); | ||||
| @ -194,7 +194,7 @@ fn treeify_unary( | ||||
| 	} | ||||
|  | ||||
| 	if prev.is_some() { | ||||
| 		if let Token::PreOperator(_,_) = prev.unwrap() { | ||||
| 		if let Token::Operator(_,_) = prev.unwrap() { | ||||
| 		} else { | ||||
| 			return Err(( | ||||
| 				*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(); | ||||
| 		return Err(( | ||||
| 			LineLocation{pos: tl.pos, len: l.pos - tl.pos + l.len}, | ||||
| @ -214,7 +214,7 @@ fn treeify_unary( | ||||
|  | ||||
| 		// This operator | ||||
| 		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); | ||||
| 			if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 			o.unwrap() | ||||
| @ -223,14 +223,14 @@ fn treeify_unary( | ||||
| 		// The operator contesting our argument | ||||
| 		let next_op = if left_associative { | ||||
| 			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); | ||||
| 				if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 				Some(o.unwrap()) | ||||
| 			} else { None } | ||||
| 		} else { | ||||
| 			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); | ||||
| 				if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 				Some(o.unwrap()) | ||||
| @ -245,10 +245,10 @@ fn treeify_unary( | ||||
| 			} else { | ||||
| 				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 Token::PreOperator(_, s) = this_pre else {panic!()}; | ||||
| 				let Token::Operator(_, s) = this_pre else {panic!()}; | ||||
| 				let o = Operator::from_string(&s); | ||||
| 				if o.is_none() { panic!() } | ||||
| 				o.unwrap() | ||||
| @ -258,9 +258,9 @@ fn treeify_unary( | ||||
| 			new_token_args.push_back(next); | ||||
|  | ||||
| 			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 { | ||||
| 				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); | ||||
| @ -279,7 +279,7 @@ pub fn treeify( | ||||
| ) -> Result<Expression, (LineLocation, ParserError)> { | ||||
|  | ||||
| 	let g_inner: &mut VecDeque<Token> = match g { | ||||
| 		Token::PreGroup(_, ref mut x) => x, | ||||
| 		Token::Group(_, ref mut x) => x, | ||||
| 		_ => panic!() | ||||
| 	}; | ||||
|  | ||||
| @ -297,10 +297,10 @@ pub fn treeify( | ||||
|  | ||||
| 		let i = j as usize; | ||||
|  | ||||
| 		// Convert preoperators | ||||
| 		// Convert operators | ||||
| 		// If not an operator, move on. | ||||
| 		let this_op = match &g_inner[i] { | ||||
| 			Token::PreOperator(l, s) => { | ||||
| 			Token::Operator(l, s) => { | ||||
| 				let o = Operator::from_string(&s); | ||||
| 				if o.is_none() { return Err((*l, ParserError::Syntax)); } | ||||
| 				o.unwrap() | ||||
| @ -342,10 +342,10 @@ pub fn treeify( | ||||
| 	let g = g_inner.pop_front().unwrap(); | ||||
| 	return match g { | ||||
| 		// Catch edge cases | ||||
| 		Token::PreOperator(l, _) => { | ||||
| 		Token::Operator(l, _) => { | ||||
| 			Err((l, ParserError::Syntax)) | ||||
| 		}, | ||||
| 		Token::PreGroup(_,_) => { | ||||
| 		Token::Group(_,_) => { | ||||
| 			treeify(g, context) | ||||
| 		}, | ||||
|  | ||||
|  | ||||
| @ -13,14 +13,15 @@ use super::{ | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub enum Token { | ||||
| 	PreQuantity(LineLocation, String), | ||||
| 	PreWord(LineLocation, String), | ||||
| 	PreOperator(LineLocation, String), | ||||
| 	Quantity(LineLocation, String), | ||||
| 	Word(LineLocation, String), | ||||
| 	Operator(LineLocation, String), | ||||
|  | ||||
| 	PreGroupStart(LineLocation), | ||||
| 	PreGroupEnd(LineLocation), | ||||
| 	PreGroup(LineLocation, VecDeque<Token>), | ||||
| 	GroupStart(LineLocation), | ||||
| 	GroupEnd(LineLocation), | ||||
| 	Group(LineLocation, VecDeque<Token>), | ||||
|  | ||||
| 	// Never parsed from input, used to build a tree. | ||||
| 	Container(Expression) | ||||
| } | ||||
|  | ||||
| @ -28,37 +29,37 @@ impl Token { | ||||
| 	#[inline(always)] | ||||
| 	pub fn get_line_location(&self) -> &LineLocation { | ||||
| 		match self { | ||||
| 			Token::PreQuantity(l, _) | ||||
| 			| Token::PreWord(l, _) | ||||
| 			| Token::PreOperator(l, _) | ||||
| 			| Token::PreGroupStart(l) | ||||
| 			| Token::PreGroupEnd(l) | ||||
| 			| Token::PreGroup(l, _) | ||||
| 			Token::Quantity(l, _) | ||||
| 			| Token::Word(l, _) | ||||
| 			| Token::Operator(l, _) | ||||
| 			| Token::GroupStart(l) | ||||
| 			| Token::GroupEnd(l) | ||||
| 			| Token::Group(l, _) | ||||
| 			=> l, | ||||
|  | ||||
| 			_ => panic!() | ||||
| 			Token::Container(_) => panic!("Containers do not have a linelocation.") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	#[inline(always)] | ||||
| 	pub fn get_mut_line_location(&mut self) -> &mut LineLocation { | ||||
| 		match self { | ||||
| 			Token::PreQuantity(l, _) | ||||
| 			| Token::PreWord(l, _) | ||||
| 			| Token::PreOperator(l, _) | ||||
| 			| Token::PreGroupStart(l) | ||||
| 			| Token::PreGroupEnd(l) | ||||
| 			| Token::PreGroup(l, _) | ||||
| 			Token::Quantity(l, _) | ||||
| 			| Token::Word(l, _) | ||||
| 			| Token::Operator(l, _) | ||||
| 			| Token::GroupStart(l) | ||||
| 			| Token::GroupEnd(l) | ||||
| 			| Token::Group(l, _) | ||||
| 			=> l, | ||||
|  | ||||
| 			_ => panic!() | ||||
| 			Token::Container(_) => panic!("Containers do not have a linelocation.") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	#[inline(always)] | ||||
| 	pub fn to_expression(self, context: &Context) -> Result<Expression, (LineLocation, ParserError)>{ | ||||
| 		match self { | ||||
| 			Token::PreQuantity(l, mut s) => { | ||||
| 			Token::Quantity(l, mut s) => { | ||||
|  | ||||
| 				// The length check here ensures that | ||||
| 				// `.` is not parsed as `0.` | ||||
| @ -76,7 +77,7 @@ impl Token { | ||||
| 				return Ok(Expression::Quantity(r.unwrap())); | ||||
| 			}, | ||||
|  | ||||
| 			Token::PreWord(_l, s) => { | ||||
| 			Token::Word(_l, s) => { | ||||
|  | ||||
| 				let c = Constant::from_string(&s); | ||||
| 				if c.is_some() { return Ok(Expression::Constant(c.unwrap())); } | ||||
| @ -91,10 +92,10 @@ impl Token { | ||||
|  | ||||
| 			Token::Container(v) => { return Ok(v); } | ||||
|  | ||||
| 			Token::PreOperator(_,_) | ||||
| 			| Token::PreGroupStart(_) | ||||
| 			| Token::PreGroupEnd(_) | ||||
| 			| Token::PreGroup(_, _) | ||||
| 			Token::Operator(_,_) | ||||
| 			| Token::GroupStart(_) | ||||
| 			| Token::GroupEnd(_) | ||||
| 			| Token::Group(_, _) | ||||
| 			=> panic!() | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
		Reference in New Issue
	
	Block a user