1313 CastExpression ,
1414 CatchStatement ,
1515 ClassDeclaration ,
16+ CloneExpression ,
1617 ClosureExpression ,
1718 Comment ,
1819 Constant ,
@@ -153,18 +154,8 @@ public function __construct() {
153154 if ('( ' === $ parse ->token ->value ) {
154155 $ parse ->expecting ('( ' , 'invoke expression ' );
155156
156- // Resolve ambiguity by looking ahead: `func(...)` which is a first-class
157- // callable reference vs. `func(...$it)` - a call with an unpacked argument
158- if ('... ' === $ parse ->token ->value ) {
159- $ dots = $ parse ->token ;
160- $ parse ->forward ();
161- if (') ' === $ parse ->token ->value ) {
162- $ parse ->forward ();
163- return new CallableExpression (new ScopeExpression ($ scope , $ expr , $ token ->line ), $ left ->line );
164- }
165-
166- array_unshift ($ parse ->queue , $ parse ->token );
167- $ parse ->token = $ dots ;
157+ if ($ this ->callable ($ parse )) {
158+ return new CallableExpression (new ScopeExpression ($ scope , $ expr , $ token ->line ), $ token ->line );
168159 }
169160
170161 $ arguments = $ this ->arguments ($ parse );
@@ -189,16 +180,8 @@ public function __construct() {
189180
190181 // Resolve ambiguity by looking ahead: `func(...)` which is a first-class
191182 // callable reference vs. `func(...$it)` - a call with an unpacked argument
192- if ('... ' === $ parse ->token ->value ) {
193- $ dots = $ parse ->token ;
194- $ parse ->forward ();
195- if (') ' === $ parse ->token ->value ) {
196- $ parse ->forward ();
197- return new CallableExpression ($ left , $ left ->line );
198- }
199-
200- array_unshift ($ parse ->queue , $ parse ->token );
201- $ parse ->token = $ dots ;
183+ if ($ this ->callable ($ parse )) {
184+ return new CallableExpression ($ left , $ token ->line );
202185 }
203186
204187 $ arguments = $ this ->arguments ($ parse );
@@ -233,7 +216,6 @@ public function __construct() {
233216 $ this ->prefix ('- ' , 90 );
234217 $ this ->prefix ('++ ' , 90 );
235218 $ this ->prefix ('-- ' , 90 );
236- $ this ->prefix ('clone ' , 90 );
237219
238220 $ this ->assignment ('= ' );
239221 $ this ->assignment ('&= ' );
@@ -294,6 +276,24 @@ public function __construct() {
294276 }
295277 });
296278
279+ $ this ->prefix ('clone ' , 90 , function ($ parse , $ token ) {
280+
281+ // clone $x vs. clone($x) or clone($x, ["id" => 6100])
282+ if ('( ' === $ parse ->token ->value ) {
283+ $ parse ->forward ();
284+ if ($ this ->callable ($ parse )) {
285+ return new CallableExpression (new Literal ('clone ' , $ token ->line ), $ token ->line );
286+ }
287+
288+ $ arguments = $ this ->arguments ($ parse );
289+ $ parse ->expecting (') ' , 'clone arguments ' );
290+ } else {
291+ $ arguments = [$ this ->expression ($ parse , 90 )];
292+ }
293+
294+ return new CloneExpression ($ arguments , $ token ->line );
295+ });
296+
297297 $ this ->prefix ('{ ' , 0 , function ($ parse , $ token ) {
298298 $ statements = $ this ->statements ($ parse );
299299 $ parse ->expecting ('} ' , 'block ' );
@@ -339,25 +339,16 @@ public function __construct() {
339339
340340 // Resolve ambiguity by looking ahead: `new T(...)` which is a first-class
341341 // callable reference vs. `new T(...$it)` - a call with an unpacked argument
342- if ('... ' === $ parse ->token ->value ) {
343- $ dots = $ parse ->token ;
344- $ parse ->forward ();
345- if (') ' === $ parse ->token ->value ) {
346- $ parse ->forward ();
347-
348- if (null === $ type ) {
349- $ class = $ this ->class ($ parse , null );
350- $ class ->annotations = $ annotations ;
351- $ new = new NewClassExpression ($ class , null , $ token ->line );
352- } else {
353- $ new = new NewExpression ($ type , null , $ token ->line );
354- }
355-
356- return new CallableNewExpression ($ new , $ token ->line );
342+ if ($ this ->callable ($ parse )) {
343+ if (null === $ type ) {
344+ $ class = $ this ->class ($ parse , null );
345+ $ class ->annotations = $ annotations ;
346+ $ new = new NewClassExpression ($ class , null , $ token ->line );
347+ } else {
348+ $ new = new NewExpression ($ type , null , $ token ->line );
357349 }
358350
359- array_unshift ($ parse ->queue , $ parse ->token );
360- $ parse ->token = $ dots ;
351+ return new CallableNewExpression ($ new , $ token ->line );
361352 }
362353
363354 $ arguments = $ this ->arguments ($ parse );
@@ -1725,6 +1716,22 @@ public function class($parse, $name, $comment= null, $modifiers= []) {
17251716 return $ decl ;
17261717 }
17271718
1719+ public function callable ($ parse ) {
1720+ if ('... ' === $ parse ->token ->value ) {
1721+ $ dots = $ parse ->token ;
1722+ $ parse ->forward ();
1723+ if (') ' === $ parse ->token ->value ) {
1724+ $ parse ->forward ();
1725+ return true ;
1726+ }
1727+
1728+ // Not first-class callable syntax but unpack
1729+ array_unshift ($ parse ->queue , $ parse ->token );
1730+ $ parse ->token = $ dots ;
1731+ }
1732+ return false ;
1733+ }
1734+
17281735 public function arguments ($ parse ) {
17291736 $ arguments = [];
17301737 while (') ' !== $ parse ->token ->value ) {
0 commit comments