/** * Tokenize a soap type * * @param string $type Type * * @return array Tokens */ public static function tokenize($type) { $stack = new Stack(); $stack->push(SOAP_STATE_DEFAULT); $stack->push(SOAP_STATE_TYPE); $tokens = array(); $token = ''; $len = strlen($type); // We don't actually care whether we're inside of a type or not // That's why there aren't separate states for inside and outside of braces for ($pos = 0; $pos < $len; ++$pos) { $char = $type[$pos]; $nextChar = isset($type[$pos + 1]) ? $type[$pos + 1] : null; switch ($stack->top()) { case SOAP_STATE_DEFAULT: if (ctype_alnum($nextChar)) { $stack->push(SOAP_STATE_TYPE); } elseif (in_array($char, self::$whitespace)) { $tokens[] = array('code' => SOAP_WHITESPACE, 'token' => $char); } elseif ($char === '{') { $tokens[] = array('code' => SOAP_OPEN_BRACE, 'token' => $char); } elseif ($char === '}') { $tokens[] = array('code' => SOAP_CLOSE_BRACE, 'token' => $char); } elseif ($char === ';') { $tokens[] = array('code' => SOAP_SEMICOLON, 'token' => $char); } break; case SOAP_STATE_TYPE: if (ctype_alnum($char)) { $token .= $char; if ($nextChar === ' ') { if (in_array($token, self::$nativeTypes)) { $tokens[] = array('code' => SOAP_NATIVE_TYPE, 'token' => $token); } else { $tokens[] = array('code' => SOAP_USER_TYPE, 'token' => $token); } $token = ''; $stack->pop(); $stack->push(SOAP_STATE_PROPERTY); } } break; case SOAP_STATE_PROPERTY: if (ctype_alnum($char)) { $token .= $char; if ($nextChar === ';' || $nextChar === ' ' || $nextChar === null) { $tokens[] = array('code' => SOAP_PROPERTY, 'token' => $token); $token = ''; $stack->pop(); } } elseif ($char === ' ') { $tokens[] = array('code' => SOAP_WHITESPACE, 'token' => $char); } break; } } return $tokens; }
function get_polish_notation($expression) { $current_op_stack = new Stack(); $outstring = ''; for ($i = 0; $i < strlen($expression); $i++) { if ($expression[$i] == ')') { while ($current_op_stack->top() != '(') { $outstring .= $current_op_stack->pop(); } $current_op_stack->pop(); } if ($expression[$i] == '(') { $current_op_stack->push($expression[$i]); } if ($expression[$i] == '-' or $expression[$i] == '+' or $expression[$i] == '*' or $expression[$i] == '/' or $expression[$i] == '^') { if ($current_op_stack->is_empty()) { $current_op_stack->push($expression[$i]); } elseif (spot_priority($expression[$i]) > spot_priority($current_op_stack->top())) { $current_op_stack->push($expression[$i]); } else { while (!$current_op_stack->is_empty() and spot_priority($current_op_stack->top()) >= spot_priority($expression[$i])) { $outstring .= $current_op_stack->pop(); } $current_op_stack->push($expression[$i]); } } if (is_numeric($expression[$i])) { $outstring .= '.'; do { $outstring .= $expression[$i]; } while (is_numeric($expression[++$i])); --$i; } } while (!$current_op_stack->is_empty()) { $outstring .= $current_op_stack->pop(); } return $outstring; }
/** * Vrátí aktuální blok * * @returns Block */ protected function getActualBlock() { return $this->stack->top(); }
/** * Vyhodnocení výrazu * * @param array * @return array */ protected function evaluateExpression(array $expr) { if ($expr[0] != 'expression') { return $this->reduceValue($expr); } array_shift($expr); //převod výrazu do postfixové notace $postfix = array(); $stack = new Stack(); foreach ($expr as $symbol) { if ($symbol == '(') { $stack->push($symbol); } elseif ($symbol == ')') { while ($top = $stack->pop()) { if ($top == '(') { break; } $postfix[] = $top; } $top = $stack->top(); if ($top[0] == 'unary' && array_key_exists($top[1], Compiler::$unaryOperators)) { $postfix[] = $stack->pop(); } } elseif ($symbol[0] == 'binary' && array_key_exists($symbol[1], Compiler::$binaryOperators)) { if ($stack->count() == 0) { $stack->push($symbol); continue; } $top = $stack->top(); while ($top != '(' && $stack->count() > 0 && $top[0] == 'binary' && Compiler::$binaryOperators[$symbol[1]] <= Compiler::$binaryOperators[$top[1]]) { $postfix[] = $stack->pop(); $top = $stack->top(); } $stack->push($symbol); } elseif ($symbol[0] == 'unary' && array_key_exists($symbol[1], Compiler::$unaryOperators)) { $stack->push($symbol); } else { $postfix[] = $this->reduceValue($symbol); $top = $stack->top(); if ($top[0] == 'unary' && array_key_exists($top[1], Compiler::$unaryOperators)) { $postfix[] = $stack->pop(); } } } while ($stack->count() > 0) { $postfix[] = $stack->pop(); } //vyhodnocení výrazu $stack->clear(); foreach ($postfix as $symbol) { if ($symbol[0] == 'unary' && array_key_exists($symbol[1], Compiler::$unaryOperators)) { if ($stack->count() < 1) { throw new CompileException("Nedostatek operandů pro unární operátor '{$symbol['1']}'"); } $symbol = $this->evaluateUnaryOperation($symbol[1], $stack->pop()); } elseif ($symbol[0] == 'binary' && array_key_exists($symbol[1], Compiler::$binaryOperators)) { if ($stack->count() < 2) { throw new CompileException("Nedostatek operandů pro binární operátor '{$symbol['1']}'"); } $value2 = $stack->pop(); $symbol = $this->evaluateBinaryOperation($symbol[1], $stack->pop(), $value2); } $stack->push($symbol); } if ($stack->count() != 1) { throw new CompileException("Výsledkem výrazu má být pouze 1 hodnota"); } return $stack->pop(); }
public function run() { $this->variables = []; $token = $this->scanner->next(TRUE); $stack = new Stack(); $stack->push('$'); do { $a = $stack->topTerminal(); try { switch ($this->getFromTable($a, $token)) { case '=': debug::printString(debug::TYPE_PRECEDENCE, "= so push token"); $stack->push($token); $token = $this->scanner->next(TRUE); break; case '<': debug::printString(debug::TYPE_PRECEDENCE, "< so push < and token"); $stack->pushTerminal('<'); $stack->push($token); $token = $this->scanner->next(TRUE); break; case '>': // Hledáme pravidlo! $found = FALSE; foreach ($this->rules as $key => $rule) { $error = FALSE; for ($i = 0; $i < count($rule['source']); $i++) { $tmp = $stack->top($i); if (is_array($tmp) && !isset($tmp['nonTerminal'])) { $tmp = $this->normalizeCodes($tmp); } if (is_array($tmp) && $tmp['nonTerminal'] != $rule['source'][count($rule['source']) - 1 - $i] || !is_array($tmp) && $tmp != $rule['source'][count($rule['source']) - 1 - $i]) { $error = TRUE; $i = count($rule['source']); } } $error = $error || $stack->top(count($rule['source'])) != '<'; if (!$error) { $result = []; foreach ($rule['source'] as $unused) { $result[] = $stack->pop(); } $stack->pop(); $stack->push(['nonTerminal' => $rule['target'], 'terminals' => $result]); $found = TRUE; break; } } if (!$found) { $stack->debug(); throw new PrecedenceException("Error - rule not found! " . print_r($token, TRUE) . " " . print_r($a, TRUE)); } else { debug::printString(debug::TYPE_PRECEDENCE, "rule: " . $key . " " . $rule['target'] . " -> " . implode(' ', $rule['source'])); } break; case '#': if ($a == '$' && in_array($token['code'], $this->stopTokens)) { $this->scanner->back(); $token = ['code' => T_SEMICOLON, 'value' => ';']; } else { throw new PrecedenceException(print_r($a, TRUE) . print_r($token, TRUE)); } break; default: die("Chyba v precedenční tabulce"); } // This solve function calls with any argument number try { $e1 = $stack->top(); $comma = $stack->top(1); $e2 = $stack->top(2); if (isset($e1['nonTerminal']) && $e1['nonTerminal'] == 'E' && isset($comma['code']) && $comma['code'] == T_COMMA && isset($e2['nonTerminal']) && $e2['nonTerminal'] == 'E') { $stack->pop(); $stack->pop(); $stack->pop(); $stack->push(['nonTerminal' => 'E', 'terminals' => [$e1, $comma, $e2]]); $stack->debug(); echo "\n"; } } catch (StackEmptyException $e) { } } catch (PrecedenceNotInTableException $e) { $this->scanner->back(); $token = ['code' => T_SEMICOLON, 'value' => ';']; } debug::printStack(debug::TYPE_PRECEDENCE, $stack); } while ($this->normalizeCodes($token) != '$' || $stack->topTerminal() != '$'); $this->result = $stack->top(); }
* @param mixed $el Element to be pushed. * @return void. */ public function push($el) { array_push($this->_data, $el); } /** * Pop the top element of the stack. * * @return mixed $element. */ public function pop() { if ($this->top() !== null) { return array_pop($this->_data); } return null; } } // Example usage: $stack = new Stack(); $stack->push("Element"); $stack->push(23); $stack->push(array(3, 4, 6)); while (!$stack->is_empty()) { var_dump($stack->top()); $stack->pop(); } // Outputs NULL var_dump($stack->top());