Basically, what happens is that each
() capturing group captures at most one expression. When you have such a group inside a repeating expression, each match for that group overwrites the previous match. So yes, you're matching each
[SYM] expression in turn, but only the last one is retained. (That's what that note means in the Explanation box on your linked site.)
In essence, you want a single regular expression to return an array of results, with the second match of each result being an array. Unfortunately, the regular expression engines available don't support that, so you'll have to loop over your regular expression results to process them into what you need.
As MagmaMcFry suggests, it's convenient here to use a simple regular expression that collects all tags, allowing you to use a simpler split function to process them. Loop over the list of tags, creating a new array for each
BIND tag, and appending to that array for each
SYM or
KEY tag.
Alternatively, you can use one more complex regular expression to collect the BIND tag parameters in a pair of matches, and the whole set of SYM/KEY tags in another match. (
/\[BIND:(\w+)\w+)\](.*)\n+((?:\[(?!BIND:)[^]]*\](?:[^[]|\n)*)*)/gm) Then you'll need to loop over the results of that expression, and use a second regular expression to parse the individual SYM/KEY tags out of the string containing them. Unfortunately, this system is both harder to implement correctly and more likely to break if anything changes.
By the way,
[\w] is equivalent to
[w] in some engines and
\w in others, so it's probably best to avoid it.