/** * Rearranges tokens according to RPN (Reverse Polish Notation) or * also known as Postfix Notation. * * @param array $tokens * @return \SplQueue * @throws \InvalidArgumentException */ public function getReversePolishNotation(array $tokens) { $queue = new \SplQueue(); $stack = new \SplStack(); $tokensCount = count($tokens); for ($i = 0; $i < $tokensCount; $i++) { if (is_numeric($tokens[$i])) { // (string + 0) converts to int or float $queue->enqueue($tokens[$i] + 0); } else { if (array_key_exists($tokens[$i], $this->_functions)) { $stack->push($tokens[$i]); } else { if ($tokens[$i] === self::FUNC_ARG_SEPARATOR) { // checking whether stack contains left parenthesis (dirty hack) if (substr_count($stack->serialize(), '(') === 0) { throw new \InvalidArgumentException('Parenthesis are misplaced'); } while ($stack->top() != '(') { $queue->enqueue($stack->pop()); } } else { if (in_array($tokens[$i], $this->_operators)) { while ($stack->count() > 0 && in_array($stack->top(), $this->_operators) && ($this->isOperatorLeftAssociative($tokens[$i]) && $this->getOperatorPrecedence($tokens[$i]) === $this->getOperatorPrecedence($stack->top()) || $this->getOperatorPrecedence($tokens[$i]) < $this->getOperatorPrecedence($stack->top()))) { $queue->enqueue($stack->pop()); } $stack->push($tokens[$i]); } else { if ($tokens[$i] === '(') { $stack->push('('); } else { if ($tokens[$i] === ')') { // checking whether stack contains left parenthesis (dirty hack) if (substr_count($stack->serialize(), '(') === 0) { throw new \InvalidArgumentException('Parenthesis are misplaced'); } while ($stack->top() != '(') { $queue->enqueue($stack->pop()); } $stack->pop(); if ($stack->count() > 0 && array_key_exists($stack->top(), $this->_functions)) { $queue->enqueue($stack->pop()); } } } } } } } } while ($stack->count() > 0) { $queue->enqueue($stack->pop()); } return $queue; }