function ctools_math_expr::pfx in Chaos Tool Suite (ctools) 6
Same name and namespace in other branches
- 7 includes/math-expr.inc \ctools_math_expr::pfx()
1 call to ctools_math_expr::pfx()
- ctools_math_expr::evaluate in includes/
math-expr.inc
File
- includes/
math-expr.inc, line 295
Class
Code
function pfx($tokens, $vars = array()) {
if ($tokens == false) {
return false;
}
$stack = new ctools_math_expr_stack();
foreach ($tokens as $token) {
// nice and easy
// if the token is a binary operator, pop two values off the stack, do the operation, and push the result back on
if (in_array($token, array(
'+',
'-',
'*',
'/',
'^',
))) {
if (is_null($op2 = $stack
->pop())) {
return $this
->trigger("internal error");
}
if (is_null($op1 = $stack
->pop())) {
return $this
->trigger("internal error");
}
switch ($token) {
case '+':
$stack
->push($op1 + $op2);
break;
case '-':
$stack
->push($op1 - $op2);
break;
case '*':
$stack
->push($op1 * $op2);
break;
case '/':
if ($op2 == 0) {
return $this
->trigger("division by zero");
}
$stack
->push($op1 / $op2);
break;
case '^':
$stack
->push(pow($op1, $op2));
break;
}
// if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
}
elseif ($token == "_") {
$stack
->push(-1 * $stack
->pop());
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
}
elseif (preg_match("/^([a-z]\\w*)\\(\$/", $token, $matches)) {
// it's a function!
$fnn = $matches[1];
if (in_array($fnn, $this->fb)) {
// built-in function:
if (is_null($op1 = $stack
->pop())) {
return $this
->trigger("internal error");
}
$fnn = preg_replace("/^arc/", "a", $fnn);
// for the 'arc' trig synonyms
if ($fnn == 'ln') {
$fnn = 'log';
}
eval('$stack->push(' . $fnn . '($op1));');
// perfectly safe eval()
}
elseif (array_key_exists($fnn, $this->f)) {
// user function
// get args
$args = array();
for ($i = count($this->f[$fnn]['args']) - 1; $i >= 0; $i--) {
if (is_null($args[$this->f[$fnn]['args'][$i]] = $stack
->pop())) {
return $this
->trigger("internal error");
}
}
$stack
->push($this
->pfx($this->f[$fnn]['func'], $args));
// yay... recursion!!!!
}
// if the token is a number or variable, push it on the stack
}
else {
if (is_numeric($token)) {
$stack
->push($token);
}
elseif (array_key_exists($token, $this->v)) {
$stack
->push($this->v[$token]);
}
elseif (array_key_exists($token, $vars)) {
$stack
->push($vars[$token]);
}
else {
return $this
->trigger("undefined variable '{$token}'");
}
}
}
// when we're out of tokens, the stack should have a single element, the final result
if ($stack->count != 1) {
return $this
->trigger("internal error");
}
return $stack
->pop();
}