$re = '/# Define the opening and closing elements before the recursion occurs
(?(DEFINE)
(?<open_curly>\{)
(?<close_curly>\})
(?<open_square>\[)
(?<close_square>\])
(?P<open_pascal>(?i:\bbegin\b))
(?P<close_pascal>(?i:\bend\b))
(?P<open_lua>--\[)
(?P<close_lua>--\])
(?<open>\g\'open_curly\'|\g\'open_square\'|\g\'open_pascal\'|\g\'open_lua\')
(?<close>\g\'close_curly\'|\g\'close_square\'|\g\'close_pascal\'|\g\'close_lua\')
)
# Match the opening element
(\g\'open\'
(?>
# For recursion, don\'t match either the opening
# or closing element
(?!\g\'open\'|\g\'close\')(.)
|
# Recurse this captured pattern
(?-1)
)*
# Match the closing element
\g\'close\')
/x';
$str = 'EVENLY BALANCED curly braces
{{{}}}
{ test1 { test2 { test3 { test4 } } } }
UNEVENLY BALANCED curly braces
{{{{}}}
{ test1 { test2 { test3 { test4 } } } } }
MULTI-LINE EVENLY BALANCED curly braces
{
}
MULTI-LINE UNEVENLY BALANCED curly braces
{{
}
EVENLY BALANCED square braces
[ test1 [ test2 [ test3 [ test4 ] ] ] ]
EVENLY BALANCED square and curly braces
{ test1 [ test2 { test3 [ test4 ] } ] }
UNEVENLY BALANCED square and curly braces
{ test1 [ test2 { test3 [ test4 ] } } ]
';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
// Print the entire match result
var_dump($matches);
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for PHP, please visit: http://php.net/manual/en/ref.pcre.php