[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 3 if ( !defined( 'MEDIAWIKI' ) ) { 4 die( 'This file is a MediaWiki extension, it is not a valid entry point' ); 5 } 6 7 // Character classes 8 define( 'EXPR_WHITE_CLASS', " \t\r\n" ); 9 define( 'EXPR_NUMBER_CLASS', '0123456789.' ); 10 11 // Token types 12 define( 'EXPR_WHITE', 1 ); 13 define( 'EXPR_NUMBER', 2 ); 14 define( 'EXPR_NEGATIVE', 3 ); 15 define( 'EXPR_POSITIVE', 4 ); 16 define( 'EXPR_PLUS', 5 ); 17 define( 'EXPR_MINUS', 6 ); 18 define( 'EXPR_TIMES', 7 ); 19 define( 'EXPR_DIVIDE', 8 ); 20 define( 'EXPR_MOD', 9 ); 21 define( 'EXPR_OPEN', 10 ); 22 define( 'EXPR_CLOSE', 11 ); 23 define( 'EXPR_AND', 12 ); 24 define( 'EXPR_OR', 13 ); 25 define( 'EXPR_NOT', 14 ); 26 define( 'EXPR_EQUALITY', 15 ); 27 define( 'EXPR_LESS', 16 ); 28 define( 'EXPR_GREATER', 17 ); 29 define( 'EXPR_LESSEQ', 18 ); 30 define( 'EXPR_GREATEREQ', 19 ); 31 define( 'EXPR_NOTEQ', 20 ); 32 define( 'EXPR_ROUND', 21 ); 33 define( 'EXPR_EXPONENT', 22 ); 34 define( 'EXPR_SINE', 23 ); 35 define( 'EXPR_COSINE', 24 ); 36 define( 'EXPR_TANGENS', 25 ); 37 define( 'EXPR_ARCSINE', 26 ); 38 define( 'EXPR_ARCCOS', 27 ); 39 define( 'EXPR_ARCTAN', 28 ); 40 define( 'EXPR_EXP', 29 ); 41 define( 'EXPR_LN', 30 ); 42 define( 'EXPR_ABS', 31 ); 43 define( 'EXPR_FLOOR', 32 ); 44 define( 'EXPR_TRUNC', 33 ); 45 define( 'EXPR_CEIL', 34 ); 46 define( 'EXPR_POW', 35 ); 47 define( 'EXPR_PI', 36 ); 48 define( 'EXPR_FMOD', 37 ); 49 define( 'EXPR_SQRT' , 38 ); 50 51 class ExprError extends MWException { 52 /** 53 * @param $msg string 54 * @param $parameter string 55 */ 56 public function __construct( $msg, $parameter = '' ) { 57 // Give grep a chance to find the usages: 58 // pfunc_expr_stack_exhausted, pfunc_expr_unexpected_number, pfunc_expr_preg_match_failure, 59 // pfunc_expr_unrecognised_word, pfunc_expr_unexpected_operator, pfunc_expr_missing_operand, 60 // pfunc_expr_unexpected_closing_bracket, pfunc_expr_unrecognised_punctuation, 61 // pfunc_expr_unclosed_bracket, pfunc_expr_division_by_zero, pfunc_expr_invalid_argument, 62 // pfunc_expr_invalid_argument_ln, pfunc_expr_unknown_error, pfunc_expr_not_a_number 63 $this->message = wfMessage( "pfunc_expr_$msg", $parameter )->inContentLanguage()->text(); 64 } 65 } 66 67 class ExprParser { 68 public $maxStackSize = 100; 69 70 public $precedence = array( 71 EXPR_NEGATIVE => 10, 72 EXPR_POSITIVE => 10, 73 EXPR_EXPONENT => 10, 74 EXPR_SINE => 9, 75 EXPR_COSINE => 9, 76 EXPR_TANGENS => 9, 77 EXPR_ARCSINE => 9, 78 EXPR_ARCCOS => 9, 79 EXPR_ARCTAN => 9, 80 EXPR_EXP => 9, 81 EXPR_LN => 9, 82 EXPR_ABS => 9, 83 EXPR_FLOOR => 9, 84 EXPR_TRUNC => 9, 85 EXPR_CEIL => 9, 86 EXPR_NOT => 9, 87 EXPR_SQRT => 9, 88 EXPR_POW => 8, 89 EXPR_TIMES => 7, 90 EXPR_DIVIDE => 7, 91 EXPR_MOD => 7, 92 EXPR_FMOD => 7, 93 EXPR_PLUS => 6, 94 EXPR_MINUS => 6, 95 EXPR_ROUND => 5, 96 EXPR_EQUALITY => 4, 97 EXPR_LESS => 4, 98 EXPR_GREATER => 4, 99 EXPR_LESSEQ => 4, 100 EXPR_GREATEREQ => 4, 101 EXPR_NOTEQ => 4, 102 EXPR_AND => 3, 103 EXPR_OR => 2, 104 EXPR_PI => 0, 105 EXPR_OPEN => -1, 106 EXPR_CLOSE => -1, 107 ); 108 109 public $names = array( 110 EXPR_NEGATIVE => '-', 111 EXPR_POSITIVE => '+', 112 EXPR_NOT => 'not', 113 EXPR_TIMES => '*', 114 EXPR_DIVIDE => '/', 115 EXPR_MOD => 'mod', 116 EXPR_FMOD => 'fmod', 117 EXPR_PLUS => '+', 118 EXPR_MINUS => '-', 119 EXPR_ROUND => 'round', 120 EXPR_EQUALITY => '=', 121 EXPR_LESS => '<', 122 EXPR_GREATER => '>', 123 EXPR_LESSEQ => '<=', 124 EXPR_GREATEREQ => '>=', 125 EXPR_NOTEQ => '<>', 126 EXPR_AND => 'and', 127 EXPR_OR => 'or', 128 EXPR_EXPONENT => 'e', 129 EXPR_SINE => 'sin', 130 EXPR_COSINE => 'cos', 131 EXPR_TANGENS => 'tan', 132 EXPR_ARCSINE => 'asin', 133 EXPR_ARCCOS => 'acos', 134 EXPR_ARCTAN => 'atan', 135 EXPR_LN => 'ln', 136 EXPR_EXP => 'exp', 137 EXPR_ABS => 'abs', 138 EXPR_FLOOR => 'floor', 139 EXPR_TRUNC => 'trunc', 140 EXPR_CEIL => 'ceil', 141 EXPR_POW => '^', 142 EXPR_PI => 'pi', 143 EXPR_SQRT => 'sqrt', 144 ); 145 146 public $words = array( 147 'mod' => EXPR_MOD, 148 'fmod' => EXPR_FMOD, 149 'and' => EXPR_AND, 150 'or' => EXPR_OR, 151 'not' => EXPR_NOT, 152 'round' => EXPR_ROUND, 153 'div' => EXPR_DIVIDE, 154 'e' => EXPR_EXPONENT, 155 'sin' => EXPR_SINE, 156 'cos' => EXPR_COSINE, 157 'tan' => EXPR_TANGENS, 158 'asin' => EXPR_ARCSINE, 159 'acos' => EXPR_ARCCOS, 160 'atan' => EXPR_ARCTAN, 161 'exp' => EXPR_EXP, 162 'ln' => EXPR_LN, 163 'abs' => EXPR_ABS, 164 'trunc' => EXPR_TRUNC, 165 'floor' => EXPR_FLOOR, 166 'ceil' => EXPR_CEIL, 167 'pi' => EXPR_PI, 168 'sqrt' => EXPR_SQRT, 169 ); 170 171 /** 172 * Evaluate a mathematical expression 173 * 174 * The algorithm here is based on the infix to RPN algorithm given in 175 * http://montcs.bloomu.edu/~bobmon/Information/RPN/infix2rpn.shtml 176 * It's essentially the same as Dijkstra's shunting yard algorithm. 177 * @param $expr string 178 * @throws ExprError 179 * @return string 180 */ 181 function doExpression( $expr ) { 182 $operands = array(); 183 $operators = array(); 184 185 # Unescape inequality operators 186 $expr = strtr( $expr, array( '<' => '<', '>' => '>', 187 '−' => '-', '−' => '-' ) ); 188 189 $p = 0; 190 $end = strlen( $expr ); 191 $expecting = 'expression'; 192 $name = ''; 193 194 while ( $p < $end ) { 195 if ( count( $operands ) > $this->maxStackSize || count( $operators ) > $this->maxStackSize ) { 196 throw new ExprError( 'stack_exhausted' ); 197 } 198 $char = $expr[$p]; 199 $char2 = substr( $expr, $p, 2 ); 200 201 // Mega if-elseif-else construct 202 // Only binary operators fall through for processing at the bottom, the rest 203 // finish their processing and continue 204 205 // First the unlimited length classes 206 207 if ( false !== strpos( EXPR_WHITE_CLASS, $char ) ) { 208 // Whitespace 209 $p += strspn( $expr, EXPR_WHITE_CLASS, $p ); 210 continue; 211 } elseif ( false !== strpos( EXPR_NUMBER_CLASS, $char ) ) { 212 // Number 213 if ( $expecting != 'expression' ) { 214 throw new ExprError( 'unexpected_number' ); 215 } 216 217 // Find the rest of it 218 $length = strspn( $expr, EXPR_NUMBER_CLASS, $p ); 219 // Convert it to float, silently removing double decimal points 220 $operands[] = floatval( substr( $expr, $p, $length ) ); 221 $p += $length; 222 $expecting = 'operator'; 223 continue; 224 } elseif ( ctype_alpha( $char ) ) { 225 // Word 226 // Find the rest of it 227 $remaining = substr( $expr, $p ); 228 if ( !preg_match( '/^[A-Za-z]*/', $remaining, $matches ) ) { 229 // This should be unreachable 230 throw new ExprError( 'preg_match_failure' ); 231 } 232 $word = strtolower( $matches[0] ); 233 $p += strlen( $word ); 234 235 // Interpret the word 236 if ( !isset( $this->words[$word] ) ) { 237 throw new ExprError( 'unrecognised_word', $word ); 238 } 239 $op = $this->words[$word]; 240 switch( $op ) { 241 // constant 242 case EXPR_EXPONENT: 243 if ( $expecting != 'expression' ) { 244 continue; 245 } 246 $operands[] = exp( 1 ); 247 $expecting = 'operator'; 248 continue 2; 249 case EXPR_PI: 250 if ( $expecting != 'expression' ) { 251 throw new ExprError( 'unexpected_number' ); 252 } 253 $operands[] = pi(); 254 $expecting = 'operator'; 255 continue 2; 256 // Unary operator 257 case EXPR_NOT: 258 case EXPR_SINE: 259 case EXPR_COSINE: 260 case EXPR_TANGENS: 261 case EXPR_ARCSINE: 262 case EXPR_ARCCOS: 263 case EXPR_ARCTAN: 264 case EXPR_EXP: 265 case EXPR_LN: 266 case EXPR_ABS: 267 case EXPR_FLOOR: 268 case EXPR_TRUNC: 269 case EXPR_CEIL: 270 case EXPR_SQRT: 271 if ( $expecting != 'expression' ) { 272 throw new ExprError( 'unexpected_operator', $word ); 273 } 274 $operators[] = $op; 275 continue 2; 276 } 277 // Binary operator, fall through 278 $name = $word; 279 } 280 281 // Next the two-character operators 282 283 elseif ( $char2 == '<=' ) { 284 $name = $char2; 285 $op = EXPR_LESSEQ; 286 $p += 2; 287 } elseif ( $char2 == '>=' ) { 288 $name = $char2; 289 $op = EXPR_GREATEREQ; 290 $p += 2; 291 } elseif ( $char2 == '<>' || $char2 == '!=' ) { 292 $name = $char2; 293 $op = EXPR_NOTEQ; 294 $p += 2; 295 } 296 297 // Finally the single-character operators 298 299 elseif ( $char == '+' ) { 300 ++$p; 301 if ( $expecting == 'expression' ) { 302 // Unary plus 303 $operators[] = EXPR_POSITIVE; 304 continue; 305 } else { 306 // Binary plus 307 $op = EXPR_PLUS; 308 } 309 } elseif ( $char == '-' ) { 310 ++$p; 311 if ( $expecting == 'expression' ) { 312 // Unary minus 313 $operators[] = EXPR_NEGATIVE; 314 continue; 315 } else { 316 // Binary minus 317 $op = EXPR_MINUS; 318 } 319 } elseif ( $char == '*' ) { 320 $name = $char; 321 $op = EXPR_TIMES; 322 ++$p; 323 } elseif ( $char == '/' ) { 324 $name = $char; 325 $op = EXPR_DIVIDE; 326 ++$p; 327 } elseif ( $char == '^' ) { 328 $name = $char; 329 $op = EXPR_POW; 330 ++$p; 331 } elseif ( $char == '(' ) { 332 if ( $expecting == 'operator' ) { 333 throw new ExprError( 'unexpected_operator', '(' ); 334 } 335 $operators[] = EXPR_OPEN; 336 ++$p; 337 continue; 338 } elseif ( $char == ')' ) { 339 $lastOp = end( $operators ); 340 while ( $lastOp && $lastOp != EXPR_OPEN ) { 341 $this->doOperation( $lastOp, $operands ); 342 array_pop( $operators ); 343 $lastOp = end( $operators ); 344 } 345 if ( $lastOp ) { 346 array_pop( $operators ); 347 } else { 348 throw new ExprError( 'unexpected_closing_bracket' ); 349 } 350 $expecting = 'operator'; 351 ++$p; 352 continue; 353 } elseif ( $char == '=' ) { 354 $name = $char; 355 $op = EXPR_EQUALITY; 356 ++$p; 357 } elseif ( $char == '<' ) { 358 $name = $char; 359 $op = EXPR_LESS; 360 ++$p; 361 } elseif ( $char == '>' ) { 362 $name = $char; 363 $op = EXPR_GREATER; 364 ++$p; 365 } else { 366 throw new ExprError( 'unrecognised_punctuation', UtfNormal::cleanUp( $char ) ); 367 } 368 369 // Binary operator processing 370 if ( $expecting == 'expression' ) { 371 throw new ExprError( 'unexpected_operator', $name ); 372 } 373 374 // Shunting yard magic 375 $lastOp = end( $operators ); 376 while ( $lastOp && $this->precedence[$op] <= $this->precedence[$lastOp] ) { 377 $this->doOperation( $lastOp, $operands ); 378 array_pop( $operators ); 379 $lastOp = end( $operators ); 380 } 381 $operators[] = $op; 382 $expecting = 'expression'; 383 } 384 385 // Finish off the operator array 386 while ( $op = array_pop( $operators ) ) { 387 if ( $op == EXPR_OPEN ) { 388 throw new ExprError( 'unclosed_bracket' ); 389 } 390 $this->doOperation( $op, $operands ); 391 } 392 393 return implode( "<br />\n", $operands ); 394 } 395 396 /** 397 * @param $op int 398 * @param $stack array 399 * @throws ExprError 400 */ 401 function doOperation( $op, &$stack ) { 402 switch ( $op ) { 403 case EXPR_NEGATIVE: 404 if ( count( $stack ) < 1 ) { 405 throw new ExprError( 'missing_operand', $this->names[$op] ); 406 } 407 $arg = array_pop( $stack ); 408 $stack[] = -$arg; 409 break; 410 case EXPR_POSITIVE: 411 if ( count( $stack ) < 1 ) { 412 throw new ExprError( 'missing_operand', $this->names[$op] ); 413 } 414 break; 415 case EXPR_TIMES: 416 if ( count( $stack ) < 2 ) { 417 throw new ExprError( 'missing_operand', $this->names[$op] ); 418 } 419 $right = array_pop( $stack ); 420 $left = array_pop( $stack ); 421 $stack[] = $left * $right; 422 break; 423 case EXPR_DIVIDE: 424 if ( count( $stack ) < 2 ) { 425 throw new ExprError( 'missing_operand', $this->names[$op] ); 426 } 427 $right = array_pop( $stack ); 428 $left = array_pop( $stack ); 429 if ( !$right ) { 430 throw new ExprError( 'division_by_zero', $this->names[$op] ); 431 } 432 $stack[] = $left / $right; 433 break; 434 case EXPR_MOD: 435 if ( count( $stack ) < 2 ) { 436 throw new ExprError( 'missing_operand', $this->names[$op] ); 437 } 438 $right = (int)array_pop( $stack ); 439 $left = (int)array_pop( $stack ); 440 if ( !$right ) { 441 throw new ExprError( 'division_by_zero', $this->names[$op] ); 442 } 443 $stack[] = $left % $right; 444 break; 445 case EXPR_FMOD: 446 if ( count( $stack ) < 2 ) { 447 throw new ExprError( 'missing_operand', $this->names[$op] ); 448 } 449 $right = (double)array_pop( $stack ); 450 $left = (double)array_pop( $stack ); 451 if ( !$right ) { 452 throw new ExprError( 'division_by_zero', $this->names[$op] ); 453 } 454 $stack[] = fmod( $left, $right ); 455 break; 456 case EXPR_PLUS: 457 if ( count( $stack ) < 2 ) { 458 throw new ExprError( 'missing_operand', $this->names[$op] ); 459 } 460 $right = array_pop( $stack ); 461 $left = array_pop( $stack ); 462 $stack[] = $left + $right; 463 break; 464 case EXPR_MINUS: 465 if ( count( $stack ) < 2 ) { 466 throw new ExprError( 'missing_operand', $this->names[$op] ); 467 } 468 $right = array_pop( $stack ); 469 $left = array_pop( $stack ); 470 $stack[] = $left - $right; 471 break; 472 case EXPR_AND: 473 if ( count( $stack ) < 2 ) { 474 throw new ExprError( 'missing_operand', $this->names[$op] ); 475 } 476 $right = array_pop( $stack ); 477 $left = array_pop( $stack ); 478 $stack[] = ( $left && $right ) ? 1 : 0; 479 break; 480 case EXPR_OR: 481 if ( count( $stack ) < 2 ) { 482 throw new ExprError( 'missing_operand', $this->names[$op] ); 483 } 484 $right = array_pop( $stack ); 485 $left = array_pop( $stack ); 486 $stack[] = ( $left || $right ) ? 1 : 0; 487 break; 488 case EXPR_EQUALITY: 489 if ( count( $stack ) < 2 ) { 490 throw new ExprError( 'missing_operand', $this->names[$op] ); 491 } 492 $right = array_pop( $stack ); 493 $left = array_pop( $stack ); 494 $stack[] = ( $left == $right ) ? 1 : 0; 495 break; 496 case EXPR_NOT: 497 if ( count( $stack ) < 1 ) { 498 throw new ExprError( 'missing_operand', $this->names[$op] ); 499 } 500 $arg = array_pop( $stack ); 501 $stack[] = ( !$arg ) ? 1 : 0; 502 break; 503 case EXPR_ROUND: 504 if ( count( $stack ) < 2 ) { 505 throw new ExprError( 'missing_operand', $this->names[$op] ); 506 } 507 $digits = intval( array_pop( $stack ) ); 508 $value = array_pop( $stack ); 509 $stack[] = round( $value, $digits ); 510 break; 511 case EXPR_LESS: 512 if ( count( $stack ) < 2 ) { 513 throw new ExprError( 'missing_operand', $this->names[$op] ); 514 } 515 $right = array_pop( $stack ); 516 $left = array_pop( $stack ); 517 $stack[] = ( $left < $right ) ? 1 : 0; 518 break; 519 case EXPR_GREATER: 520 if ( count( $stack ) < 2 ) { 521 throw new ExprError( 'missing_operand', $this->names[$op] ); 522 } 523 $right = array_pop( $stack ); 524 $left = array_pop( $stack ); 525 $stack[] = ( $left > $right ) ? 1 : 0; 526 break; 527 case EXPR_LESSEQ: 528 if ( count( $stack ) < 2 ) { 529 throw new ExprError( 'missing_operand', $this->names[$op] ); 530 } 531 $right = array_pop( $stack ); 532 $left = array_pop( $stack ); 533 $stack[] = ( $left <= $right ) ? 1 : 0; 534 break; 535 case EXPR_GREATEREQ: 536 if ( count( $stack ) < 2 ) { 537 throw new ExprError( 'missing_operand', $this->names[$op] ); 538 } 539 $right = array_pop( $stack ); 540 $left = array_pop( $stack ); 541 $stack[] = ( $left >= $right ) ? 1 : 0; 542 break; 543 case EXPR_NOTEQ: 544 if ( count( $stack ) < 2 ) { 545 throw new ExprError( 'missing_operand', $this->names[$op] ); 546 } 547 $right = array_pop( $stack ); 548 $left = array_pop( $stack ); 549 $stack[] = ( $left != $right ) ? 1 : 0; 550 break; 551 case EXPR_EXPONENT: 552 if ( count( $stack ) < 2 ) { 553 throw new ExprError( 'missing_operand', $this->names[$op] ); 554 } 555 $right = array_pop( $stack ); 556 $left = array_pop( $stack ); 557 $stack[] = $left * pow( 10, $right ); 558 break; 559 case EXPR_SINE: 560 if ( count( $stack ) < 1 ) { 561 throw new ExprError( 'missing_operand', $this->names[$op] ); 562 } 563 $arg = array_pop( $stack ); 564 $stack[] = sin( $arg ); 565 break; 566 case EXPR_COSINE: 567 if ( count( $stack ) < 1 ) { 568 throw new ExprError( 'missing_operand', $this->names[$op] ); 569 } 570 $arg = array_pop( $stack ); 571 $stack[] = cos( $arg ); 572 break; 573 case EXPR_TANGENS: 574 if ( count( $stack ) < 1 ) { 575 throw new ExprError( 'missing_operand', $this->names[$op] ); 576 } 577 $arg = array_pop( $stack ); 578 $stack[] = tan( $arg ); 579 break; 580 case EXPR_ARCSINE: 581 if ( count( $stack ) < 1 ) { 582 throw new ExprError( 'missing_operand', $this->names[$op] ); 583 } 584 $arg = array_pop( $stack ); 585 if ( $arg < -1 || $arg > 1 ) { 586 throw new ExprError( 'invalid_argument', $this->names[$op] ); 587 } 588 $stack[] = asin( $arg ); 589 break; 590 case EXPR_ARCCOS: 591 if ( count( $stack ) < 1 ) { 592 throw new ExprError( 'missing_operand', $this->names[$op] ); 593 } 594 $arg = array_pop( $stack ); 595 if ( $arg < -1 || $arg > 1 ) { 596 throw new ExprError( 'invalid_argument', $this->names[$op] ); 597 } 598 $stack[] = acos( $arg ); 599 break; 600 case EXPR_ARCTAN: 601 if ( count( $stack ) < 1 ) { 602 throw new ExprError( 'missing_operand', $this->names[$op] ); 603 } 604 $arg = array_pop( $stack ); 605 $stack[] = atan( $arg ); 606 break; 607 case EXPR_EXP: 608 if ( count( $stack ) < 1 ) { 609 throw new ExprError( 'missing_operand', $this->names[$op] ); 610 } 611 $arg = array_pop( $stack ); 612 $stack[] = exp( $arg ); 613 break; 614 case EXPR_LN: 615 if ( count( $stack ) < 1 ) { 616 throw new ExprError( 'missing_operand', $this->names[$op] ); 617 } 618 $arg = array_pop( $stack ); 619 if ( $arg <= 0 ) { 620 throw new ExprError( 'invalid_argument_ln', $this->names[$op] ); 621 } 622 $stack[] = log( $arg ); 623 break; 624 case EXPR_ABS: 625 if ( count( $stack ) < 1 ) { 626 throw new ExprError( 'missing_operand', $this->names[$op] ); 627 } 628 $arg = array_pop( $stack ); 629 $stack[] = abs( $arg ); 630 break; 631 case EXPR_FLOOR: 632 if ( count( $stack ) < 1 ) { 633 throw new ExprError( 'missing_operand', $this->names[$op] ); 634 } 635 $arg = array_pop( $stack ); 636 $stack[] = floor( $arg ); 637 break; 638 case EXPR_TRUNC: 639 if ( count( $stack ) < 1 ) { 640 throw new ExprError( 'missing_operand', $this->names[$op] ); 641 } 642 $arg = array_pop( $stack ); 643 $stack[] = (int)$arg; 644 break; 645 case EXPR_CEIL: 646 if ( count( $stack ) < 1 ) { 647 throw new ExprError( 'missing_operand', $this->names[$op] ); 648 } 649 $arg = array_pop( $stack ); 650 $stack[] = ceil( $arg ); 651 break; 652 case EXPR_POW: 653 if ( count( $stack ) < 2 ) { 654 throw new ExprError( 'missing_operand', $this->names[$op] ); 655 } 656 $right = array_pop( $stack ); 657 $left = array_pop( $stack ); 658 if ( false === ( $stack[] = pow( $left, $right ) ) ) { 659 throw new ExprError( 'division_by_zero', $this->names[$op] ); 660 } 661 break; 662 case EXPR_SQRT: 663 if ( count( $stack ) < 1 ) { 664 throw new ExprError( 'missing_operand', $this->names[$op] ); 665 } 666 $arg = array_pop( $stack ); 667 $result = sqrt( $arg ); 668 if ( is_nan( $result ) ) { 669 throw new ExprError( 'not_a_number', $this->names[$op] ); 670 } 671 $stack[] = $result; 672 break; 673 default: 674 // Should be impossible to reach here. 675 throw new ExprError( 'unknown_error' ); 676 } 677 } 678 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |