public function testInsertAndRemove() { $Stack = new Stack(); $Stack->push('Radig'); $this->assertIdentical($Stack->size(), 1); $this->assertIdentical($Stack->nth(), 'Radig'); $Stack->push('CakePHP'); $this->assertIdentical($Stack->size(), 2); // testa com 1-lookahead $this->assertIdentical($Stack->nth(), 'CakePHP'); // teste com 2-lookahead $this->assertIdentical($Stack->nth(2), 'Radig'); $this->assertIdentical($Stack->pop(), 'CakePHP'); $this->assertIdentical($Stack->pop(), 'Radig'); $this->assertIdentical($Stack->pop(), null); unset($Stack); }
/** * Evaluate postfix notation * * @param array $tokens * @param array $vars * * @return mixed boolean *false* in failures and *numeric* value in success */ protected function pfx($tokens, $vars = array()) { bcscale($this->precision); if ($tokens === false) { return false; } $stack = new Stack(); foreach ($tokens as $token) { // 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()) || is_null($op1 = $stack->pop())) { return $this->error("Internal error"); } switch ($token) { case '+': $stack->push(bcadd($op1, $op2)); break; case '-': $stack->push(bcsub($op1, $op2)); break; case '*': $stack->push(bcmul($op1, $op2)); break; case '/': if ($op2 == 0) { return $this->error("Division by zero"); } $stack->push(bcdiv($op1, $op2)); break; case '^': $stack->push(bcpow($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 == "_") { // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on $stack->push(-1 * $stack->pop()); } elseif (preg_match("/^([a-z]\\w*)\\(\$/", $token, $matches)) { // it's a function! $fnn = $matches[1]; // built-in function: if (in_array($fnn, $this->fb)) { if (is_null($op1 = $stack->pop())) { return $this->error("Internal error"); } // for the 'arc' trig synonyms $fnn = preg_replace("/^arc/", "a", $fnn); if ($fnn == 'ln') { $fnn = 'log'; } if ($fnn == 'sqrt') { $fnn = 'bcsqrt'; } $val = $this->strictPrecision(call_user_func($fnn, $op1)); $stack->push($val); } elseif (array_key_exists($fnn, $this->f)) { // 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->error("Internal error"); } } $stack->push($this->pfx($this->f[$fnn]['func'], $args)); // yay... recursion!!!! } } else { if (is_numeric($token)) { $stack->push($this->strictPrecision($token)); } elseif (array_key_exists($token, $this->v)) { $stack->push($this->strictPrecision($this->v[$token])); } elseif (array_key_exists($token, $vars)) { $stack->push($this->strictPrecision($vars[$token])); } else { return $this->error("Undefined variable '{$token}'"); } } } // when we're out of tokens, the stack should have a single element, the final result if ($stack->size() != 1) { return $this->error("Internal error"); } return $stack->pop(); }