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++; } }