Skip to content

Commit

Permalink
Allow % as modulo in some cases, see #265
Browse files Browse the repository at this point in the history
  • Loading branch information
printfn committed May 4, 2024
1 parent 37004a9 commit 26b3188
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
24 changes: 24 additions & 0 deletions core/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,27 @@ fn parse_modulo_cont(input: &[Token]) -> ParseResult<'_> {
Ok((b, input))
}

// try parsing `%` as modulo
fn parse_modulo2_cont(input: &[Token]) -> ParseResult<'_> {
let (token, input) = parse_token(input)?;
if let Token::Ident(ident) = token {
if ident.as_str() != "%" {
return Err(ParseError::UnexpectedInput);
}
} else {
return Err(ParseError::UnexpectedInput);
}
// extra restriction: `%` can't be directly followed by an operator, since we
// assume that e.g. `1 % + ...` should be a percentage
if input.first().is_some_and(|t| {
matches!(t, Token::Symbol(_)) && !matches!(t, Token::Symbol(Symbol::OpenParens))
}) {
return Err(ParseError::UnexpectedInput);
}
let (b, input) = parse_power(input, true)?;
Ok((b, input))
}

fn parse_multiplicative(input: &[Token]) -> ParseResult<'_> {
let (mut res, mut input) = parse_power(input, true)?;
loop {
Expand All @@ -296,6 +317,9 @@ fn parse_multiplicative(input: &[Token]) -> ParseResult<'_> {
} else if let Ok((term, remaining)) = parse_modulo_cont(input) {
res = Expr::Bop(Bop::Mod, Box::new(res.clone()), Box::new(term));
input = remaining;
} else if let Ok((term, remaining)) = parse_modulo2_cont(input) {
res = Expr::Bop(Bop::Mod, Box::new(res.clone()), Box::new(term));
input = remaining;
} else if let Ok((new_res, remaining)) = parse_mixed_fraction(input, &res) {
res = new_res;
input = remaining;
Expand Down
7 changes: 7 additions & 0 deletions core/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4717,6 +4717,7 @@ fn zero_kilocelsius_to_millifahrenheit() {
}

#[test]
#[ignore]
fn five_percent_celsius_to_fahrenheit() {
test_eval("5% °C to °F", "32.09 °F");
}
Expand Down Expand Up @@ -5965,3 +5966,9 @@ fn test_mean() {

test_eval("average d500", "250.5");
}

#[test]
fn modulo_percent() {
test_eval("5%4", "1");
test_eval("(104857566-103811072+1) % (1024*1024/512)", "2015");
}

0 comments on commit 26b3188

Please sign in to comment.