+# First we take the template string and convert it into a tree of
+# strings and sub-templates. A template is a hash with a name string,
+# a pieces array, and possibly an args array.
+
+function parse_template($string) {
+ $tem =& tem_push();
+ $tem['pieces'] = array();
+ # 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);
+ # create a new sub-template
+ # and add it to the parent.
+ $tem =& tem_push($tem);
+ $tem['parent']['pieces'][] =& $tem;
+ $tem['name'] = $name;
+ $tem['pieces'] = array();
+ $tem['args'] = $args;
+ } elseif(last($args) == '}') { # close block
+ array_pop($args);
+ $cur = $tem['name'];
+ if($name && $name != $cur) {
+ die("Invalid template: tried to close '$name', but '$cur' is current.");
+ }
+ $tem =& $tem['parent'];
+ } else { # value slot
+ $tem['pieces'][] = array('name' => $name, 'args' => $args);
+ }
+ } elseif($match and $match != '<!--') { # static string
+ $tem['pieces'][] = $match;
+ }