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