185 # Unescape inequality operators
186 $expr =
strtr( $expr, [
'<' =>
'<',
'>' =>
'>',
187 '−' =>
'-',
'−' =>
'-' ] );
191 $expecting =
'expression';
194 while ( $p < $end ) {
195 if ( count( $operands ) > $this->maxStackSize || count( $operators ) > $this->maxStackSize ) {
196 throw new ExprError(
'stack_exhausted' );
199 $char2 =
substr( $expr, $p, 2 );
215 if ( $expecting !==
'expression' ) {
216 throw new ExprError(
'unexpected_number' );
224 $expecting =
'operator';
229 $remaining =
substr( $expr, $p );
232 throw new ExprError(
'preg_match_failure' );
238 if ( !
isset( $this->words[$word] ) ) {
239 throw new ExprError(
'unrecognised_word', $word );
241 $op = $this->words[
$word];
245 if ( $expecting !==
'expression' ) {
248 $operands[] =
exp( 1 );
249 $expecting =
'operator';
252 if ( $expecting !==
'expression' ) {
253 throw new ExprError(
'unexpected_number' );
256 $expecting =
'operator';
273 if ( $expecting !==
'expression' ) {
274 throw new ExprError(
'unexpected_operator', $word );
281 }
elseif ( $char2 ===
'<=' ) {
285 }
elseif ( $char2 ===
'>=' ) {
289 }
elseif ( $char2 ===
'<>' || $char2 ===
'!=' ) {
293 }
elseif ( $char ===
'+' ) {
295 if ( $expecting ===
'expression' ) {
303 }
elseif ( $char ===
'-' ) {
305 if ( $expecting ===
'expression' ) {
313 }
elseif ( $char ===
'*' ) {
317 }
elseif ( $char ===
'/' ) {
321 }
elseif ( $char ===
'^' ) {
325 }
elseif ( $char ===
'(' ) {
326 if ( $expecting ===
'operator' ) {
327 throw new ExprError(
'unexpected_operator',
'(' );
332 }
elseif ( $char ===
')' ) {
333 $lastOp = end( $operators );
334 while ( $lastOp && $lastOp !=
EXPR_OPEN ) {
337 $lastOp = end( $operators );
342 throw new ExprError(
'unexpected_closing_bracket' );
344 $expecting =
'operator';
347 }
elseif ( $char ===
'=' ) {
351 }
elseif ( $char ===
'<' ) {
355 }
elseif ( $char ===
'>' ) {
360 $utfExpr = Validator::cleanUp(
substr( $expr, $p ) );
365 if ( $expecting ===
'expression' ) {
366 throw new ExprError(
'unexpected_operator', $name );
370 $lastOp = end( $operators );
371 while ( $lastOp && $this->precedence[$op] <= $this->precedence[$lastOp] ) {
374 $lastOp = end( $operators );
377 $expecting =
'expression';
382 while ( $op =
array_pop( $operators ) ) {
385 throw new ExprError(
'unclosed_bracket' );
390 return implode(
"<br />\n", $operands );
401 if ( count( $stack ) < 1 ) {
402 throw new ExprError(
'missing_operand', $this->names[$op] );
408 if ( count( $stack ) < 1 ) {
409 throw new ExprError(
'missing_operand', $this->names[$op] );
413 if ( count( $stack ) < 2 ) {
414 throw new ExprError(
'missing_operand', $this->names[$op] );
418 $stack[] = $left *
$right;
421 if ( count( $stack ) < 2 ) {
422 throw new ExprError(
'missing_operand', $this->names[$op] );
427 throw new ExprError(
'division_by_zero', $this->names[$op] );
429 $stack[] = $left /
$right;
432 if ( count( $stack ) < 2 ) {
433 throw new ExprError(
'missing_operand', $this->names[$op] );
438 throw new ExprError(
'division_by_zero', $this->names[$op] );
440 $stack[] = $left %
$right;
443 if ( count( $stack ) < 2 ) {
444 throw new ExprError(
'missing_operand', $this->names[$op] );
449 throw new ExprError(
'division_by_zero', $this->names[$op] );
451 $stack[] =
fmod( $left, $right );
454 if ( count( $stack ) < 2 ) {
455 throw new ExprError(
'missing_operand', $this->names[$op] );
459 $stack[] = $left +
$right;
462 if ( count( $stack ) < 2 ) {
463 throw new ExprError(
'missing_operand', $this->names[$op] );
467 $stack[] = $left -
$right;
470 if ( count( $stack ) < 2 ) {
471 throw new ExprError(
'missing_operand', $this->names[$op] );
475 $stack[] = ( $left &&
$right ) ? 1 : 0;
478 if ( count( $stack ) < 2 ) {
479 throw new ExprError(
'missing_operand', $this->names[$op] );
483 $stack[] = ( $left ||
$right ) ? 1 : 0;
486 if ( count( $stack ) < 2 ) {
487 throw new ExprError(
'missing_operand', $this->names[$op] );
491 $stack[] = ( $left ==
$right ) ? 1 : 0;
494 if ( count( $stack ) < 1 ) {
495 throw new ExprError(
'missing_operand', $this->names[$op] );
498 $stack[] = ( !
$arg ) ? 1 : 0;
501 if ( count( $stack ) < 2 ) {
502 throw new ExprError(
'missing_operand', $this->names[$op] );
509 if ( count( $stack ) < 2 ) {
510 throw new ExprError(
'missing_operand', $this->names[$op] );
514 $stack[] = ( $left <
$right ) ? 1 : 0;
517 if ( count( $stack ) < 2 ) {
518 throw new ExprError(
'missing_operand', $this->names[$op] );
522 $stack[] = ( $left >
$right ) ? 1 : 0;
525 if ( count( $stack ) < 2 ) {
526 throw new ExprError(
'missing_operand', $this->names[$op] );
530 $stack[] = ( $left <=
$right ) ? 1 : 0;
533 if ( count( $stack ) < 2 ) {
534 throw new ExprError(
'missing_operand', $this->names[$op] );
538 $stack[] = ( $left >=
$right ) ? 1 : 0;
541 if ( count( $stack ) < 2 ) {
542 throw new ExprError(
'missing_operand', $this->names[$op] );
546 $stack[] = ( $left !=
$right ) ? 1 : 0;
549 if ( count( $stack ) < 2 ) {
550 throw new ExprError(
'missing_operand', $this->names[$op] );
554 $stack[] = $left *
pow( 10, $right );
557 if ( count( $stack ) < 1 ) {
558 throw new ExprError(
'missing_operand', $this->names[$op] );
561 $stack[] =
sin( $arg );
564 if ( count( $stack ) < 1 ) {
565 throw new ExprError(
'missing_operand', $this->names[$op] );
568 $stack[] =
cos( $arg );
571 if ( count( $stack ) < 1 ) {
572 throw new ExprError(
'missing_operand', $this->names[$op] );
575 $stack[] =
tan( $arg );
578 if ( count( $stack ) < 1 ) {
579 throw new ExprError(
'missing_operand', $this->names[$op] );
582 if ( $arg < -1 || $arg > 1 ) {
583 throw new ExprError(
'invalid_argument', $this->names[$op] );
585 $stack[] =
asin( $arg );
588 if ( count( $stack ) < 1 ) {
589 throw new ExprError(
'missing_operand', $this->names[$op] );
592 if ( $arg < -1 || $arg > 1 ) {
593 throw new ExprError(
'invalid_argument', $this->names[$op] );
595 $stack[] =
acos( $arg );
598 if ( count( $stack ) < 1 ) {
599 throw new ExprError(
'missing_operand', $this->names[$op] );
602 $stack[] =
atan( $arg );
605 if ( count( $stack ) < 1 ) {
606 throw new ExprError(
'missing_operand', $this->names[$op] );
609 $stack[] =
exp( $arg );
612 if ( count( $stack ) < 1 ) {
613 throw new ExprError(
'missing_operand', $this->names[$op] );
617 throw new ExprError(
'invalid_argument_ln', $this->names[$op] );
619 $stack[] = log( $arg );
622 if ( count( $stack ) < 1 ) {
623 throw new ExprError(
'missing_operand', $this->names[$op] );
626 $stack[] =
abs( $arg );
629 if ( count( $stack ) < 1 ) {
630 throw new ExprError(
'missing_operand', $this->names[$op] );
633 $stack[] =
floor( $arg );
636 if ( count( $stack ) < 1 ) {
637 throw new ExprError(
'missing_operand', $this->names[$op] );
640 $stack[] = (
int)$arg;
643 if ( count( $stack ) < 1 ) {
644 throw new ExprError(
'missing_operand', $this->names[$op] );
647 $stack[] =
ceil( $arg );
650 if ( count( $stack ) < 2 ) {
651 throw new ExprError(
'missing_operand', $this->names[$op] );
655 $result =
pow( $left, $right );
656 if ( $result ===
false ) {
657 throw new ExprError(
'division_by_zero', $this->names[$op] );
662 if ( count( $stack ) < 1 ) {
663 throw new ExprError(
'missing_operand', $this->names[$op] );
666 $result =
sqrt( $arg );
667 if (
is_nan( $result ) ) {
668 throw new ExprError(
'not_a_number', $this->names[$op] );