1 package com.teamkonzept.lib.math; 2 3 import java.util.*; 4 import java.io.StringReader ; 5 import java.io.IOException ; 6 7 public class Eval{ 8 9 public Eval(){} 10 11 public double eval(String expr) 12 throws MalformedExpressionException, 13 IOException , BadOperandTypeException, 14 UnsupportedOperatorException{ 15 16 Vector list = parseExpression(removeWhiteSpaces(expr.toLowerCase())); 17 18 Vector operators = extractOperators(list); 19 22 sortOperators(operators); 23 24 return evalTokenList(list, operators); 25 } 26 27 Vector parseExpression(String expr) 28 throws MalformedExpressionException, UnsupportedOperatorException, 29 IOException { 30 Vector res = new Vector(); 31 Object o = null; 32 StringReader in = new StringReader (expr); 33 res = parseExpression(in, res, -1, 34 0, true, 35 true, 0); 36 return res; 37 } 38 39 Vector parseExpression(StringReader in, Vector tokens, 40 int lookAhead, 41 int level, boolean newLevel, 42 boolean lastWasBinaryOpOrOpenParen, int position) 43 throws MalformedExpressionException, UnsupportedOperatorException, 44 IOException { 45 boolean lookedAhead = false; 46 int lookedAheadChar = -1; 47 boolean functionFound = false; 48 int c = lookAhead; 50 if ( c < 0 ){ 51 c = in.read(); 52 position++; 53 } 54 if ( newLevel ){ 57 if ( c == '+' ){ 58 return parseExpression(in, tokens, -1, 60 level, false, true, position); 61 } 62 else if ( c == '-' ){ 63 tokens.add(new Double (0.0)); 65 tokens.add(new MathBinaryOperator(MathBinaryOperator.MINUS, 66 level, position)); 67 return parseExpression(in, tokens, -1, 69 level, false, true, position); 70 } 71 } 72 if ( !lastWasBinaryOpOrOpenParen ){ 77 if ( c < 0 ){ 79 if ( level == 0 ) 81 return tokens; 82 throw new MalformedExpressionException 84 (MalformedExpressionException.MISSING_CLOSING_PAREN, position); 85 } 86 else if ( c == ')' ){ 88 if ( level-- > 0 ) 89 return parseExpression(in, tokens, -1, 90 level, false, false, position); 91 throw new MalformedExpressionException 93 (MalformedExpressionException.MISSING_OPENING_PAREN, 94 position); 95 } 96 else if ( c == '+' ){ 98 tokens.add(new MathBinaryOperator(MathBinaryOperator.PLUS, 99 level, position)); 100 return parseExpression(in, tokens, -1, 101 level, false, true, position); 102 } 103 else if ( c == '-' ){ 104 tokens.add(new MathBinaryOperator(MathBinaryOperator.MINUS, 105 level, position)); 106 return parseExpression(in, tokens, -1, 107 level, false, true, position); 108 } 109 else if ( c == '*' ){ 110 tokens.add(new MathBinaryOperator(MathBinaryOperator.MULT, 111 level, position)); 112 return parseExpression(in, tokens, -1, 113 level, false, true, position); 114 } 115 else if ( c == '/' ){ 116 tokens.add(new MathBinaryOperator(MathBinaryOperator.DIV, 117 level, position)); 118 return parseExpression(in, tokens, -1, 119 level, false, true, position); 120 } 121 else if ( c == '\\' ){ 122 tokens.add(new MathBinaryOperator(MathBinaryOperator.INT_DIV, 123 level, position)); 124 return parseExpression(in, tokens, -1, 125 level, false, true, position); 126 } 127 else if ( c == '%' ){ 128 tokens.add(new MathBinaryOperator(MathBinaryOperator.MODULO, 129 level, position)); 130 return parseExpression(in, tokens, -1, 131 level, false, true, position); 132 } 133 else if ( c == '^' ){ 134 tokens.add(new MathBinaryOperator(MathBinaryOperator.POW, 135 level, position)); 136 return parseExpression(in, tokens, -1, 137 level, false, true, position); 138 } 139 else if ( c == '=' ){ 142 checkNextChar('=', in, ++position); 144 tokens.add(new CompareOperator(CompareOperator.EQUAL, 145 level, position)); 146 } 147 else if ( c == '!' ){ 148 checkNextChar('=', in, ++position); 150 tokens.add(new CompareOperator(CompareOperator.NOT_EQUAL, 151 level, position)); 152 } 153 else if ( c == '<' ){ 155 lookedAheadChar = in.read(); 157 position++; 158 if ( lookedAheadChar == '=' ) 159 tokens.add(new CompareOperator(CompareOperator.LESS_OR_EQUAL, 160 level, position)); 161 else{ 162 tokens.add(new CompareOperator(CompareOperator.LESS, 163 level, position)); 164 lookedAhead = true; 165 } 166 } 167 else if ( c == '>' ){ 168 lookedAheadChar = in.read(); 170 position++; 171 if ( lookedAheadChar == '=' ) 172 tokens.add(new CompareOperator(CompareOperator.GREATER_OR_EQUAL, 173 level, position)); 174 else{ 175 tokens.add(new CompareOperator(CompareOperator.GREATER, 176 level, position)); 177 lookedAhead = true; 178 } 179 } 180 else if ( c == '|' ){ 183 checkNextChar((char)c, in, ++position); 185 tokens.add(new BinaryLogicalOperator(BinaryLogicalOperator.OR, 186 level, position)); 187 } 188 else if ( c == '&'){ 189 checkNextChar((char)c, in, ++position); 191 tokens.add(new BinaryLogicalOperator(BinaryLogicalOperator.AND, 192 level, position)); 193 } 194 else 196 throw new MalformedExpressionException 197 (MalformedExpressionException.SYNTAX_ERROR, position); 198 if ( lookedAhead ) 200 return parseExpression(in, tokens, lookedAheadChar, 201 level, true, true, position); 202 else 203 return parseExpression(in, tokens, -1, 204 level, true, true, position); 205 } 206 else{ StringBuffer sb = new StringBuffer (); 212 if ( Character.isDigit((char)c) || c == '.' ){ 213 sb.append((char)c); 214 c = in.read(); position++; 215 while ( Character.isDigit((char)c) || c == '.' ){ 216 sb.append((char)c); 217 c = in.read(); position++; 218 } 219 Double d = new Double (sb.toString()); 220 if ( c == 'l' ){ 222 c = in.read(); position++; 223 if ( c == 'o' ){ 224 c = in.read(); position++; 225 if ( c == 'g' ){ 226 c = in.read(); position++; 227 if ( c != '(' ) 228 throw new MalformedExpressionException 229 (MalformedExpressionException.MISSING_OPENING_PAREN, 230 position); 231 else{ 232 tokens.add(new MathFunction(MathFunction.LOG, 233 level, position, d)); 234 return parseExpression(in, tokens, -1, 235 ++level, true, true, position); 236 } 237 } 238 } 239 throw new MalformedExpressionException 241 (MalformedExpressionException.SYNTAX_ERROR, position); 242 } 243 tokens.add(d); 245 return parseExpression(in, tokens, c, 247 level, false, false, position); 248 } 249 else if ( c == '(' ){ 251 return parseExpression(in, tokens, -1, 252 ++level, true, true, position); 253 } 254 else if ( c == '!' ){ 256 tokens.add(new UnaryLogicalOperator(UnaryLogicalOperator.NOT, 257 level, position)); 258 return parseExpression(in, tokens, -1, 259 level, true, true, position); 260 } 261 else{ functionFound = false; 263 lookedAhead = false; 264 if ( c == 'a' ){ 266 c = in.read(); position++; 267 if ( c == 'b' ){ 269 c = in.read(); position++; 270 if ( c == 's' ){ 271 tokens.add(new MathFunction(MathFunction.ABS, 272 level, position)); 273 functionFound = true; 274 } 275 } 276 else if ( c == 'c' ){ 278 c = in.read(); position++; 279 if ( c == 'o' ){ 280 c = in.read(); position++; 281 if ( c == 's' ){ 282 tokens.add(new MathFunction(MathFunction.ACOS, 283 level, position)); 284 functionFound = true; 285 } 286 } 287 } 288 else if ( c == 's' ){ 290 c = in.read(); position++; 291 if ( c == 'i' ){ 292 c = in.read(); position++; 293 if ( c == 'n' ){ 294 tokens.add(new MathFunction(MathFunction.ASIN, 295 level, position)); 296 functionFound = true; 297 } 298 } 299 } 300 else if ( c == 't' ){ 302 c = in.read(); position++; 303 if ( c == 'a' ){ 304 c = in.read(); position++; 305 if ( c == 'n' ){ 306 tokens.add(new MathFunction(MathFunction.ATAN, 307 level, position)); 308 functionFound = true; 309 } 310 } 311 } 312 } 313 else if ( c == 'c' ){ 315 c = in.read(); position++; 316 if ( c == 'e' ){ 318 c = in.read(); position++; 319 if ( c == 'i' ){ 320 c = in.read(); position++; 321 if ( c == 'l' ){ 322 tokens.add(new MathFunction(MathFunction.CEIL, 323 level, position)); 324 functionFound = true; 325 } 326 } 327 } 328 else if ( c == 'o' ){ 330 c = in.read(); position++; 331 if ( c == 's' ){ 333 c = in.read(); position++; 334 if ( c == 'h' ){ 336 tokens.add(new MathFunction(MathFunction.COSH, 337 level, position)); 338 functionFound = true; 339 } 340 else { 342 tokens.add(new MathFunction(MathFunction.COS, 343 level, position)); 344 functionFound = true; 345 lookedAhead = true; 346 } 347 } 348 else if ( c == 't' ){ 350 c = in.read(); position++; 351 if ( c == 'a' ){ 352 c = in.read(); position++; 353 if ( c == 'n' ){ 354 tokens.add(new MathFunction(MathFunction.COTAN, 355 level, position)); 356 functionFound = true; 357 } 358 } 359 } 360 } 361 } 362 else if ( c == 'e' ){ 364 c = in.read(); position++; 365 if ( c == 'x' ){ 366 c = in.read(); position++; 367 if ( c == 'p' ){ 368 tokens.add(new MathFunction(MathFunction.EXP, 369 level, position)); 370 functionFound = true; 371 } 372 } 373 } 374 else if ( c == 'f' ){ 376 c = in.read(); position++; 377 if ( c == 'a' ){ 379 c = in.read(); position++; 380 if ( c == 'c' ){ 381 tokens.add(new MathFunction(MathFunction.FAC, 382 level, position)); 383 functionFound = true; 384 } 385 } 386 else if ( c == 'l' ){ 388 c = in.read(); position++; 389 if ( c == 'o' ){ 390 c = in.read(); position++; 391 if ( c == 'o' ){ 392 c = in.read(); position++; 393 if ( c == 'r' ){ 394 tokens.add(new MathFunction(MathFunction.FLOOR, 395 level, position)); 396 functionFound = true; 397 } 398 } 399 } 400 } 401 else if ( c == 'p' ){ 403 c = in.read(); position++; 404 if ( c == 'a' ){ 405 c = in.read(); position++; 406 if ( c == 'r' ){ 407 c = in.read(); position++; 408 if ( c == 't' ){ 409 tokens.add(new MathFunction(MathFunction.FPART, 410 level, position)); 411 functionFound = true; 412 } 413 } 414 } 415 } 416 } 417 else if ( c == 'l' ){ 419 c = in.read(); position++; 420 if ( c == 'n' ){ 421 tokens.add(new MathFunction(MathFunction.LN, level, position)); 422 functionFound = true; 423 } 424 } 425 else if ( c == 'r' ){ 427 c = in.read(); position++; 428 if ( c == 'o' ){ 429 c = in.read(); position++; 430 if ( c == 'u' ){ 431 c = in.read(); position++; 432 if ( c == 'n' ){ 433 c = in.read(); position++; 434 if ( c == 'd' ){ 435 tokens.add(new MathFunction(MathFunction.ROUND, 436 level, position)); 437 functionFound = true; 438 } 439 } 440 } 441 } 442 } 443 else if ( c == 's' ){ 445 c = in.read(); position++; 446 if ( c == 'f' ){ 448 c = in.read(); position++; 449 if ( c == 'a' ){ 450 c = in.read(); position++; 451 if ( c == 'c' ){ 452 tokens.add(new MathFunction(MathFunction.SFAC, 453 level, position)); 454 functionFound = true; 455 } 456 } 457 } 458 else if ( c == 'i' ){ 460 c = in.read(); position++; 461 if ( c == 'n' ){ 462 c = in.read(); position++; 463 if ( c == 'h' ){ 465 tokens.add(new MathFunction(MathFunction.SINH, 466 level, position)); 467 functionFound = true; 468 } 469 else { 471 tokens.add(new MathFunction(MathFunction.SIN, 472 level, position)); 473 functionFound = true; 474 lookedAhead = true; 475 } 476 } 477 } 478 else if ( c == 'q' ){ 480 c = in.read(); position++; 481 if ( c == 'r' ){ 482 c = in.read(); position++; 483 if ( c == 't' ){ 484 tokens.add(new MathFunction(MathFunction.SQRT, 485 level, position)); 486 functionFound = true; 487 } 488 } 489 } 490 } 491 else if ( c == 't' ){ 493 c = in.read(); position++; 494 if ( c == 'a' ){ 495 c = in.read(); position++; 496 if ( c == 'n' ){ 497 c = in.read(); position++; 498 if ( c == 'h' ){ 500 tokens.add(new MathFunction(MathFunction.TANH, 501 level, position)); 502 functionFound = true; 503 } 504 else { 506 tokens.add(new MathFunction(MathFunction.TAN, 507 level, position)); 508 functionFound = true; 509 lookedAhead = true; 510 } 511 } 512 } 513 } 514 } 515 if ( functionFound ){ 517 if ( !lookedAhead ) 519 c = in.read(); position++; 520 if ( c != '(' ) 521 throw new MalformedExpressionException 522 (MalformedExpressionException.MISSING_OPENING_PAREN, 523 position); 524 return parseExpression(in, tokens, -1, 526 ++level, true, true, position); 527 } 528 else{ throw new MalformedExpressionException 530 (MalformedExpressionException.SYNTAX_ERROR, 531 position); 532 } 533 } 534 } 535 536 539 Vector extractOperators(Vector list){ 540 Vector result = new Vector(); 541 int size = list.size(); 542 for ( int i = 0; i < size; i++ ){ 543 Object o = list.get(i); 544 if ( o instanceof OperatorPriority ) 545 result.add(o); 546 } 547 return result; 548 } 549 550 553 void sortOperators(Vector list){ 554 Collections.sort(list, new Comparator(){ 555 public int compare(Object o1, Object o2){ 556 return -1 * ((OperatorPriority)o1).compareTo(o2); 557 } 558 public boolean equals(Object obj){ 559 return false; 560 } 561 }); 562 } 563 564 567 double evalTokenList(Vector list, Vector sorted) 568 throws BadOperandTypeException, MalformedExpressionException{ 569 int size = sorted.size(); 570 for ( int i = 0; i < size; i++ ){ 571 Object o = sorted.get(i); 572 int listpos = list.indexOf(o); 573 int rightpos = listpos + 1; 574 if ( o instanceof BinaryOperator ){ 575 int leftpos = listpos - 1; 576 BinaryOperator op = (BinaryOperator)o; 577 Object left = list.get(leftpos); 579 Object right = list.get(rightpos); 580 Object res = op.evaluate(left, right); 582 list.setElementAt(res, leftpos); 584 list.removeElementAt(listpos); 585 list.removeElementAt(listpos); 586 } 587 else{ 588 UnaryOperator op = (UnaryOperator)o; 589 Object operand = list.get(rightpos); 591 Object res = op.evaluate(operand); 593 list.setElementAt(res, listpos); 595 list.removeElementAt(rightpos); 596 } 597 } 598 if ( list.size() != 1 ) 600 throw new MalformedExpressionException 601 (MalformedExpressionException.UNKNOWN_RESULT, -1); 602 Object o = list.get(0); 603 if ( o instanceof Double ) 604 return ((Double )o).doubleValue(); 605 else if ( o instanceof Boolean ){ 606 if ( ((Boolean )o).booleanValue() ) 607 return 1.0; 608 else 609 return 0.0; 610 } 611 else 612 throw new MalformedExpressionException 613 (MalformedExpressionException.UNKNOWN_RESULT, -1); 614 } 615 616 617 618 619 public String removeWhiteSpaces(String s){ 620 StringBuffer sb = new StringBuffer (s); 621 int l = sb.length(); 622 for ( int i = 0; i < l; i++ ) 623 if ( sb.charAt(i) == ' ' ){ 624 sb.deleteCharAt(i--); 625 l--; 626 } 627 return sb.toString(); 628 } 629 630 void checkNextChar(char toRead, StringReader in, int position) 631 throws MalformedExpressionException, IOException { 632 int c = in.read(); 633 if ( c != toRead ) 634 throw new MalformedExpressionException 635 (MalformedExpressionException.SYNTAX_ERROR, position); 636 } 637 } 638 639 | Popular Tags |