From f023d535d56e1f39655814474bb019edc307c80f Mon Sep 17 00:00:00 2001 From: Kasper Date: Fri, 31 Jul 2026 10:01:53 +0200 Subject: [PATCH] Fix parsing of InchOfMercury --- CHANGELOG.md | 1 + src/evaluator.rs | 4 ++++ src/lexer.rs | 48 +++++++++++++++++++++++++----------------------- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79a6880..d9e9096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Add REPL to the `cpc` CLI - Add support for numbers with thousands separators `_`, ` ` and ` ` (thin space) - Format numbers with thousands separator +- Fix parsing of `inch of mercury` ## 4.2.0 - 2026 Jul 1 - Add ambiguous unit resolution depending on context and user locale. diff --git a/src/evaluator.rs b/src/evaluator.rs index fef10cd..89ee33a 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -489,6 +489,10 @@ mod tests { eval_test("1 lbf to newtons", "4.4482216152605 newtons"); results_eq("1 bar to Pa", "100000 Pa"); results_eq("1 kHz to Hz", "1000 Hz"); + results_eq("1 in of mercury", "1 inch of mercury"); + results_eq("1 \" of mercury", "1 inch of mercury"); + results_eq("1 \" of hg", "1 inch of mercury"); + results_eq("1\"hg", "1 inch of mercury"); eval_test( "1 km/h to m/s", "≈ 0.277777777777777777777777777777777777778 meters / second", diff --git a/src/lexer.rs b/src/lexer.rs index bc88bf3..b29118b 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -165,14 +165,8 @@ fn lex_token(lexer: &mut Lexer) -> Result<(), String> { "'" => Token::unit(Foot), "\"" | "“" | "”" | "″" => { lexer.graphemes.next(); - match read_word(lexer).as_str() { - "hg" | "mercury" => Token::unit(InchOfMercury), - other => { - lexer.tokens.push(Token::unit(Inch)); - lex_word_if_non_empty(other, lexer)?; - return Ok(()); - } - } + lex_word(first_grapheme, lexer)?; + return Ok(()); } grapheme => { return Err(format!("Invalid character: {}", grapheme)); @@ -283,8 +277,29 @@ fn lex_word(word: &str, lexer: &mut Lexer) -> Result<(), String> { "dm" | "decimeter" | "decimeters" | "decimetre" | "decimetres" => Token::unit(Decimeter), "m" | "meter" | "meters" | "metre" | "metres" => Token::unit(Meter), "km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Token::unit(Kilometer), - "in" => Token::LexerKeyword(In), - "inch" | "inches" => Token::unit(Inch), + "\"" | "“" | "”" | "″" | "in" | "inch" | "inches" => { + match read_word(lexer).as_str() { + "of" => match read_word(lexer).as_str() { + "hg" | "mercury" => Token::unit(InchOfMercury), + other => { + lexer.tokens.push(Token::unit(Inch)); + lexer.tokens.push(Token::TextOperator(Of)); + lex_word_if_non_empty(other, lexer)?; + return Ok(()); + } + }, + "hg" if matches!(word, "\"" | "“" | "”" | "″") => Token::unit(InchOfMercury), + other => { + if word.to_ascii_lowercase() == "in" { + lexer.tokens.push(Token::LexerKeyword(In)); + } else { + lexer.tokens.push(Token::unit(Inch)); + } + lex_word_if_non_empty(other, lexer)?; + return Ok(()); + } + } + } "ft" | "foot" | "feet" => Token::unit(Foot), "yd" | "yard" | "yards" => Token::unit(Yard), "mi" | "mile" | "miles" => Token::unit(Mile), @@ -880,19 +895,6 @@ pub fn lex(input: &str, remove_trailing_operator: bool) -> Result, St } } } - // decide if "in" is Inch or To - Token::LexerKeyword(In) => { - match tokens.get(token_index + 1) { - Some(Token::Unit(_)) => { - // "in" should be To - tokens[token_index] = Token::TextOperator(To); - } - _ => { - // otherwise, Inch - tokens[token_index] = Token::unit(Inch); - } - } - } _ => {} } if token_index == tokens.len() - 1 { -- 2.51.2