• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #[macro_use]
2 extern crate criterion;
3 
4 #[global_allocator]
5 static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
6 
7 use criterion::Criterion;
8 use nom::{
9   branch::alt,
10   character::complete::{char, digit1, one_of, space0},
11   combinator::map_res,
12   multi::fold_many0,
13   sequence::{delimited, pair},
14   IResult,
15 };
16 
17 // Parser definition
18 
19 // We transform an integer string into a i64, ignoring surrounding whitespaces
20 // We look for a digit suite, and try to convert it.
21 // If there are no digits, we look for a parenthesized expression.
factor(input: &[u8]) -> IResult<&[u8], i64>22 fn factor(input: &[u8]) -> IResult<&[u8], i64> {
23   delimited(
24     space0,
25     alt((
26       map_res(digit1, |digits| {
27         unsafe { std::str::from_utf8_unchecked(digits) }.parse()
28       }),
29       delimited(char('('), expr, char(')')),
30     )),
31     space0,
32   )(input)
33 }
34 
35 // We read an initial factor and for each time we find
36 // a * or / operator followed by another factor, we do
37 // the math by folding everything
term(input: &[u8]) -> IResult<&[u8], i64>38 fn term(input: &[u8]) -> IResult<&[u8], i64> {
39   let (input, init) = factor(input)?;
40   fold_many0(
41     pair(one_of("*/"), factor),
42     move || init,
43     |acc, (op, val)| {
44       if op == '*' {
45         acc * val
46       } else {
47         acc / val
48       }
49     },
50   )(input)
51 }
52 
expr(input: &[u8]) -> IResult<&[u8], i64>53 fn expr(input: &[u8]) -> IResult<&[u8], i64> {
54   let (input, init) = term(input)?;
55   fold_many0(
56     pair(one_of("+-"), term),
57     move || init,
58     |acc, (op, val)| {
59       if op == '+' {
60         acc + val
61       } else {
62         acc - val
63       }
64     },
65   )(input)
66 }
67 
68 #[allow(clippy::eq_op, clippy::erasing_op)]
arithmetic(c: &mut Criterion)69 fn arithmetic(c: &mut Criterion) {
70   let data = b"  2*2 / ( 5 - 1) + 3 / 4 * (2 - 7 + 567 *12 /2) + 3*(1+2*( 45 /2));";
71 
72   assert_eq!(
73     expr(data),
74     Ok((
75       &b";"[..],
76       2 * 2 / (5 - 1) + 3 / 4 * (2 - 7 + 567 * 12 / 2) + 3 * (1 + 2 * (45 / 2)),
77     ))
78   );
79   c.bench_function("arithmetic", |b| {
80     b.iter(|| expr(data).unwrap());
81   });
82 }
83 
84 criterion_group!(benches, arithmetic);
85 criterion_main!(benches);
86