function spliceDynamicCallsWithin(Source $s, $first, $last)
{
$pos = $first;
$anchor = INF;
$suppress = false;
while ($pos <= $last) {
switch ($s->tokens[$pos][Source::TYPE_OFFSET]) {
case '$':
case T_VARIABLE:
$anchor = min($pos, $anchor);
break;
case Generic\LEFT_ROUND:
if ($anchor !== INF && !$suppress) {
$callable = $s->read($anchor, $pos - $anchor);
$arguments = $s->read($pos + 1, $s->match($pos) - $pos - 1);
$pos = $s->match($pos);
$replacement = sprintf(DYNAMIC_CALL_REPLACEMENT, $callable, $arguments);
$s->splice($replacement, $anchor, $pos - $anchor + 1);
}
break;
case Generic\LEFT_SQUARE:
case Generic\LEFT_CURLY:
spliceDynamicCallsWithin($s, $pos + 1, $s->match($pos) - 1);
$pos = $s->match($pos);
break;
case T_WHITESPACE:
case T_COMMENT:
case T_DOC_COMMENT:
break;
case T_OBJECT_OPERATOR:
case T_DOUBLE_COLON:
case T_NEW:
$suppress = true;
break;
default:
$suppress = false;
$anchor = INF;
}
$pos++;
}
}