1 module benchmark;
2 
3 import std.datetime, std.range, std.random, std.stdio, std.conv, std.exception;
4 import pry.stream;
5 
6 alias S = SimpleStream!string;
7 
8 auto makeParser(){
9 	import pry;
10 
11 	with(parsers!S) {
12 		auto expr = dynamic!int;
13 		auto primary = any(
14 			range!('0', '9').rep.map!(x => x.to!int),
15 			seq(tk!'(', expr, tk!')').map!(x => x[1])
16 		);
17 		auto term = dynamic!int;
18 		term = any(
19 			seq(primary, tk!'*', term).map!(x => x[0] * x[2]),
20 			seq(primary, tk!'/', term).map!(x => x[0] / x[2]),
21 			primary
22 		);
23 		expr = any(
24 			seq(term, tk!'+', expr).map!(x => x[0] + x[2]),
25 			seq(term, tk!'-', expr).map!(x => x[0] - x[2]),
26 			term
27 		);
28 		return expr;
29 	}
30 }
31 
32 auto rng = Xorshift(42);
33 
34 string generateSample(int depth){
35 	if(depth == 0){
36 		int len = uniform(1, 6, rng);
37 		return generate!(() => cast(char)(uniform(0, 10, rng) + '0'))
38 				.take(len).array.assumeUnique;
39 	}
40 	int dice = uniform(0, 5, rng);
41 	switch(dice){
42 	case 0:
43 		return "(" ~ generateSample(depth-1) ~ ")";
44 	case 1:
45 		return generateSample(depth-1) ~ "+" ~ generateSample(depth-1);
46 	case 2:
47 		return generateSample(depth-1) ~ "-" ~ generateSample(depth-1);
48 	case 3:
49 		return generateSample(depth-1) ~ "*" ~ generateSample(depth-1);
50 	case 4:
51 		return generateSample(depth-1);
52 	default:
53 		assert(false);
54 	}
55 }
56 
57 void main(){
58 	auto sample = generateSample(20);
59 	version(pry)
60 		auto parser = makeParser();
61 	else version(manual){
62 		import manual = parser;
63 		struct parser {
64 			alias parse = manual.expr;
65 		}
66 	}
67 	else {
68 		static assert(false, "Use -version=pry or -version=manual");
69 	}
70 	int value;
71 	StopWatch sw;
72 	sw.start();
73 	foreach(i; 0..100){
74 		S s = S(sample);
75 		int v;
76 		S.Error err;
77 		parser.parse(s, v, err);
78 		value += v;
79 	}
80 	sw.stop();
81 	writefln("Value: %d\nTime: %s ms", value, sw.peek().msecs);
82 }