diff --git a/src/parse.rs b/src/parse.rs index c6308bb..4688d51 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -21,9 +21,9 @@ pub fn parse(input: &str) -> Result, ParseError> { for token in tokenize(input) { match (&state, token) { (Expect::Number, Token::Number(number)) => { - let number = match number.trim().parse() { - Ok(number) => number, - Err(_) => { + let number = match parse_number(&number) { + Some(number) => number, + None => { return Err(ParseError::NotValidNumber(number)); } }; @@ -63,6 +63,11 @@ pub fn parse(input: &str) -> Result, ParseError> { Ok(quantities) } +fn parse_number(input: &str) -> Option { + let no_whitespace: String = input.chars().filter(|c| !c.is_whitespace()).collect(); + no_whitespace.parse().ok() +} + fn parse_unit(input: &str) -> Option { match input { // Length @@ -187,6 +192,9 @@ mod test { NonMetricQuantity { amount: 5.0, unit: NonMetric::Foot }, NonMetricQuantity { amount: 8.0, unit: NonMetric::Inch }, ])); + assert_eq!(parse("20 000 lbs"), Ok(vec![ + NonMetricQuantity { amount: 20_000.0, unit: NonMetric::Pound }, + ])); assert_eq!(parse("12.0."), Err(ParseError::NotValidNumber("12.0.".to_string()))); assert_eq!(parse("ft"), Err(ParseError::UnexpectedUnit("ft".to_string()))); @@ -194,6 +202,17 @@ mod test { assert_eq!(parse("12"), Err(ParseError::ExpectedUnit)); } + #[test] + fn numbers() { + assert_eq!(parse_number(""), None); + assert_eq!(parse_number("1"), Some(1.0)); + assert_eq!(parse_number("1.0"), Some(1.0)); + assert_eq!(parse_number("0.1"), Some(0.1)); + assert_eq!(parse_number("0.1."), None); + assert_eq!(parse_number("-10"), Some(-10.0)); + assert_eq!(parse_number("10\t00\u{1680}000"), Some(10_00_000.0)); + } + #[test] fn units() { // Length @@ -243,6 +262,8 @@ mod test { assert_eq!(tokenize("10"), vec![Token::Number("10".to_string())]); assert_eq!(tokenize(" 10 "), vec![Token::Number("10".to_string())]); assert_eq!(tokenize("10 000"), vec![Token::Number("10 000".to_string())]); + assert_eq!(tokenize("10\t000"), vec![Token::Number("10\t000".to_string())]); + assert_eq!(tokenize("10\u{1680}000"), vec![Token::Number("10\u{1680}000".to_string())]); assert_eq!(tokenize("10.0.1"), vec![Token::Number("10.0.1".to_string())]); assert_eq!(tokenize("ft"), vec![Token::Unit("ft".to_string())]); assert_eq!(