This is what I got now:
/{% if(.+?) %}(.*?){% endif %}/gusi
It catches multiple if statements etc just fine.
IMG: http://image.xesau.eu/2015
It is almost trivial to change your pattern into a recursive pattern:
{% if(.+?) %}((?>(?R)|.)*?){% endif %}
Working example: https://regex101.com/r/gX8rM0/1
However, that would be a bad idea: the pattern is missing many cases, which are really bugs in your parser. Just a few common examples:
Comments:
{% if aaa %}
123
{% endif %}
String literals:
{% if aaa %}a = "{% endif %}"{% endif %}
{% if $x == "{% %}" %}...{% endif %}
Escaped characters (you do need escaped characters, right?):
To start a condition, use \{% if aaa %}
Invalid input:
It would be nice if the parser can work relatively well on invalid input, and point to the correct position of the error.