Fix parsing of numbers with internal spaces

This commit is contained in:
Juhani Krekelä 2023-05-28 18:07:28 +03:00
parent 188df1fa5c
commit 54118ca879
1 changed files with 24 additions and 3 deletions

View File

@ -21,9 +21,9 @@ pub fn parse(input: &str) -> Result<Vec<NonMetricQuantity>, 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<Vec<NonMetricQuantity>, ParseError> {
Ok(quantities)
}
fn parse_number(input: &str) -> Option<f64> {
let no_whitespace: String = input.chars().filter(|c| !c.is_whitespace()).collect();
no_whitespace.parse().ok()
}
fn parse_unit(input: &str) -> Option<NonMetric> {
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!(