protected function replaceTagsWithText($content, $tags, $generator)
    {
        // The string with tags replaced with markers
        $str = '';
        // The start index of the next tag, remembered as we step backwards through the list
        $li = null;

        $i = count($tags);
        while ($i--) {
            if ($li === null) {
                $tail = substr($content, $tags[$i]['e']);
            } else {
                $tail = substr($content, $tags[$i]['e'], $li - $tags[$i]['e']);
            }

            if ($tags[$i]['escaped']) {
                $str = substr($content, $tags[$i]['s']+1, $tags[$i]['e'] - $tags[$i]['s'] - 2) . $tail . $str;
            } else {
                $str = $generator($i, $tags[$i]) . $tail . $str;
            }

            $li = $tags[$i]['s'];
        }

        return substr($content, 0, $tags[0]['s']) . $str;
    }