private function evaluatePostfixNotation($tokens, $variables = array())
 {
     if ($tokens == false) {
         return false;
     }
     $stack = new Stack();
     foreach ($tokens as $token) {
         if (in_array($token, array('+', '-', '*', '/', '^', '%'))) {
             $lastOperatorTwo = $stack->pop();
             $lastOperatorOne = $stack->pop();
             if (is_null($lastOperatorOne)) {
                 return $this->raiseError('Internal error');
             }
             if (is_null($lastOperatorTwo)) {
                 return $this->raiseError('Internal error');
             }
             switch ($token) {
                 case '+':
                     $stack->push($this->executionEngine->add($lastOperatorOne, $lastOperatorTwo));
                     break;
                 case '-':
                     $stack->push($this->executionEngine->subtract($lastOperatorOne, $lastOperatorTwo));
                     break;
                 case '*':
                     $stack->push($this->executionEngine->multiply($lastOperatorOne, $lastOperatorTwo));
                     break;
                 case '/':
                     if ($lastOperatorTwo == 0) {
                         return $this->raiseError('Divide by zero error.');
                     }
                     $stack->push($this->executionEngine->divide($lastOperatorOne, $lastOperatorTwo));
                     break;
                 case '^':
                     $stack->push($this->executionEngine->pow($lastOperatorOne, $lastOperatorTwo));
                     break;
                 case '%':
                     $stack->push($this->executionEngine->mod($lastOperatorOne, $lastOperatorTwo));
                     break;
             }
         } elseif ($token == '_') {
             // If the token is a unary operator, pop one value off the stack and
             // then do the operation, then push it back on.
             $stack->push(-1 * $stack->pop());
         } elseif (preg_match("/^([a-z]\\w*)\\(\$/", $token, $matches)) {
             // If the token is a function, pop arguments off the stack, hand them to
             // the function and push the result back on.
             $functionName = $matches[1];
             if (in_array($functionName, $this->functions)) {
                 // The function name is one of the default functions.
                 $lastOperatorOne = $stack->pop();
                 if (is_null($lastOperatorOne)) {
                     return $this->raiseError('Internal error.');
                 }
                 // Handles the 'arc' trig synonyms.
                 $functionName = preg_replace("/^arc/", "a", $functionName);
                 // Converts 'ln' into the 'log' function name.
                 if ($functionName == 'ln') {
                     $functionName = 'log';
                 }
                 // Here the original code had an eval statement. We are going to try and do
                 // away with that and handle the function execution ourself. We will also do
                 // this so that this driver can use the MathExecutionEngine implementation.
                 // This piece of code will look-up a function on the MathExecutionEngine
                 // implementation and call an instance method on the implementation. We do this
                 // so that we do not have to define a use-case for each and every function
                 // that the driver may encounter.
                 if (in_array($functionName, $this->functions)) {
                     $stack->push($this->executionEngine->{$functionName}($lastOperatorOne));
                 }
             } elseif (array_key_exists($functionName, $this->userFunctions)) {
                 // This is a user defined function.
                 $arguments = array();
                 for ($i = count($this->userFunctions[$functionName]['args']) - 1; $i >= 0; $i--) {
                     if (is_null($arguments[$this->userFunctions[$functionName]['args'][$i]] = $stack->pop())) {
                         return $this->raiseError('Internal error.');
                     }
                 }
                 $stack->push($this->evaluatePostfixNotation($this->userFunctions[$functionName]['func'], $arguments));
             }
         } else {
             if (is_numeric($token)) {
                 $stack->push($token);
             } elseif (array_key_exists($token, $this->constants)) {
                 $stack->push($this->constants[$token]);
             } elseif (array_key_exists($token, $variables)) {
                 $stack->push($variables[$token]);
             } else {
                 return $this->raiseError('Undefined variable \'' . $token . '\'');
             }
         }
     }
     // After there are no more tokens, the stack should have the final result.
     if ($stack->getCount() != 1) {
         return $this->raiseError('Internal error');
     }
     // Return the result.
     return $stack->pop();
 }
Beispiel #2
0
 /**
  * Calculates the factorial of a number.
  *
  * @param  number $number
  * @return number
  */
 public function factorial($number)
 {
     return $this->executionEngine->factorial($number);
 }