public function testRewindDouble() { $stack = new ezcDocumentRstStack(); $array = array(); array_unshift($array, 1); array_unshift($array, 23); $stack->unshift(1); $stack->unshift(23); $this->assertSame(reset($array), $stack->rewind()); }
/** * Shift- / reduce-parser for RST token stack * * @param array $tokens * @return void */ public function parse(array $tokens) { $tokens = new ezcDocumentRstStack($tokens); /* DEBUG echo "\n\nStart parser\n============\n\n"; // /DEBUG */ while (($token = $tokens->shift()) !== null) { /* DEBUG echo "[T] Token: " . ezcDocumentRstToken::getTokenName( $token->type ) . " ({$token->type}) at {$token->line}:{$token->position}.\n"; // /DEBUG */ // First shift given token by the defined reduction methods foreach ($this->shifts[$token->type] as $method) { /* DEBUG echo " [S] Try $method\n"; // /DEBUG */ if (($node = $this->{$method}($token, $tokens)) === false) { // The shift method cannot handle the token, go to next continue; } /* DEBUG echo " [=> Skip used.\n"; // /DEBUG */ if ($node === true) { // The shift method handled the token, but did not return a // new node, we just go to the next token... continue 2; } // Call reduce methods for nodes as long the reduction methods // recreate some node $ruleNumber = 0; $ruleType = 0; do { // Reset the rule counter on changes of the node type if ($ruleType !== $node->type) { $ruleNumber = 0; } if (!isset($this->reductions[$node->type]) || !isset($this->reductions[$node->type][$ruleNumber])) { // If there are no reduction rules for the node, just // add it to the stack /* DEBUG echo " [R] Add '" . ezcDocumentRstNode::getTokenName( $node->type ) . "' to stack (" . ( count( $this->documentStack ) + 1 ) . " elements).\n"; // /DEBUG */ $this->documentStack->unshift($node); break; } $ruleType = $node->type; $reduction = $this->reductions[$node->type][$ruleNumber++]; /* DEBUG echo " [R] Reduce with $reduction.\n"; // /DEBUG */ $node = $this->{$reduction}($node); } while ($node !== null); // We found a matching rule, so that we can leave the loop break; } } // Check if we successfully reduced the document stack if (count($this->documentStack) !== 1 || !($document = $this->documentStack->rewind()) instanceof ezcDocumentRstDocumentNode) { $node = isset($document) ? $document : $this->documentStack->rewind(); $this->triggerError(E_PARSE, 'Expected end of file, got: ' . ezcDocumentRstNode::getTokenName($node->type) . ".", null, null, null); } /* DEBUG // echo "\nResulting document:\n\n", $document->dump(), "\nTest result: "; // /DEBUG */ return $document; }