Wouldn't you do it similar to this:
<?php
$orig = "[table]
[tr][td]Column 1[/td][td]Column 2[/td][td]Column 3[/td][/tr]
[tr][td]Something[/td][td]is[/td][td]wrong[/td][/tr]
[tr][td]because[/td][td]I[/td][td]can't[/td][/tr]
[tr][td]think[/td][td]of[/td][td]any[/td][/tr]
[tr][td]tabular[/td][td]data[/td][td][/td][/tr]
[/table]";
$regex = Array("#\[table\](.*?)\[/table\]#is","#\[tr\](.*?)\[/tr\]#is","#\[td\](.*?)\[/td\]#is");
$rep = Array("<table>$1</table>","<tr>$1</tr>","<td>$1</td>");
$outcome = preg_replace($regex, $rep, $orig);
?>
But maybe with a check for data within the table, and a check for the same amount of td's in a tr...
Maybe?
I know it's hard to mash home-made code into a board, but it can be done.
And the only reason that it'd mess up the board layout, is if someone typed it wrong, so obviously you'd need to get some checks in to prevent data from being outside of <td> tags, but inside the table tags. Lol....