protected function subparse($test = null, $next = false)
{
$line = $this->stream->getCurrentToken()->getLine();
$nodes = array();
while (!$this->stream->isEOS()) {
switch ($this->stream->getCurrentToken()->getType()) {
case Token::TEXT:
$token = $this->stream->next();
$nodes[] = new Node\TextNode($token->getValue(), $token->getLine());
break;
case Token::BLOCK_START:
$this->stream->next();
$token = $this->stream->getCurrentToken();
if ($token->getType() !== Token::NAME) {
throw new SyntaxError(sprintf('unexpected "%s", expecting a valid tag', str_replace("\n", '\\n', $token->getValue())), $token);
}
if (!is_null($test) && $token->test($test)) {
if (is_bool($next)) {
$next = $next ? 1 : 0;
}
$this->stream->skip($next);
return new NodeList($nodes, $line);
}
if (!in_array($token->getValue(), array_keys($this->tags))) {
if (is_array($test)) {
$expecting = '"' . implode('" or "', $test) . '"';
} elseif ($test) {
$expecting = '"' . $test . '"';
} else {
$expecting = 'a valid tag';
}
throw new SyntaxError(sprintf('unexpected "%s", expecting %s', str_replace("\n", '\\n', $token->getValue()), $expecting), $token);
}
$this->stream->next();
if (isset($this->tags[$token->getValue()]) && is_callable(array($this, $this->tags[$token->getValue()]))) {
$node = call_user_func(array($this, $this->tags[$token->getValue()]), $token);
} else {
throw new SyntaxError(sprintf('missing construct handler "%s"', $token->getValue()), $token);
}
if (!is_null($node)) {
$nodes[] = $node;
}
break;
case Token::OUTPUT_START:
$token = $this->stream->next();
$expr = $this->parseExpression();
$autoEscape = $this->autoEscape[count($this->autoEscape) - 1];
if ($autoEscape) {
$filters = array();
if ($expr instanceof FilterExpression) {
if (!$expr->isRaw()) {
$expr->setAutoEscape(true);
}
} else {
$expr = new Expression\FilterExpression($expr, $filters, true, $token->getLine());
}
}
$nodes[] = $this->parseIfModifier($token, new Node\OutputNode($expr, $token->getLine()));
$this->stream->expect(Token::OUTPUT_END);
break;
default:
throw new SyntaxError('parser ended up in unsupported state', $this->stream->getCurrentToken());
}
}
return new NodeList($nodes, $line);
}