public function compile(array $tokens, $className)
{
$this->tokens = $tokens;
$output = '';
$this->output =& $output;
$this->inHead = TRUE;
$this->htmlNode = $this->macroNode = $this->context = NULL;
$this->placeholders = $this->properties = [];
$this->methods = ['main' => NULL, 'prepare' => NULL];
$macroHandlers = new \SplObjectStorage();
array_map([$macroHandlers, 'attach'], call_user_func_array('array_merge', $this->macros));
foreach ($macroHandlers as $handler) {
$handler->initialize($this);
}
foreach ($tokens as $this->position => $token) {
if ($this->inHead && !($token->type === $token::COMMENT || $token->type === $token::MACRO_TAG && isset($this->flags[$token->name]) && $this->flags[$token->name] & IMacro::ALLOWED_IN_HEAD || $token->type === $token::TEXT && trim($token->text) === '')) {
$this->inHead = FALSE;
}
$this->{"process{$token->type}"}($token);
}
while ($this->htmlNode) {
if (!empty($this->htmlNode->macroAttrs)) {
throw new CompileException('Missing ' . self::printEndTag($this->htmlNode));
}
$this->htmlNode = $this->htmlNode->parentNode;
}
while ($this->macroNode) {
if (~$this->flags[$this->macroNode->name] & IMacro::AUTO_CLOSE) {
throw new CompileException('Missing ' . self::printEndTag($this->macroNode));
}
$this->closeMacro($this->macroNode->name);
}
$prepare = $epilogs = '';
foreach ($macroHandlers as $handler) {
$res = $handler->finalize();
$prepare .= empty($res[0]) ? '' : "<?php {$res['0']} ?>";
$epilogs = (empty($res[1]) ? '' : "<?php {$res['1']} ?>") . $epilogs;
}
$this->addMethod('main', $this->expandTokens("extract(\$this->params);?>\n{$output}{$epilogs}<?php return get_defined_vars();"));
if ($prepare) {
$this->addMethod('prepare', "extract(\$this->params);?>{$prepare}<?php");
}
if ($this->contentType !== self::CONTENT_HTML) {
$this->addProperty('contentType', $this->contentType);
}
foreach ($this->properties as $name => $value) {
$members[] = "\tpublic \${$name} = " . PhpHelpers::dump($value) . ';';
}
foreach (array_filter($this->methods) as $name => $method) {
$members[] = "\n\tfunction {$name}({$method['arguments']})\n\t{\n" . ($method['body'] ? "\t\t{$method['body']}\n" : '') . "\t}";
}
return "<?php\n" . "use Latte\\Runtime as LR;\n\n" . "class {$className} extends Latte\\Runtime\\Template\n{\n" . implode("\n\n", $members) . "\n\n}\n";
}