Esempio n. 1
0
 /**
  * Convert template to PHP code
  *
  * @throws CompileException
  */
 public function compile()
 {
     $end = $pos = 0;
     foreach ($this->_fenom->getPreFilters() as $filter) {
         $this->_src = call_user_func($filter, $this, $this->_src);
     }
     while (($start = strpos($this->_src, '{', $pos)) !== false) {
         // search open-symbol of tags
         switch (substr($this->_src, $start + 1, 1)) {
             // check next character
             case "\n":
             case "\r":
             case "\t":
             case " ":
             case "}":
                 // ignore the tag
                 $this->_appendText(substr($this->_src, $pos, $start - $pos + 2));
                 $end = $start + 1;
                 break;
             case "*":
                 // comment block
                 $end = strpos($this->_src, '*}', $start);
                 // find end of the comment block
                 if ($end === false) {
                     throw new CompileException("Unclosed comment block in line {$this->_line}", 0, 1, $this->_name, $this->_line);
                 }
                 $end++;
                 $this->_appendText(substr($this->_src, $pos, $start - $pos));
                 $comment = substr($this->_src, $start, $end - $start);
                 // read the comment block for processing
                 $this->_line += substr_count($comment, "\n");
                 // count lines in comments
                 unset($comment);
                 // cleanup
                 break;
             default:
                 $this->_appendText(substr($this->_src, $pos, $start - $pos));
                 $end = $start + 1;
                 do {
                     $need_more = false;
                     $end = strpos($this->_src, '}', $end + 1);
                     // search close-symbol of the tag
                     if ($end === false) {
                         // if unexpected end of template
                         throw new CompileException("Unclosed tag in line {$this->_line}", 0, 1, $this->_name, $this->_line);
                     }
                     $tag = substr($this->_src, $start + 1, $end - $start - 1);
                     if ($this->_ignore) {
                         // check ignore
                         if ($tag === '/' . $this->_ignore) {
                             // turn off ignore
                             $this->_ignore = false;
                         } else {
                             // still ignore
                             $this->_appendText('{' . $tag . '}');
                             continue;
                         }
                     }
                     if ($this->_tag_filters) {
                         foreach ($this->_tag_filters as $filter) {
                             $tag = call_user_func($filter, $tag, $this);
                         }
                     }
                     $tokens = new Tokenizer($tag);
                     // tokenize the tag
                     if ($tokens->isIncomplete()) {
                         // all strings finished?
                         $need_more = true;
                     } else {
                         $this->_appendCode($this->parseTag($tokens), '{' . $tag . '}');
                         // start the tag lexer
                         if ($tokens->key()) {
                             // if tokenizer have tokens - throws exceptions
                             throw new CompileException("Unexpected token '" . $tokens->current() . "' in {$this} line {$this->_line}, near '{" . $tokens->getSnippetAsString(0, 0) . "' <- there", 0, E_ERROR, $this->_name, $this->_line);
                         }
                     }
                 } while ($need_more);
                 unset($tag);
                 // cleanup
                 break;
         }
         $pos = $end + 1;
         // move search-pointer to end of the tag
     }
     gc_collect_cycles();
     $this->_appendText(substr($this->_src, $end ? $end + 1 : 0));
     // append tail of the template
     if ($this->_stack) {
         $_names = array();
         foreach ($this->_stack as $scope) {
             $_names[] = '{' . $scope->name . '} opened on line ' . $scope->line;
         }
         /* @var Tag $scope */
         $message = "Unclosed tag" . (count($_names) > 1 ? "s" : "") . ": " . implode(", ", $_names);
         throw new CompileException($message, 0, 1, $this->_name, $scope->line);
     }
     $this->_src = "";
     // cleanup
     if ($this->_post) {
         foreach ($this->_post as $cb) {
             call_user_func_array($cb, array($this, &$this->_body));
         }
     }
     $this->addDepend($this);
     // for 'verify' performance
     foreach ($this->_fenom->getPostFilters() as $filter) {
         $this->_body = call_user_func($filter, $this, $this->_body);
     }
 }