/** * Find a token in the tokenizer. You can search by the token's literal code or name. You can also specify on * offset for the search. If the offset is negative, the search will be done starting from the end. * * @param string|integer $search The token's literal code or name. * @param integer $offset The offset to start searching from. A negative offest searches from the end. * @return integer|boolean The index of the token that has been found or false. */ public function findToken($search, $offset = 0) { if ($search === null) { throw new \InvalidArgumentException('A token cannot be searched for with a null value.'); } elseif (!is_int($offset)) { throw new \InvalidArgumentException('On offset must be specified as an integer.'); } if ($offset >= 0) { // Offset is greater than zero. Search from left to right $tokenizer = clone $this; $is_reversed = false; } else { // Offset is negative. Search from right to left $tokenizer = new Tokenizer(array_reverse($this->tokens)); $offset = abs($offset) - 1; $is_reversed = true; } // Seek to the offset and start the search from there $tokenizer->seek($offset); // Loop through the tokens and search for the target token while ($tokenizer->valid()) { $token = $tokenizer->current(); if ($token->code === $search || $token->name === $search || $token->value === $search) { $index = $tokenizer->key(); // Calculate the index as if the tokenizer is not reversed if ($is_reversed) { $index = count($tokenizer) - $index - 1; } return $index; } $tokenizer->next(); } return false; }