1 /* 2 * Copyright (C) 2014 Nonki Takkahashi. All rights reserved. 3 * 4 * History: 5 * 0.1 2014-01-10 Created. 6 */ 7 8 /** 9 * @fileOverview Paresr - Mathematic Expression Parser Object 10 * @version 0.1 11 * @author Nonki Takahashi 12 */ 13 14 /** 15 * onCalc Function - Calc Button Handler 16 */ 17 function onCalc() { 18 var input = document.calculator.expression.value; 19 var expr = new Expression(input); 20 var output = document.getElementById("result"); 21 output.innerHTML = output.innerHTML + input + "=" + expr.expression() + "<br>"; 22 }; 23 24 /** 25 * Mathematic Expression Parser Object 26 * @class Represents Parser Object 27 * @this {Expression} 28 * @param {String} src source string 29 * @since 0.1 30 */ 31 Expression = function(src) { 32 this.value = 0; 33 /* inherit the methods of class Lex */ 34 Lex.call(this, src); 35 }; 36 Expression.prototype = new Lex(); 37 38 /** 39 * Runner for Expression 40 * @param {String} src source string 41 * @return {Float} calculated value 42 * @since 0.1 43 */ 44 Expression.prototype.run = function(n, match, parser) { 45 var retval; 46 switch (parser) { 47 case "expression" : 48 retval = match[0]; 49 for (var i = 2; i <= n; i += 2) 50 switch (match[i - 1]) { 51 case "+" : 52 retval += match[i]; 53 break; 54 case "-" : 55 retval -= match[i]; 56 } 57 break; 58 case "term" : 59 retval = match[0]; 60 for (var i = 2; i <= n; i += 2) 61 switch (match[i - 1]) { 62 case "*" : 63 retval *= match[i]; 64 break; 65 case "/" : 66 retval /= match[i]; 67 } 68 break; 69 case "factor" : 70 if (match[0] == "(") 71 retval = match[1]; 72 else 73 retval = match[0]; 74 break; 75 case "integer" : 76 case "real" : 77 retval = new String(); 78 for (var i = 0; i <= n; i++) 79 if (match[i]) 80 retval += match[i]; 81 retval = parseFloat(retval); 82 break; 83 }; 84 return retval; 85 }; 86 87 /** 88 * Parse Expression<br> 89 * expression = term, {('+' | '-'), term}; 90 * @return {Float} calculated value 91 * @since 0.1 92 */ 93 Expression.prototype.expression = function() { 94 var match = []; 95 var n = 0; 96 this.push(); 97 match[n] = this.term(); 98 if (!match[n]) { 99 this.pop(true); 100 return null; 101 } 102 this.pop(false); 103 while (match[n]) { 104 this.push(); 105 match[++n] = this.ch("+"); 106 if (!match[n]) 107 match[n] = this.ch("-"); 108 if (match[n]) 109 match[++n] = this.term(); 110 if (match[n]) 111 this.pop(false); 112 else 113 this.pop(true); 114 } 115 return this.run(n, match, "expression"); 116 }; 117 118 /** 119 * Parse Term<br> 120 * term = factor, {('*' | '/'), factor}; 121 * @return {Float} calculated value 122 * @since 0.1 123 */ 124 Expression.prototype.term = function() { 125 var match = []; 126 var n = 0; 127 this.push(); 128 match[n] = this.factor(); 129 if (!match[n]) { 130 this.pop(true); 131 return null; 132 } 133 this.pop(false); 134 while (match[n]) { 135 this.push(); 136 match[++n] = this.ch("*"); 137 if (!match[n]) 138 match[n] = this.ch("/"); 139 if (match[n]) 140 match[++n] = this.factor(); 141 if (match[n]) 142 this.pop(false); 143 else 144 this.pop(true); 145 } 146 return this.run(n, match, "term"); 147 }; 148 149 /** 150 * Parse Factor<br> 151 * factor = ('(', expression, ')') | real | integer; 152 * @return {Float} calculated value 153 * @since 0.1 154 */ 155 Expression.prototype.factor = function() { 156 var match = []; 157 var n = 0; 158 this.push(); 159 match[n] = this.ch("("); 160 if (match[n]) 161 match[++n] = this.expression(); 162 if (match[n]) 163 match[++n] = this.ch(")"); 164 if (match[n]) 165 this.pop(false); 166 else { 167 this.pop(true); 168 n = 0; 169 match[n] = this.real(); 170 } 171 if (!match[n]) { 172 n = 0; 173 match[n] = this.integer(); 174 } 175 if (!match[n]) 176 return null; 177 return this.run(n, match, "factor"); 178 }; 179 180 /** 181 * Parse Real<br> 182 * real = ((integer, '.') | (('.', digit)), {digit}; 183 * @return {Float} calculated value 184 * @since 0.1 185 */ 186 Expression.prototype.real = function() { 187 var match = []; 188 var n = 0; 189 this.push(); 190 match[n] = this.integer(); 191 if (match[n]) 192 match[++n] = this.ch("."); 193 if (match[n]) 194 this.pop(false); 195 else { 196 this.pop(true); 197 this.push(); 198 n = 0; 199 match[n] = this.ch("."); 200 if (match[n]) 201 match[++n] = this.integer(); 202 if (match[n]) 203 this.pop(false); 204 else 205 this.pop(true); 206 } 207 if (!match[n]) 208 return null; 209 while (match[n]) { 210 match[++n] = this.digit(); 211 } 212 return this.run(n, match, "real"); 213 }; 214 215 /** 216 * Parse Integer<br> 217 * integer = ['-'], digit, {digit}; 218 * @return {Float} calculated value 219 * @since 0.1 220 */ 221 Expression.prototype.integer = function() { 222 var match = []; 223 var n = 0; 224 this.push(); 225 match[n] = this.ch("-"); 226 match[++n] = this.digit(); 227 if (!match[n]) { 228 this.pop(true); 229 return null; 230 } 231 this.pop(false); 232 while (match[n]) { 233 match[++n] = this.digit(); 234 } 235 return this.run(n, match, "integer"); 236 }; 237