+# First we take the template string and break it up into an array
+# of strings and sub-arrays. The first item in a sub-array is the name
+# of the value or sub-template.
+
+function parse_template($string) {
+ # Don't mess with the $stack/$tem assignments! Since
+ # PHP references point to the variable, not the data,
+ # it really does have to be written exactly like this.
+ $stack[] = array('name' => 'root', 'pieces' => array());
+ $tem = &last($stack);
+ # note: for some reason this captures '<!--' but not '-->'.
+ $matches = preg_split("/(<!--)?(~[^~]*~)(?(1)-->)/", $string, -1, PREG_SPLIT_DELIM_CAPTURE);
+ foreach($matches as $match) {
+ if(substr($match,0,1) == '~') {
+ $args = explode(' ', substr($match,1,-1));
+
+ if(count($args) == 1 and $args[0] == '}') $name = '';
+ else $name = array_shift($args);
+
+ if(last($args) == '{') { # open block
+ array_pop($args);
+ $stack[] = array('name' => $name, 'pieces' => array(), 'args' => $args);
+ $tem['pieces'][] = &last($stack);
+ $tem = &last($stack);
+ } elseif(last($args) == '}') { # close block
+ array_pop($args);
+ $cur = $stack[count($stack)-1]['name'];
+ if($name && $name != $cur) {
+ die("Invalid template: tried to close '$name', but '$cur' is current.");
+ }
+ array_pop($stack); $tem = &last($stack);
+ } else { # value slot
+ $tem['pieces'][] = array('name' => $name, 'args' => $args);