1 module pegged.examples.arithmetic; 2 3 import std.conv: to; 4 5 import pegged.grammar; 6 7 mixin(grammar(` 8 Arithmetic: 9 Term < Factor (Add / Sub)* 10 Add < "+" Factor 11 Sub < "-" Factor 12 Factor < Primary (Mul / Div)* 13 Mul < "*" Primary 14 Div < "/" Primary 15 Primary < Parens / Neg / Number / Variable 16 Parens < :"(" Term :")" 17 Neg < "-" Primary 18 Number < ~([0-9]+) 19 Variable <- identifier 20 `)); 21 22 float interpreter(string expr) 23 { 24 auto p = Arithmetic(expr); 25 26 //writeln(p); 27 28 float value(ParseTree p) 29 { 30 switch (p.name) 31 { 32 case "Arithmetic": 33 return value(p.children[0]); 34 case "Arithmetic.Term": 35 float v = 0.0; 36 foreach(child; p.children) v += value(child); 37 return v; 38 case "Arithmetic.Add": 39 return value(p.children[0]); 40 case "Arithmetic.Sub": 41 return -value(p.children[0]); 42 case "Arithmetic.Factor": 43 float v = 1.0; 44 foreach(child; p.children) v *= value(child); 45 return v; 46 case "Arithmetic.Mul": 47 return value(p.children[0]); 48 case "Arithmetic.Div": 49 return 1.0/value(p.children[0]); 50 case "Arithmetic.Primary": 51 return value(p.children[0]); 52 case "Arithmetic.Parens": 53 return value(p.children[0]); 54 case "Arithmetic.Neg": 55 return -value(p.children[0]); 56 case "Arithmetic.Number": 57 return to!float(p.matches[0]); 58 default: 59 return float.nan; 60 } 61 } 62 63 return value(p); 64 } 65 66 unittest 67 { 68 assert(interpreter("1") == 1.0); 69 assert(interpreter("-1") == -1.0); 70 assert(interpreter("1+1") == 2.0); 71 assert(interpreter("1-1") == 0.0); 72 73 assert(interpreter("1+1+1") == 3.0); 74 assert(interpreter("1-1-1") == -1.0); 75 assert(interpreter("1+1-1") == 1.0); 76 assert(interpreter("1-1+1") == 1.0); 77 assert(interpreter("-1+1+1") == 1.0); 78 79 assert(interpreter("(-1+1)+1") == 1.0); 80 assert(interpreter("-1+(1+1)") == 1.0); 81 assert(interpreter("(-1+1+1)") == 1.0); 82 assert(interpreter("1-(1-1)") == 1.0); 83 84 assert(interpreter("1*1") == 1.0); 85 assert(interpreter("1/1") == 1.0); 86 assert(interpreter("-1*1") == -1.0); 87 assert(interpreter("-1/1") == -1.0); 88 89 assert(interpreter("1+2*3") == 7.0); 90 assert(interpreter("1-2*3") == -5.0); 91 assert(interpreter("-1-2*-3") == 5.0); 92 assert(interpreter("-1+2*-3") == -7.0); 93 94 assert(interpreter("1/2/(1/2)") == 1.0); 95 assert(interpreter("1/2/1/2") == .25); 96 assert(interpreter("1-2*3-2*3") == -11.0); 97 98 assert(interpreter("2*3*3-3*3+3*4") == 21.0); 99 assert(interpreter("2*3*3-3*(3+3*4)") == -27.0); 100 }