- $matches = array();
- # this limits sub_template names to 50 chars
- if(ereg('<!--~([^~]*) start~-->', substr($in, 0, 65), $matches)) {
- list($start_tag, $tag_name) = $matches;
- $out .= '~' . $tag_name . '~';
- $in = substr($in, strlen($start_tag));
- $this->sub_templates[$tag_name] = '';
- $this->_load($in, $this->sub_templates[$tag_name]);
- } else {
- # it's not a start tag or end tag, so let's pass it through:
- $out .= substr($in, 0, 5);
- $in = substr($in, 5);
+# 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);