Bardzo ciężka sprawa...
Na stackoverflow nawet mówią, że się nie da.
Inni podają jakieś przykłady, które nie nadają się dla Twojego problemu...
Sam dopracowałem się czegoś takiego(przez ostatnie dwie i pół godziny):
<?php
$str = '{abcd}{ef{gh}{ijkl}{mnop}{rst{u}';
preg_match_all('/\\{([^\\{]*?(?!\\{)[^\\{]*?)(?(1)}|\\{[^}]+?})/', $str, $out);
Jeszcze jutro spróbuję.
Może ktoś jeszcze ma jakiś pomysł ?
Pozdro.
PS. Musisz wstawić podwójny znak ucieczki - raz dla PHP, a drugi raz dla PCRE.