public function expect(string $type, $value = null, string $message = null): void
    {
        if ($this->test($type, $value)) {
            return;
        }

        $currentToken = $this->getCurrent();

        if ($message === null) {
            // Let's create a default message
            $formattedMessage = \sprintf(
                'Expected token type %s%s',
                $type,
                $value === null ? '' : " with value \"$value\""
            );

            if ($currentToken === null) {
                $formattedMessage .= ', got end of stream';
            } else {
                $formattedMessage .= \sprintf(
                    ', got %s with value \"%s\"',
                    $currentToken->type,
                    $currentToken->value
                );
            }
        } else {
            $formattedMessage = \sprintf(
                $message,
                $currentToken === null ? 'T_EOF' : $currentToken->type,
                $currentToken === null ? 'end of stream' : $currentToken->value
            );
        }

        throw new InvalidArgumentException($formattedMessage);
    }