Original

start underline bold here before italic italic, broken bold again end underline italic bold italic still italic bold

a b c
d e f

<p><u>start underline <b>bold here</b> before italic <i>italic, broken <b>bold again</b> end underline</u> italic  <b>bold italic</b>  still italic </i><b>bold</b></p>

<table>
    <tr>
        <td>a</td>
        <td><u>b</td>
        <td>c</td>
    </tr>
    <tr>
        <td>d</td>

        <td>e</u></td>
        <td>f</td>
    </tr>
</table>

Fixed

start underline bold here before italic italic, broken bold again end underline italic bold italic still italic bold

a b c
d e f

<p><u>start underline <b>bold here</b> before italic <i>italic, broken <b>bold again</b> end underline</i></u><i> italic  </i><b><i>bold italic</i></b><i>  still italic </i><b>bold</b></p>

<table>
    <tr>
        <td>a</td>
        <td><u>b</u></td>
        <td><u>c</u></td>
    </tr>
    <tr>
        <td><u>d</u></td>

        <td><u>e</u></td>
        <td>f</td>
    </tr>
</table>


<?php

$input 
'<p><u>start underline <b>bold here</b> before italic <i>italic, broken <b>bold again</b> end underline</u> italic  <b>bold italic</b>  still italic </i><b>bold</b></p>

<table>
    <tr>
        <td>a</td>
        <td><u>b</td>
        <td>c</td>
    </tr>
    <tr>
        <td>d</td>

        <td>e</u></td>
        <td>f</td>
    </tr>
</table>'
;

echo 
'<h1>Original</h1>';
echo 
$input.'<br/><pre>';
echo 
htmlentities($input);
echo 
'</pre>';

$parts preg_split('!(</?[a-zA-Z]+)!'$input, -1PREG_SPLIT_DELIM_CAPTURE);
$tags = array();
$isTag false;
$output '';
foreach (
$parts as $num => $part) {
    if (
$isTag) {
        if (
$part[1] == '/') {
            
$tag substr($part2);
            if (
false !== array_search($tag$tags)) {
                while ((
$curTag array_pop($tags)) && $tag != $curTag) {
                    
$output .= '</'.$curTag.'>';
                }
            } else {
                
$curTag '';
            }
            if (!
$curTag) {
                
//$pos = strrpos($output, '>');
                //$output = substr($output, 0, $pos + 1).'<'.$tag.'>'.substr($output, $pos + 1);
                
$pos strrpos($output'</'.$tag.'>');
                
$subParts preg_split('!(</?[^>]*>)!i'substr($output$pos strlen($tag) + 3), -1PREG_SPLIT_DELIM_CAPTURE);
                
$output substr($output0$pos strlen($tag) + 3);
                
$isSubTag false;
                
$maxSub count($subParts) - 1;
                foreach (
$subParts as $subNum => $subPart) {
                    if (!
$isSubTag && (strlen(trim($subPart)) || $subNum == $maxSub)) {
                        
$output .= '<'.$tag.'>'.$subPart.($subNum == $maxSub '' '</'.$tag.'>');
                    } else {
                        
$output .= $subPart;
                    }
                    
$isSubTag = !$isSubTag;
                }
                
/*$output = substr($output, 0, $pos + strlen($tag) + 4).
                    preg_replace('!(^/?[^>]*>)!',
                                 '\1<'.$tag.'>',
                                 preg_replace('!(</?[^>]*>)!',
                                              '</'.$tag.'>\1<'.$tag.'>',
                                              substr($output, $pos + strlen($tag) + 4)));*/
            
}
        } else {
            
$tag substr($part1);
            
$tags[] = $tag;
        }
        
$output .= $part;
    } else {
        
$output .= $part;
    }
    
$isTag = !$isTag;
}

echo 
'<h1>Fixed</h1>';
echo 
$output.'<br/><pre>';
echo 
htmlentities($output).'</pre><br/><br/>';

highlight_file(__FILE__);

?>