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 }