protected function readNumber($start, $code)
    {
        $position = $start;
        $type = Token::INT_TYPE;

        if ($code === 45) { // -
            $code = $this->charCodeAt(++$position);
        }

        if ($code === 48) { // 0
            $code = $this->charCodeAt(++$position);
        } elseif ($code >= 49 && $code <= 57) { // 1 - 9
            do {
                $code = $this->charCodeAt(++$position);
            } while ($code >= 48 && $code <= 57); // 0 - 9
        } else {
            // @todo Throw proper exception.
            throw new \Exception('Invalid number.');
        }

        if ($code === 46) { // .
            $type = Token::FLOAT_TYPE;

            $code = $this->charCodeAt(++$position);
            if ($code >= 48 && $code <= 57) { // 0 - 9
                do {
                    $code = $this->charCodeAt(++$position);
                } while ($code >= 48 && $code <= 57); // 0 - 9
            } else {
                // @todo Throw proper exception.
                throw new \Exception('Invalid number.');
            }

            if ($code === 69 || $code === 101) { // E e
                $code = $this->charCodeAt(++$position);
                if ($code === 43 || $code === 45) { // + -
                    $code = $this->charCodeAt(++$position);
                }
                if ($code >= 48 && $code <= 57) { // 0 - 9
                    do {
                        $code = $this->charCodeAt(++$position);
                    } while ($code >= 48 && $code <= 57); // 0 - 9
                } else {
                    // @todo Throw proper exception.
                    throw new \Exception('Invalid number.');
                }
            }
        }

        $body = $this->source->getBody();
        $value = mb_substr($body, $start, $position - $start, 'UTF-8');
        return new Token($type, $start, $position, $value);
    }