By looping, I mean doing something like this:
do {
$count = 0;
if (preg_replace($pattern1, $repl1, $subject) != $subject) ++$count;
if (preg_replace($pattern2, $repl2, $subject) != $subject) ++$count;
if (preg_replace($pattern3, $repl3, $subject) != $subject) ++$count;
} while ($count > 0);
(In Perl, this can be done more concisely. I'm not sure if the above is the best way to do it in PHP.)
I found that approach necessary for certain nestable tags.
In later versions of UBB.classic, that approach was added for all of the markup translation.
I think that UBB.classic, unlike UBB.threads, always translates the opening and closing tags in a single regex replacement. Perhaps the advantage of the former approach is that it makes it harder for a user to mess up a post by using unmatched tags. There might also be security benefits, since by regex-ing the text between the opening and closing tags, you can make sure that nothing "sneaky" is being done.