Skip to content

Commit c9fb699

Browse files
committed
Support parsing new (call_function())()
And add tests for arbitrary parenthesized expressions in `new` and `instanceof`
1 parent 8eebdbe commit c9fb699

10 files changed

+357
-2
lines changed

src/Parser.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,7 +2678,7 @@ private function parsePostfixExpressionRest($expression, $allowUpdateExpression
26782678
return $this->parsePostfixExpressionRest($expression);
26792679
}
26802680

2681-
if ($tokenKind === TokenKind::OpenParenToken && !$this->isParsingObjectCreationExpression) {
2681+
if ($tokenKind === TokenKind::OpenParenToken && !$this->isParsingUnparenthesizedObjectCreationExpression($expression)) {
26822682
$expression = $this->parseCallExpressionRest($expression);
26832683

26842684
if (!$this->checkToken(TokenKind::OpenParenToken)) {
@@ -2822,19 +2822,37 @@ private function parseScopedPropertyAccessExpression($expression, $fallbackParen
28222822
return $scopedPropertyAccessExpression;
28232823
}
28242824

2825+
public function isParsingUnparenthesizedObjectCreationExpression($expression) {
2826+
if (!$this->isParsingObjectCreationExpression) {
2827+
return false;
2828+
}
2829+
if ($expression instanceof Token) {
2830+
return true;
2831+
}
2832+
while ($expression->parent) {
2833+
$expression = $expression->parent;
2834+
if ($expression instanceof ObjectCreationExpression) {
2835+
return true;
2836+
} elseif ($expression instanceof ParenthesizedExpression) {
2837+
return false;
2838+
}
2839+
}
2840+
}
2841+
28252842
private $isParsingObjectCreationExpression = false;
28262843

28272844
private function parseObjectCreationExpression($parentNode) {
28282845
$objectCreationExpression = new ObjectCreationExpression();
28292846
$objectCreationExpression->parent = $parentNode;
28302847
$objectCreationExpression->newKeword = $this->eat1(TokenKind::NewKeyword);
28312848
// TODO - add tests for this scenario
2849+
$oldIsParsingObjectCreationExpression = $this->isParsingObjectCreationExpression;
28322850
$this->isParsingObjectCreationExpression = true;
28332851
$objectCreationExpression->classTypeDesignator =
28342852
$this->eatOptional1(TokenKind::ClassKeyword) ??
28352853
$this->parseExpression($objectCreationExpression);
28362854

2837-
$this->isParsingObjectCreationExpression = false;
2855+
$this->isParsingObjectCreationExpression = $oldIsParsingObjectCreationExpression;
28382856

28392857
$objectCreationExpression->openParen = $this->eatOptional1(TokenKind::OpenParenToken);
28402858
if ($objectCreationExpression->openParen !== null) {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
// php 8.0 instanceof
3+
$x = $y instanceof (function_call());
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
{
2+
"SourceFileNode": {
3+
"statementList": [
4+
{
5+
"InlineHtml": {
6+
"scriptSectionEndTag": null,
7+
"text": null,
8+
"scriptSectionStartTag": {
9+
"kind": "ScriptSectionStartTag",
10+
"textLength": 6
11+
}
12+
}
13+
},
14+
{
15+
"ExpressionStatement": {
16+
"expression": {
17+
"AssignmentExpression": {
18+
"leftOperand": {
19+
"Variable": {
20+
"dollar": null,
21+
"name": {
22+
"kind": "VariableName",
23+
"textLength": 2
24+
}
25+
}
26+
},
27+
"operator": {
28+
"kind": "EqualsToken",
29+
"textLength": 1
30+
},
31+
"byRef": null,
32+
"rightOperand": {
33+
"BinaryExpression": {
34+
"leftOperand": {
35+
"Variable": {
36+
"dollar": null,
37+
"name": {
38+
"kind": "VariableName",
39+
"textLength": 2
40+
}
41+
}
42+
},
43+
"operator": {
44+
"kind": "InstanceOfKeyword",
45+
"textLength": 10
46+
},
47+
"rightOperand": {
48+
"ParenthesizedExpression": {
49+
"openParen": {
50+
"kind": "OpenParenToken",
51+
"textLength": 1
52+
},
53+
"expression": {
54+
"CallExpression": {
55+
"callableExpression": {
56+
"QualifiedName": {
57+
"globalSpecifier": null,
58+
"relativeSpecifier": null,
59+
"nameParts": [
60+
{
61+
"kind": "Name",
62+
"textLength": 13
63+
}
64+
]
65+
}
66+
},
67+
"openParen": {
68+
"kind": "OpenParenToken",
69+
"textLength": 1
70+
},
71+
"argumentExpressionList": null,
72+
"closeParen": {
73+
"kind": "CloseParenToken",
74+
"textLength": 1
75+
}
76+
}
77+
},
78+
"closeParen": {
79+
"kind": "CloseParenToken",
80+
"textLength": 1
81+
}
82+
}
83+
}
84+
}
85+
}
86+
}
87+
},
88+
"semicolon": {
89+
"kind": "SemicolonToken",
90+
"textLength": 1
91+
}
92+
}
93+
}
94+
],
95+
"endOfFileToken": {
96+
"kind": "EndOfFileToken",
97+
"textLength": 0
98+
}
99+
}
100+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?php
2+
$x = new (function_call())();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
{
2+
"SourceFileNode": {
3+
"statementList": [
4+
{
5+
"InlineHtml": {
6+
"scriptSectionEndTag": null,
7+
"text": null,
8+
"scriptSectionStartTag": {
9+
"kind": "ScriptSectionStartTag",
10+
"textLength": 6
11+
}
12+
}
13+
},
14+
{
15+
"ExpressionStatement": {
16+
"expression": {
17+
"AssignmentExpression": {
18+
"leftOperand": {
19+
"Variable": {
20+
"dollar": null,
21+
"name": {
22+
"kind": "VariableName",
23+
"textLength": 2
24+
}
25+
}
26+
},
27+
"operator": {
28+
"kind": "EqualsToken",
29+
"textLength": 1
30+
},
31+
"byRef": null,
32+
"rightOperand": {
33+
"ObjectCreationExpression": {
34+
"newKeword": {
35+
"kind": "NewKeyword",
36+
"textLength": 3
37+
},
38+
"classTypeDesignator": {
39+
"ParenthesizedExpression": {
40+
"openParen": {
41+
"kind": "OpenParenToken",
42+
"textLength": 1
43+
},
44+
"expression": {
45+
"CallExpression": {
46+
"callableExpression": {
47+
"QualifiedName": {
48+
"globalSpecifier": null,
49+
"relativeSpecifier": null,
50+
"nameParts": [
51+
{
52+
"kind": "Name",
53+
"textLength": 13
54+
}
55+
]
56+
}
57+
},
58+
"openParen": {
59+
"kind": "OpenParenToken",
60+
"textLength": 1
61+
},
62+
"argumentExpressionList": null,
63+
"closeParen": {
64+
"kind": "CloseParenToken",
65+
"textLength": 1
66+
}
67+
}
68+
},
69+
"closeParen": {
70+
"kind": "CloseParenToken",
71+
"textLength": 1
72+
}
73+
}
74+
},
75+
"openParen": {
76+
"kind": "OpenParenToken",
77+
"textLength": 1
78+
},
79+
"argumentExpressionList": null,
80+
"closeParen": {
81+
"kind": "CloseParenToken",
82+
"textLength": 1
83+
},
84+
"classBaseClause": null,
85+
"classInterfaceClause": null,
86+
"classMembers": null
87+
}
88+
}
89+
}
90+
},
91+
"semicolon": {
92+
"kind": "SemicolonToken",
93+
"textLength": 1
94+
}
95+
}
96+
}
97+
],
98+
"endOfFileToken": {
99+
"kind": "EndOfFileToken",
100+
"textLength": 0
101+
}
102+
}
103+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?php
2+
new (new (new york())())();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]

0 commit comments

Comments
 (0)