diff --git a/src/lexer.rs b/src/lexer.rs index 7627a71..b860fc5 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -589,3 +589,29 @@ pub fn lex(input: &str, allow_trailing_operators: bool, default_degree: Unit) -> Ok(tokens) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::numtok; + + #[test] + fn test_lex() { + pub fn run_lex(input: &str, expected_tokens: Vec) { + let tokens = lex(input, false, Unit::Celsius).unwrap(); + let matching_tokens = tokens.iter().zip(&expected_tokens).filter(|&(a, b)| a == b); + assert_eq!(matching_tokens.count(), expected_tokens.len()); + } + + run_lex("42 millilitres", vec![numtok!(42), Token::Unit(Milliliter)]); + run_lex("50 / 10", vec![numtok!(50), Token::Operator(Divide), numtok!(10)]); + run_lex("33.3 square meters", vec![numtok!(33.3), Token::Unit(SquareMeter)]); + run_lex("101 nautical miles", vec![numtok!(101), Token::Unit(NauticalMile)]); + run_lex("87 sq miles", vec![numtok!(87), Token::Unit(SquareMile)]); + run_lex("1 light year", vec![numtok!(1), Token::Unit(LightYear)]); + run_lex("34 cubic feet + 23 cubic yards", vec![numtok!(34), Token::Unit(CubicFoot), Token::Operator(Plus), numtok!(23), Token::Unit(CubicYard)]); + run_lex("50 metric tonnes", vec![numtok!(50), Token::Unit(MetricTon)]); + run_lex("5432 newton metres", vec![numtok!(5432), Token::Unit(NewtonMeter)]); + run_lex("2345 newton-meters", vec![numtok!(2345), Token::Unit(NewtonMeter)]); + } +} diff --git a/src/lib.rs b/src/lib.rs index f56202e..1c2f4ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,7 +78,7 @@ impl Display for Number { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// Math operators like [`Multiply`](Operator::Multiply), parentheses, etc. pub enum Operator { Plus, @@ -91,21 +91,21 @@ pub enum Operator { RightParen, // lexer only } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// Unary operators like [`Percent`](UnaryOperator::Percent) and [`Factorial`](UnaryOperator::Factorial). pub enum UnaryOperator { Percent, Factorial, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// A Text operator like [`To`](TextOperator::To) or [`Of`](TextOperator::Of). pub enum TextOperator { To, Of, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// A named number like [`Million`](NamedNumber::Million). pub enum NamedNumber { Hundred, @@ -134,14 +134,14 @@ pub enum NamedNumber { Googol, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// A constant like [`Pi`](Constant::Pi) or [`E`](Constant::E). pub enum Constant { Pi, E, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// Functions identifiers like [`Sqrt`](FunctionIdentifier::Sqrt), [`Sin`](FunctionIdentifier::Sin), [`Round`](FunctionIdentifier::Round), etc. pub enum FunctionIdentifier { Sqrt, @@ -161,7 +161,7 @@ pub enum FunctionIdentifier { Tan, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// A temporary enum used by the [`lexer`] to later determine what [`Token`] it is. /// /// For example, when a symbol like `%` is found, the lexer turns it into a @@ -180,7 +180,7 @@ pub enum LexerKeyword { Force, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// A token like a [`Number`](Token::Number), [`Operator`](Token::Operator), [`Unit`](Token::Unit) etc. /// /// Strings can be divided up into these tokens by the [`lexer`], and then put into the [`parser`]. @@ -203,6 +203,13 @@ pub enum Token { Unit(units::Unit), } +#[macro_export] +macro_rules! numtok { + ( $num:literal ) => { + Token::Number(d128!($num)); + } +} + /// Evaluates a string into a resulting [`Number`]. /// /// Example: