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