diff --git a/src/parse.rs b/src/parse.rs index 01471de..83e475e 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -131,7 +131,7 @@ enum Token { enum TokState { Neutral, Number, - Unit, + Unit(bool), } fn tokenize(input: &str) -> Vec { @@ -147,7 +147,7 @@ fn tokenize(input: &str) -> Vec { state = TokState::Number; } else if !c.is_whitespace() { token.push(c); - state = TokState::Unit; + state = TokState::Unit(false); } } TokState::Number => { @@ -157,17 +157,23 @@ fn tokenize(input: &str) -> Vec { token.push(c); } else { tokens.push(Token::Number(token.trim().to_string())); - state = TokState::Unit; + state = TokState::Unit(false); token = String::new(); token.push(c); } } - TokState::Unit => { - if c.is_ascii_digit() || c == '-' { + TokState::Unit(after_caret) => { + if !after_caret && (c.is_ascii_digit() || c == '-') { tokens.push(Token::Unit(token.trim().to_string())); state = TokState::Number; token = String::new(); token.push(c); + } else if c == '^' { + token.push(c); + state = TokState::Unit(true); + } else if c.is_whitespace() { + token.push(c); + state = TokState::Unit(false); } else { token.push(c); } @@ -178,7 +184,7 @@ fn tokenize(input: &str) -> Vec { match state { TokState::Neutral => { assert!(token.len() == 0); } TokState::Number => { tokens.push(Token::Number(token.trim().to_string())); } - TokState::Unit => { tokens.push(Token::Unit(token.trim().to_string())); } + TokState::Unit(_) => { tokens.push(Token::Unit(token.trim().to_string())); } } tokens @@ -338,5 +344,31 @@ mod test { Token::Number("2".to_string()), ] ); + assert_eq!( + tokenize("ft^2"), + vec![ + Token::Unit("ft^2".to_string()), + ] + ); + assert_eq!( + tokenize("ft^22"), + vec![ + Token::Unit("ft^22".to_string()), + ] + ); + assert_eq!( + tokenize("ft^2 2"), + vec![ + Token::Unit("ft^2".to_string()), + Token::Number("2".to_string()), + ] + ); + assert_eq!( + tokenize("ft^2 s^-1 lb 2"), + vec![ + Token::Unit("ft^2 s^-1 lb".to_string()), + Token::Number("2".to_string()), + ] + ); } }