@@ -168,17 +168,19 @@ private function setup() {
168
168
169
169
// ($a) ==> $a + 1 vs. ($a ?? $b)->invoke();
170
170
if (': ' === $ this ->token ->value || '==> ' === $ this ->token ->value ) {
171
- $ this ->token = $ this ->advance ();
172
- $ node = $ this ->func (null , []);
173
- $ this ->queue = [$ this ->token ];
174
- $ this ->token = new Node ($ this ->symbol ('; ' ));
175
171
$ node ->arity = 'lambda ' ;
172
+
173
+ $ this ->token = $ this ->advance ();
174
+ $ signature = $ this ->signature ();
175
+ $ this ->token = $ this ->advance ();
176
+ $ node ->value = [$ signature , $ this ->expression (0 )];
176
177
} else {
178
+ $ node ->arity = 'braced ' ;
179
+
177
180
$ this ->token = $ this ->advance ();
178
181
$ this ->token = $ this ->expect ('( ' );
179
182
$ node ->value = $ this ->expression (0 );
180
183
$ this ->token = $ this ->expect (') ' );
181
- $ node ->arity = 'braced ' ;
182
184
}
183
185
return $ node ;
184
186
});
@@ -267,15 +269,56 @@ private function setup() {
267
269
// Closure `$a= function() { ... };` vs. declaration `function a() { ... }`;
268
270
// the latter explicitely becomes a statement by pushing a semicolon.
269
271
if ('( ' === $ this ->token ->symbol ->id ) {
270
- $ node = $ this ->func (null , []);
271
272
$ node ->arity = 'closure ' ;
273
+ $ signature = $ this ->signature ();
274
+
275
+ if ('use ' === $ this ->token ->value ) {
276
+ $ this ->token = $ this ->advance ();
277
+ $ this ->token = $ this ->advance ();
278
+ $ use = [];
279
+ while (') ' !== $ this ->token ->symbol ->id ) {
280
+ if ('& ' === $ this ->token ->value ) {
281
+ $ this ->token = $ this ->advance ();
282
+ $ use []= '&$ ' .$ this ->token ->value ;
283
+ } else {
284
+ $ use []= '$ ' .$ this ->token ->value ;
285
+ }
286
+ $ this ->token = $ this ->advance ();
287
+ if (') ' === $ this ->token ->symbol ->id ) break ;
288
+ $ this ->token = $ this ->expect (', ' );
289
+ }
290
+ $ this ->token = $ this ->expect (') ' );
291
+ } else {
292
+ $ use = null ;
293
+ }
294
+
295
+ $ this ->token = $ this ->expect ('{ ' );
296
+ $ statements = $ this ->statements ();
297
+ $ this ->token = $ this ->expect ('} ' );
298
+
299
+ $ node ->value = [$ signature , $ use , $ statements ];
272
300
} else {
301
+ $ node ->arity = 'function ' ;
273
302
$ name = $ this ->token ->value ;
274
303
$ this ->token = $ this ->advance ();
275
- $ node = $ this ->func ($ name , []);
276
- $ node ->arity = 'function ' ;
304
+ $ signature = $ this ->signature ();
305
+
306
+ if ('==> ' === $ this ->token ->value ) { // Compact syntax, terminated with ';'
307
+ $ n = new Node ($ this ->token ->symbol );
308
+ $ this ->token = $ this ->advance ();
309
+ $ n ->value = $ this ->expression (0 );
310
+ $ n ->arity = 'return ' ;
311
+ $ statements = [$ n ];
312
+ $ this ->token = $ this ->expect ('; ' );
313
+ } else { // Regular function
314
+ $ this ->token = $ this ->expect ('{ ' );
315
+ $ statements = $ this ->statements ();
316
+ $ this ->token = $ this ->expect ('} ' );
317
+ }
318
+
277
319
$ this ->queue = [$ this ->token ];
278
320
$ this ->token = new Node ($ this ->symbol ('; ' ));
321
+ $ node ->value = [$ name , $ signature , $ statements ];
279
322
}
280
323
281
324
return $ node ;
@@ -710,64 +753,20 @@ private function parameters() {
710
753
return $ parameters ;
711
754
}
712
755
713
- private function func ($ name , $ modifiers ) {
714
- $ node = new Node ($ this ->token ->symbol );
715
-
716
- $ this ->scope = new Scope ($ this ->scope ); {
717
- $ this ->token = $ this ->expect ('( ' );
718
- $ parameters = $ this ->parameters ();
719
- $ this ->token = $ this ->expect (') ' );
756
+ private function signature () {
757
+ $ this ->token = $ this ->expect ('( ' );
758
+ $ parameters = $ this ->parameters ();
759
+ $ this ->token = $ this ->expect (') ' );
720
760
721
- if (': ' === $ this ->token ->value ) {
722
- $ this ->token = $ this ->advance ();
723
- $ return = $ this ->scope ->resolve ($ this ->token ->value );
724
- $ this ->token = $ this ->advance ();
725
- } else {
726
- $ return = null ;
727
- }
728
-
729
- if ('use ' === $ this ->token ->value ) {
730
- $ this ->token = $ this ->advance ();
731
- $ this ->token = $ this ->advance ();
732
- $ use = [];
733
- while (') ' !== $ this ->token ->symbol ->id ) {
734
- if ('& ' === $ this ->token ->value ) {
735
- $ this ->token = $ this ->advance ();
736
- $ use []= '&$ ' .$ this ->token ->value ;
737
- } else {
738
- $ use []= '$ ' .$ this ->token ->value ;
739
- }
740
- $ this ->token = $ this ->advance ();
741
- if (') ' === $ this ->token ->symbol ->id ) break ;
742
- $ this ->token = $ this ->expect (', ' );
743
- }
744
- $ this ->token = $ this ->expect (') ' );
745
- } else {
746
- $ use = null ;
747
- }
748
-
749
- if ('{ ' === $ this ->token ->value ) {
750
- $ this ->token = $ this ->advance ();
751
- $ statements = $ this ->statements ();
752
- $ this ->token = $ this ->expect ('} ' );
753
- } else if ('; ' === $ this ->token ->value ) {
754
- $ statements = null ;
755
- $ this ->token = $ this ->expect ('; ' );
756
- } else if ('==> ' === $ this ->token ->value ) {
757
- $ n = new Node ($ this ->token ->symbol );
758
- $ this ->token = $ this ->advance ();
759
- $ n ->value = $ this ->expression (0 );
760
- $ n ->arity = 'return ' ;
761
- $ statements = [$ n ];
762
- $ this ->token = $ this ->expect ('; ' );
763
- } else {
764
- $ this ->token = $ this ->expect ('{ or ==> ' );
765
- }
761
+ if (': ' === $ this ->token ->value ) {
762
+ $ this ->token = $ this ->advance ();
763
+ $ return = $ this ->scope ->resolve ($ this ->token ->value );
764
+ $ this ->token = $ this ->advance ();
765
+ } else {
766
+ $ return = null ;
766
767
}
767
768
768
- $ this ->scope = $ this ->scope ->parent ;
769
- $ node ->value = [$ name , $ modifiers , $ parameters , $ statements , $ return , $ use ];
770
- return $ node ;
769
+ return [$ parameters , $ return ];
771
770
}
772
771
773
772
private function type ($ name , $ modifiers = []) {
@@ -845,12 +844,33 @@ private function body() {
845
844
$ this ->token = $ this ->advance ();
846
845
$ this ->token = $ this ->expect ('; ' );
847
846
} else if ('function ' === $ this ->token ->symbol ->id ) {
847
+ $ member = new Node ($ this ->token ->symbol );
848
+ $ member ->arity = 'method ' ;
849
+
848
850
$ this ->token = $ this ->advance ();
849
851
$ name = $ this ->token ->value ;
850
852
$ this ->token = $ this ->advance ();
851
- $ member = $ this ->func ($ name , $ modifiers );
852
- $ member ->arity = 'method ' ;
853
- $ member ->value []= $ annotations ;
853
+ $ signature = $ this ->signature ();
854
+
855
+ if ('{ ' === $ this ->token ->value ) { // Regular body
856
+ $ this ->token = $ this ->advance ();
857
+ $ statements = $ this ->statements ();
858
+ $ this ->token = $ this ->expect ('} ' );
859
+ } else if ('; ' === $ this ->token ->value ) { // Abstract or interface method
860
+ $ statements = null ;
861
+ $ this ->token = $ this ->expect ('; ' );
862
+ } else if ('==> ' === $ this ->token ->value ) { // Compact syntax, terminated with ';'
863
+ $ n = new Node ($ this ->token ->symbol );
864
+ $ this ->token = $ this ->advance ();
865
+ $ n ->value = $ this ->expression (0 );
866
+ $ n ->arity = 'return ' ;
867
+ $ statements = [$ n ];
868
+ $ this ->token = $ this ->expect ('; ' );
869
+ } else {
870
+ $ this ->token = $ this ->expect ('{, ; or ==> ' );
871
+ }
872
+
873
+ $ member ->value = [$ name , $ modifiers , $ signature , $ annotations , $ statements ];
854
874
$ body []= $ member ;
855
875
$ modifiers = [];
856
876
$ annotations = null ;
0 commit comments