in src/Parser.php [2906:2971]
private function parsePostfixExpressionRest($expression, $allowUpdateExpression = true) {
$tokenKind = $this->getCurrentToken()->kind;
// `--$a++` is invalid
if ($allowUpdateExpression &&
($tokenKind === TokenKind::PlusPlusToken ||
$tokenKind === TokenKind::MinusMinusToken)) {
return $this->parseParsePostfixUpdateExpression($expression);
}
// TODO write tons of tests
if (!($expression instanceof Variable ||
$expression instanceof ParenthesizedExpression ||
$expression instanceof QualifiedName ||
$expression instanceof CallExpression ||
$expression instanceof MemberAccessExpression ||
$expression instanceof SubscriptExpression ||
$expression instanceof ScopedPropertyAccessExpression ||
$expression instanceof StringLiteral ||
$expression instanceof ArrayCreationExpression
)) {
return $expression;
}
if ($tokenKind === TokenKind::ColonColonToken) {
$expression = $this->parseScopedPropertyAccessExpression($expression, null);
return $this->parsePostfixExpressionRest($expression);
}
$tokenKind = $this->getCurrentToken()->kind;
if ($tokenKind === TokenKind::OpenBraceToken ||
$tokenKind === TokenKind::OpenBracketToken) {
$expression = $this->parseSubscriptExpression($expression);
return $this->parsePostfixExpressionRest($expression);
}
if ($expression instanceof ArrayCreationExpression) {
// Remaining postfix expressions are invalid, so abort
return $expression;
}
if ($tokenKind === TokenKind::ArrowToken || $tokenKind === TokenKind::QuestionArrowToken) {
$expression = $this->parseMemberAccessExpression($expression);
return $this->parsePostfixExpressionRest($expression);
}
if ($tokenKind === TokenKind::OpenParenToken && !$this->isParsingUnparenthesizedObjectCreationExpression($expression)) {
$expression = $this->parseCallExpressionRest($expression);
if (!$this->checkToken(TokenKind::OpenParenToken)) {
return $this->parsePostfixExpressionRest($expression);
}
if (
$expression instanceof ParenthesizedExpression ||
$expression instanceof CallExpression ||
$expression instanceof SubscriptExpression) {
// Continue parsing the remaining brackets for expressions
// such as `(new Foo())()`, `foo()()`, `foo()['index']()`
return $this->parsePostfixExpressionRest($expression);
}
return $expression;
}
// Reached the end of the postfix-expression, so return
return $expression;
}