public function consume($length = null)
    {
        $length = $length ?: $this->nextConsumeLength;

        if ($length === null) {
            $this->throwException(
                'Failed to consume: No length given. Peek or match first.'
            );
        }

        $consumedPart = mb_substr($this->input, 0, $length, $this->encoding);
        $this->input = substr($this->input, strlen($consumedPart));
        $this->inputLength -= $length;
        $this->position += $length;
        $this->offset += $length;

        //Check for new-lines in consumed part to increase line and offset correctly
        $newLines = mb_substr_count($consumedPart, "\n");
        $this->line += $newLines;

        if ($newLines) {
            //if we only have one new-line character, the new offset is 0
            //Else the offset is the length of the last line read - 1
            if (mb_strlen($consumedPart, $this->encoding) === 1) {
                $this->offset = 1;
            } else {
                $parts = explode("\n", $consumedPart);
                $this->offset = mb_strlen($parts[count($parts) - 1], $this->encoding);
            }
        }

        $this->nextConsumeLength = null;
        $this->lastPeekResult = null;
        $this->lastMatchResult = null;

        return $consumedPart;
    }