public static function getClause($statement, $list, $clause, $type = 0, $skipFirst = true)
    {
        /**
         * The index of the current clause.
         *
         * @var int
         */
        $currIdx = 0;

        /**
         * The count of brackets.
         * We keep track of them so we won't insert the clause in a subquery.
         *
         * @var int
         */
        $brackets = 0;

        /**
         * The string to be returned.
         *
         * @var string
         */
        $ret = '';

        /**
         * The clauses of this type of statement and their index.
         *
         * @var array
         */
        $clauses = array_flip(array_keys($statement->getClauses()));

        /**
         * Lexer used for lexing the clause.
         *
         * @var Lexer
         */
        $lexer = new Lexer($clause);

        /**
         * The type of this clause.
         *
         * @var string
         */
        $clauseType = $lexer->list->getNextOfType(Token::TYPE_KEYWORD)->keyword;

        /**
         * The index of this clause.
         *
         * @var int
         */
        $clauseIdx = $clauses[$clauseType];

        $firstClauseIdx = $clauseIdx;
        $lastClauseIdx = $clauseIdx;

        // Determining the behavior of this function.
        if ($type === -1) {
            $firstClauseIdx = -1; // Something small enough.
            $lastClauseIdx = $clauseIdx - 1;
        } elseif ($type === 1) {
            $firstClauseIdx = $clauseIdx + 1;
            $lastClauseIdx = 10000; // Something big enough.
        } elseif (is_string($type) && isset($clauses[$type])) {
            if ($clauses[$type] > $clauseIdx) {
                $firstClauseIdx = $clauseIdx + 1;
                $lastClauseIdx = $clauses[$type] - 1;
            } else {
                $firstClauseIdx = $clauses[$type] + 1;
                $lastClauseIdx = $clauseIdx - 1;
            }
        }

        // This option is unavailable for multiple clauses.
        if ($type !== 0) {
            $skipFirst = false;
        }

        for ($i = $statement->first; $i <= $statement->last; ++$i) {
            $token = $list->tokens[$i];

            if ($token->type === Token::TYPE_COMMENT) {
                continue;
            }

            if ($token->type === Token::TYPE_OPERATOR) {
                if ($token->value === '(') {
                    ++$brackets;
                } elseif ($token->value === ')') {
                    --$brackets;
                }
            }

            if ($brackets === 0) {
                // Checking if the section was changed.
                if (($token->type === Token::TYPE_KEYWORD)
                    && isset($clauses[$token->keyword])
                    && ($clauses[$token->keyword] >= $currIdx)
                ) {
                    $currIdx = $clauses[$token->keyword];
                    if ($skipFirst && ($currIdx === $clauseIdx)) {
                        // This token is skipped (not added to the old
                        // clause) because it will be replaced.
                        continue;
                    }
                }
            }

            if (($firstClauseIdx <= $currIdx) && ($currIdx <= $lastClauseIdx)) {
                $ret .= $token->token;
            }
        }

        return trim($ret);
    }