16855e09eSopenharmony_ci#[macro_use] 26855e09eSopenharmony_ciextern crate criterion; 36855e09eSopenharmony_ci 46855e09eSopenharmony_ci#[global_allocator] 56855e09eSopenharmony_cistatic ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; 66855e09eSopenharmony_ci 76855e09eSopenharmony_ciuse criterion::Criterion; 86855e09eSopenharmony_ciuse nom::{ 96855e09eSopenharmony_ci branch::alt, 106855e09eSopenharmony_ci character::complete::{char, digit1, one_of, space0}, 116855e09eSopenharmony_ci combinator::map_res, 126855e09eSopenharmony_ci multi::fold_many0, 136855e09eSopenharmony_ci sequence::{delimited, pair}, 146855e09eSopenharmony_ci IResult, 156855e09eSopenharmony_ci}; 166855e09eSopenharmony_ci 176855e09eSopenharmony_ci// Parser definition 186855e09eSopenharmony_ci 196855e09eSopenharmony_ci// We transform an integer string into a i64, ignoring surrounding whitespaces 206855e09eSopenharmony_ci// We look for a digit suite, and try to convert it. 216855e09eSopenharmony_ci// If there are no digits, we look for a parenthesized expression. 226855e09eSopenharmony_cifn factor(input: &[u8]) -> IResult<&[u8], i64> { 236855e09eSopenharmony_ci delimited( 246855e09eSopenharmony_ci space0, 256855e09eSopenharmony_ci alt(( 266855e09eSopenharmony_ci map_res(digit1, |digits| { 276855e09eSopenharmony_ci unsafe { std::str::from_utf8_unchecked(digits) }.parse() 286855e09eSopenharmony_ci }), 296855e09eSopenharmony_ci delimited(char('('), expr, char(')')), 306855e09eSopenharmony_ci )), 316855e09eSopenharmony_ci space0, 326855e09eSopenharmony_ci )(input) 336855e09eSopenharmony_ci} 346855e09eSopenharmony_ci 356855e09eSopenharmony_ci// We read an initial factor and for each time we find 366855e09eSopenharmony_ci// a * or / operator followed by another factor, we do 376855e09eSopenharmony_ci// the math by folding everything 386855e09eSopenharmony_cifn term(input: &[u8]) -> IResult<&[u8], i64> { 396855e09eSopenharmony_ci let (input, init) = factor(input)?; 406855e09eSopenharmony_ci fold_many0( 416855e09eSopenharmony_ci pair(one_of("*/"), factor), 426855e09eSopenharmony_ci move || init, 436855e09eSopenharmony_ci |acc, (op, val)| { 446855e09eSopenharmony_ci if op == '*' { 456855e09eSopenharmony_ci acc * val 466855e09eSopenharmony_ci } else { 476855e09eSopenharmony_ci acc / val 486855e09eSopenharmony_ci } 496855e09eSopenharmony_ci }, 506855e09eSopenharmony_ci )(input) 516855e09eSopenharmony_ci} 526855e09eSopenharmony_ci 536855e09eSopenharmony_cifn expr(input: &[u8]) -> IResult<&[u8], i64> { 546855e09eSopenharmony_ci let (input, init) = term(input)?; 556855e09eSopenharmony_ci fold_many0( 566855e09eSopenharmony_ci pair(one_of("+-"), term), 576855e09eSopenharmony_ci move || init, 586855e09eSopenharmony_ci |acc, (op, val)| { 596855e09eSopenharmony_ci if op == '+' { 606855e09eSopenharmony_ci acc + val 616855e09eSopenharmony_ci } else { 626855e09eSopenharmony_ci acc - val 636855e09eSopenharmony_ci } 646855e09eSopenharmony_ci }, 656855e09eSopenharmony_ci )(input) 666855e09eSopenharmony_ci} 676855e09eSopenharmony_ci 686855e09eSopenharmony_ci#[allow(clippy::eq_op, clippy::erasing_op)] 696855e09eSopenharmony_cifn arithmetic(c: &mut Criterion) { 706855e09eSopenharmony_ci let data = b" 2*2 / ( 5 - 1) + 3 / 4 * (2 - 7 + 567 *12 /2) + 3*(1+2*( 45 /2));"; 716855e09eSopenharmony_ci 726855e09eSopenharmony_ci assert_eq!( 736855e09eSopenharmony_ci expr(data), 746855e09eSopenharmony_ci Ok(( 756855e09eSopenharmony_ci &b";"[..], 766855e09eSopenharmony_ci 2 * 2 / (5 - 1) + 3 / 4 * (2 - 7 + 567 * 12 / 2) + 3 * (1 + 2 * (45 / 2)), 776855e09eSopenharmony_ci )) 786855e09eSopenharmony_ci ); 796855e09eSopenharmony_ci c.bench_function("arithmetic", |b| { 806855e09eSopenharmony_ci b.iter(|| expr(data).unwrap()); 816855e09eSopenharmony_ci }); 826855e09eSopenharmony_ci} 836855e09eSopenharmony_ci 846855e09eSopenharmony_cicriterion_group!(benches, arithmetic); 856855e09eSopenharmony_cicriterion_main!(benches); 86