preg_match_all(
'/(?<=\[) # Assert that the previous characters is a [
(?: # Match either...
[^[\]]* # any number of characters except brackets
| # or
\[ # an opening bracket
(?R) # containing a match of this very regex
\] # followed by a closing bracket
)* # Repeat as needed
(?=\]) # Assert the next character is a ]/x',
$string, $result, PREG_PATTERN_ORDER);