Auto convert temp units to kelvin before sending to the AST parser

This commit is contained in:
2024-12-01 20:55:10 -07:00
parent 4ec3278296
commit bce9a55721
2 changed files with 33 additions and 15 deletions

View File

@@ -339,14 +339,11 @@ impl Tokenizer {
'f' => Temperature::Fahrenheit(number), 'f' => Temperature::Fahrenheit(number),
'k' => Temperature::Kelvin(number), 'k' => Temperature::Kelvin(number),
_ => return Ok(Token::new(TokenType::Number(number), line, column)), _ => return Ok(Token::new(TokenType::Number(number), line, column)),
}; }
.to_kelvin();
self.next_char()?; self.next_char()?;
Ok(Token::new( Ok(Token::new(TokenType::Number(temperature), line, column))
TokenType::Temperature(temperature),
line,
column,
))
} else { } else {
Ok(Token::new(TokenType::Number(number), line, column)) Ok(Token::new(TokenType::Number(number), line, column))
} }
@@ -632,28 +629,25 @@ mod tests {
#[test] #[test]
fn test_temperature_unit() -> Result<()> { fn test_temperature_unit() -> Result<()> {
let mut tokenizer = Tokenizer::from(String::from("10c 10f 10k")); let mut tokenizer = Tokenizer::from(String::from("10c 14f 10k"));
let token = tokenizer.next_token()?.unwrap(); let token = tokenizer.next_token()?.unwrap();
assert_eq!( assert_eq!(
token.token_type, token.token_type,
TokenType::Temperature(Temperature::Celsius(Number::Integer(10))) TokenType::Number(Number::Decimal(Decimal::new(28315, 2)))
); );
let token = tokenizer.next_token()?.unwrap(); let token = tokenizer.next_token()?.unwrap();
assert_eq!( assert_eq!(
token.token_type, token.token_type,
TokenType::Temperature(Temperature::Fahrenheit(Number::Integer(10))) TokenType::Number(Number::Decimal(Decimal::new(26315, 2)))
); );
let token = tokenizer.next_token()?.unwrap(); let token = tokenizer.next_token()?.unwrap();
assert_eq!( assert_eq!(token.token_type, TokenType::Number(Number::Integer(10)));
token.token_type,
TokenType::Temperature(Temperature::Kelvin(Number::Integer(10)))
);
Ok(()) Ok(())
} }

View File

@@ -1,3 +1,4 @@
use rust_decimal::prelude::*;
use rust_decimal::Decimal; use rust_decimal::Decimal;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
@@ -37,6 +38,31 @@ impl std::fmt::Display for Temperature {
} }
} }
impl Temperature {
pub fn to_kelvin(self) -> Number {
match self {
Temperature::Celsius(n) => {
let n = match n {
Number::Integer(i) => Decimal::new(i as i64, 0),
Number::Decimal(d) => d,
};
Number::Decimal(n + Decimal::new(27315, 2))
}
Temperature::Fahrenheit(n) => {
let n = match n {
Number::Integer(i) => Decimal::new(i as i64, 0),
Number::Decimal(d) => d,
};
let a = n - Decimal::new(32, 0);
let b = Decimal::new(5, 0) / Decimal::new(9, 0);
Number::Decimal(a * b + Decimal::new(27315, 2))
}
Temperature::Kelvin(n) => n,
}
}
}
#[derive(Debug, PartialEq, Hash, Eq, Clone)] #[derive(Debug, PartialEq, Hash, Eq, Clone)]
pub enum TokenType { pub enum TokenType {
/// Represents a string token /// Represents a string token
@@ -51,7 +77,6 @@ pub enum TokenType {
Identifier(String), Identifier(String),
/// Represents a symbol token /// Represents a symbol token
Symbol(Symbol), Symbol(Symbol),
Temperature(Temperature),
/// Represents an end of file token /// Represents an end of file token
EOF, EOF,
} }
@@ -65,7 +90,6 @@ impl std::fmt::Display for TokenType {
TokenType::Keyword(k) => write!(f, "{:?}", k), TokenType::Keyword(k) => write!(f, "{:?}", k),
TokenType::Identifier(i) => write!(f, "{}", i), TokenType::Identifier(i) => write!(f, "{}", i),
TokenType::Symbol(s) => write!(f, "{:?}", s), TokenType::Symbol(s) => write!(f, "{:?}", s),
TokenType::Temperature(t) => write!(f, "{}", t),
TokenType::EOF => write!(f, "EOF"), TokenType::EOF => write!(f, "EOF"),
} }
} }