First of all, you should rethink your variable rewriting. There's several cases where your method doesn't end as expected, when you have some dependencies between them. Additionaly, everything gets replaced regardless of a variable being in a loop or not.
If you want something like {while(condition)}code{/while}, you need to be aware that recursion is also possible and therefore it's not as simple as matching a regex on it.
A simple approach would be the following:
- Find the start of a token (variable, whileloop) and remember the position where you find it
- If it is a variable and you are in the most outer scope (not in a loop), process it by doing a replacement. Adjust your pointer so that you don't read the replacement afterwards to avoid replacing things that you don't want to.
- If it is a loop
- extract the condition between the brackets and store it somewher
- additionaly, store the current location
- Push the token onto a stack to remember the current recursion level.
- Remove a token from the stack when you encounter the {/while} token.
- Now proceed recursively, pushing all nested loop tokens on the stack and removing them as they end. Stop when you are at the outermost level again.
- Evaluate the condition of the loop. As long as it is true, create new copies from the source text between the start token and the end token and process them by using recursion.
- Concatenate the intermediate results and replace everything from {while} to {/while} with this concatenation. Adjust your pointer so that you're pointing after the loop and continue :)
Hope that this helps. I know that it sounds a bit painful, but if you understand the concept, you should be able to do it (although it is not super-efficient and compiling template engines like smarty will always be in advance since they parse the template file just once and compile it to PHP code).
@Daff: you could find the tokens with regular expressions, but using one regex to match on a whole loop construct doesn't work due to the recursions (unless your regex has a recursive extension).