Te l'ho modificato un pochino per fargli leggere anche le sottoliste
Codice PHP:
$pattern = "#\
[list\]((\n|\r\n)?((\[\*\].+?)(\n|\[\*\])?)+?)\[/list\]#is";
$r1 = preg_replace_callback($pattern,
create_function('$m', '$split=explode($m[5],$m[1]); $lis=""; foreach($split as $li): $clean=trim(substr($li, 3)); if (!empty($clean)): $lis.="<li>".$clean."</li>"; endif; endforeach; return "<ul>$lis</ul>";'),
$str);
$r2 = preg_replace_callback($pattern,
create_function('$m', '$split=explode($m[5],$m[1]); $lis=""; foreach($split as $li): $clean=trim(substr($li, 3)); if (!empty($clean)): $lis.="<li>".$clean."</li>"; endif; endforeach; return "<ul>$lis</ul>";'),
$r1);
echo $r2;
Output:
Codice HTML:
<ul>
<li>lista 1</li>
<li><ul><li>sublist 1</li><li>sublist 2</li></ul></li>
<li>lista 2</li>
</ul>
A te poi istituire un criterio per ciclare tot volte il preg_replace_callback quante te ne occorrono per convertire tutte le list.
L'unica nota importante è rispettare la sintassi, la prima lista deve avere ogni elemento che termina con un breakline (una mandata a capo insomma) mentre nelle sottoliste il primo[*] deve essere attaccato subito dopo il tag list mentre la fine dell'ultimo[*] subito prima della chiusura senza breakline (proprio come nell'immagine insomma).
Purtroppo usare questa sintassi per le sottoliste è caotico e porta a dover assumere restrizioni sintattiche complesse come in questo caso.