Compare commits

...

6 Commits

Author SHA1 Message Date
Juhani Krekelä 5d8462c6e4 Add more ways to spell square mile 2023-05-29 22:05:08 +03:00
Juhani Krekelä 8060f79067 Add more ways to spell square feet 2023-05-29 22:03:08 +03:00
Juhani Krekelä e6ec05323f Add more ways to spell square inches 2023-05-29 21:58:29 +03:00
Juhani Krekelä c81ebb80df Add more ways to spell degrees Fahrenheit 2023-05-29 21:52:34 +03:00
Juhani Krekelä 5335e141a4 Allow units to contain nubers after a caret 2023-05-29 21:48:45 +03:00
Juhani Krekelä fbbafcd2ec Allow units to contain spaces 2023-05-29 21:43:02 +03:00
1 changed files with 132 additions and 18 deletions

View File

@ -98,25 +98,65 @@ fn parse_unit(input: String) -> Result<NonMetric, ParseError> {
"st" => Ok(NonMetric::Stone),
// Temperature
"degree Fahrenheit" => Ok(NonMetric::Fahrenheit),
"degrees Fahrenheit" => Ok(NonMetric::Fahrenheit),
"degree fahrenheit" => Ok(NonMetric::Fahrenheit),
"degrees fahrenheit" => Ok(NonMetric::Fahrenheit),
"Fahrenheit" => Ok(NonMetric::Fahrenheit),
"fahrenheit" => Ok(NonMetric::Fahrenheit),
"°F" => Ok(NonMetric::Fahrenheit),
"F" => Ok(NonMetric::Fahrenheit),
// Area
"square inch" => Ok(NonMetric::SquareInch),
"square inches" => Ok(NonMetric::SquareInch),
"square in" => Ok(NonMetric::SquareInch),
"sq inch" => Ok(NonMetric::SquareInch),
"sq inches" => Ok(NonMetric::SquareInch),
"sq in" => Ok(NonMetric::SquareInch),
"inch²" => Ok(NonMetric::SquareInch),
"inches²" => Ok(NonMetric::SquareInch),
"in²" => Ok(NonMetric::SquareInch),
"\"²" => Ok(NonMetric::SquareInch),
"″²" => Ok(NonMetric::SquareInch),
"inch^2" => Ok(NonMetric::SquareInch),
"inches^2" => Ok(NonMetric::SquareInch),
"in^2" => Ok(NonMetric::SquareInch),
"\"^2" => Ok(NonMetric::SquareInch),
"square foot" => Ok(NonMetric::SquareFoot),
"square feet" => Ok(NonMetric::SquareFoot),
"square ft" => Ok(NonMetric::SquareFoot),
"sq foot" => Ok(NonMetric::SquareFoot),
"sq feet" => Ok(NonMetric::SquareFoot),
"sq ft" => Ok(NonMetric::SquareFoot),
"foot²" => Ok(NonMetric::SquareFoot),
"feet²" => Ok(NonMetric::SquareFoot),
"ft²" => Ok(NonMetric::SquareFoot),
"" => Ok(NonMetric::SquareFoot),
"′²" => Ok(NonMetric::SquareFoot),
"foot^2" => Ok(NonMetric::SquareFoot),
"feet^2" => Ok(NonMetric::SquareFoot),
"ft^2" => Ok(NonMetric::SquareFoot),
"'^2" => Ok(NonMetric::SquareFoot),
"sf" => Ok(NonMetric::SquareFoot),
"acre" => Ok(NonMetric::Acre),
"acres" => Ok(NonMetric::Acre),
"ac" => Ok(NonMetric::Acre),
"square mile" => Ok(NonMetric::SquareMile),
"square miles" => Ok(NonMetric::SquareMile),
"square mi" => Ok(NonMetric::SquareMile),
"sq mile" => Ok(NonMetric::SquareMile),
"sq miles" => Ok(NonMetric::SquareMile),
"sq mi" => Ok(NonMetric::SquareMile),
"mile²" => Ok(NonMetric::SquareMile),
"miles²" => Ok(NonMetric::SquareMile),
"mi²" => Ok(NonMetric::SquareMile),
"mile^2" => Ok(NonMetric::SquareMile),
"miles^2" => Ok(NonMetric::SquareMile),
"mi^2" => Ok(NonMetric::SquareMile),
_ => Err(ParseError::UnknownUnit(input)),
}
@ -131,7 +171,7 @@ enum Token {
enum TokState {
Neutral,
Number,
Unit,
Unit(bool),
}
fn tokenize(input: &str) -> Vec<Token> {
@ -147,7 +187,7 @@ fn tokenize(input: &str) -> Vec<Token> {
state = TokState::Number;
} else if !c.is_whitespace() {
token.push(c);
state = TokState::Unit;
state = TokState::Unit(false);
}
}
TokState::Number => {
@ -157,23 +197,25 @@ fn tokenize(input: &str) -> Vec<Token> {
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 == '-' {
tokens.push(Token::Unit(token));
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.is_whitespace() {
} else if c == '^' {
token.push(c);
state = TokState::Unit(true);
} else if c.is_whitespace() {
token.push(c);
state = TokState::Unit(false);
} else {
tokens.push(Token::Unit(token));
state = TokState::Neutral;
token = String::new();
token.push(c);
}
}
}
@ -182,7 +224,7 @@ fn tokenize(input: &str) -> Vec<Token> {
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)); }
TokState::Unit(_) => { tokens.push(Token::Unit(token.trim().to_string())); }
}
tokens
@ -263,25 +305,65 @@ mod test {
assert_eq!(parse_unit("st".to_string()), Ok(NonMetric::Stone));
// Temperature
assert_eq!(parse_unit("degree Fahrenheit".to_string()), Ok(NonMetric::Fahrenheit));
assert_eq!(parse_unit("degrees Fahrenheit".to_string()), Ok(NonMetric::Fahrenheit));
assert_eq!(parse_unit("degree fahrenheit".to_string()), Ok(NonMetric::Fahrenheit));
assert_eq!(parse_unit("degrees fahrenheit".to_string()), Ok(NonMetric::Fahrenheit));
assert_eq!(parse_unit("Fahrenheit".to_string()), Ok(NonMetric::Fahrenheit));
assert_eq!(parse_unit("fahrenheit".to_string()), Ok(NonMetric::Fahrenheit));
assert_eq!(parse_unit("°F".to_string()), Ok(NonMetric::Fahrenheit));
assert_eq!(parse_unit("F".to_string()), Ok(NonMetric::Fahrenheit));
// Area
assert_eq!(parse_unit("square inch".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("square inches".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("square in".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("sq inch".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("sq inches".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("sq in".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("inch²".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("inches²".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("in²".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("\"²".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("″²".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("inch^2".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("inches^2".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("in^2".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("\"^2".to_string()), Ok(NonMetric::SquareInch));
assert_eq!(parse_unit("square foot".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("square feet".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("square ft".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("sq foot".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("sq feet".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("sq ft".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("foot²".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("feet²".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("ft²".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("′²".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("foot^2".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("feet^2".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("ft^2".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("'^2".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("sf".to_string()), Ok(NonMetric::SquareFoot));
assert_eq!(parse_unit("acre".to_string()), Ok(NonMetric::Acre));
assert_eq!(parse_unit("acres".to_string()), Ok(NonMetric::Acre));
assert_eq!(parse_unit("ac".to_string()), Ok(NonMetric::Acre));
assert_eq!(parse_unit("square mile".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("square miles".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("square mi".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("sq mile".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("sq miles".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("sq mi".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("mile²".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("miles²".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("mi²".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("mile^2".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("miles^2".to_string()), Ok(NonMetric::SquareMile));
assert_eq!(parse_unit("mi^2".to_string()), Ok(NonMetric::SquareMile));
// Unknown unit
assert_eq!(parse_unit("hutenosa".to_string()), Err(ParseError::UnknownUnit("hutenosa".to_string())));
@ -304,13 +386,6 @@ mod test {
Token::Unit("ft".to_string()),
]
);
assert_eq!(
tokenize("ft in"),
vec![
Token::Unit("ft".to_string()),
Token::Unit("in".to_string()),
]
);
assert_eq!(
tokenize("5 ft 7 in"),
vec![
@ -336,5 +411,44 @@ mod test {
Token::Unit("lbs".to_string()),
]
);
assert_eq!(
tokenize("sq ft"),
vec![
Token::Unit("sq ft".to_string()),
]
);
assert_eq!(
tokenize("sq ft2"),
vec![
Token::Unit("sq ft".to_string()),
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()),
]
);
}
}