public function addRule($pattern, $replacement = null)
    {
        if (is_object($pattern) && method_exists($pattern, 'toArray'))
            $pattern = $pattern->toArray();
        if (is_object($replacement) && method_exists($replacement, 'toArray'))
            $replacement = $replacement->toArray();

        if (!(is_array($pattern) || is_string($pattern)))
            throw new \RuntimeException("Arguments must be string or array, or implement toArray method");

        if (is_array($pattern))
        {
            if ($replacement !== null)
            {
                if (!is_array($replacement) || count($replacement) !== count($pattern))
                    throw new \RuntimeException("When providing arrays as arguments, the should have the same number of elements");
                $pattern = array_combine($pattern, $replacement);
            }

            foreach ($pattern as $pat => $repl)
                $this->addRule($pat, $repl);

            return $this;
        }

        // Create a pattern from strings that aren't patterns already
        if (substr($pattern, 0, 1) !== "/")
            $pattern = "/" . preg_quote($pattern, "/") . "/";

        $cb = is_callable($replacement);

        if ($cb)
        {
            $interceptor = new ErrorInterceptor('preg_replace_callback');
            $interceptor->registerError(E_WARNING, 'preg_replace');
            $interceptor->execute($pattern, $replacement, '');
            $errors = $interceptor->getInterceptedErrors();
        }
        else
        {
            $interceptor = new ErrorInterceptor('preg_replace');
            $interceptor->registerError(E_WARNING, 'preg_replace');
            $interceptor->execute($pattern, $replacement, "");
            $errors = $interceptor->getInterceptedErrors();
        }

        if (!empty($errors))
        {
            $e = reset($errors);
            self::$logger->error("Invalid pattern / replacement: {0} / {1}", [$pattern, $replacement]);
            throw new \RuntimeException("Invalid pattern or replacement: {$pattern} / {$replacement}", 0, $e);
        }

        $this->rules[$pattern] = $replacement;
        return $this;
    }