protected function parseMacro($token)
{
if (!empty($this->currentBlock)) {
throw new SyntaxError('cannot declare macros inside blocks', $token);
}
if ($this->inMacro) {
throw new SyntaxError('cannot declare macros inside another macro', $token);
}
$this->inMacro = true;
$name = $this->parseName()->getValue();
if (isset($this->macros[$name])) {
throw new SyntaxError(sprintf('macro "%s" already defined', $name), $token);
}
$args = array();
if ($this->stream->consume(Token::OPERATOR, '(')) {
while (!$this->stream->test(Token::OPERATOR, ')')) {
if (!empty($args)) {
$this->stream->expect(Token::OPERATOR, ',');
if ($this->stream->test(Token::OPERATOR, ')')) {
break;
}
}
$key = $this->parseName()->getValue();
if ($this->stream->consume(Token::OPERATOR, '=')) {
$val = $this->parseLiteralExpression();
} else {
$val = new Expression\ConstantExpression(null, $token->getLine());
}
$args[$key] = $val;
}
$this->stream->expect(Token::OPERATOR, ')');
}
$this->stream->expect(Token::BLOCK_END);
$body = $this->subparse('endmacro');
if ($this->stream->next()->getValue() != 'endmacro') {
throw new SyntaxError('malformed macro statement', $token);
}
$this->stream->consume(Token::NAME, $name);
$this->stream->expect(Token::BLOCK_END);
$this->macros[$name] = new Node\MacroNode($name, $args, $body, $token->getLine());
$this->inMacro = false;
}