There is a BBCode package in PEAR. I couldn't get it to work, but I'm sure that's just me.
I think you could use preg for this, although it would be a bit complicated:
<tag attr="y"> <-> [tag=y] is ok.
[/tag] -> </tag> is ok.
The only tricky bit is the </tag> -> [/tag]
If you search for <tag... after the opening one and then count the same number of identical closing </tag> until you get to the outer closing </tag> that matches the one you're replacing. This means the XML/(X)HTML has to be well formed and you need to provide for self closing tags, e.g. <br />, <img />, <hr />, <link />, <meta /> (there are more I think).
I'm stopping there - the though of that regex is giving me a nosebleed. How about SimpleXML or building an XML tree? Just typing aloud.
/?EDIT just read your last line - OK NOT XML tree.