Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 150 | Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
%pure_parser
2
%expect 2
3
 
4
%tokens
5
 
6
%%
7
 
8
start:
9
    top_statement_list                                      { $$ = $this->handleNamespaces($1); }
10
;
11
 
12
top_statement_list_ex:
13
      top_statement_list_ex top_statement                   { pushNormalizing($1, $2); }
14
    | /* empty */                                           { init(); }
15
;
16
 
17
top_statement_list:
18
      top_statement_list_ex
19
          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
20
            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
21
;
22
 
23
ampersand:
24
      T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
25
    | T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG
26
;
27
 
28
reserved_non_modifiers:
29
      T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND
30
    | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE
31
    | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH
32
    | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
33
    | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT
34
    | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
35
    | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER | T_FN
36
    | T_MATCH | T_ENUM
37
;
38
 
39
semi_reserved:
40
      reserved_non_modifiers
41
    | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC | T_READONLY
42
;
43
 
44
identifier_maybe_reserved:
45
      T_STRING                                              { $$ = Node\Identifier[$1]; }
46
    | semi_reserved                                         { $$ = Node\Identifier[$1]; }
47
;
48
 
49
identifier_not_reserved:
50
      T_STRING                                              { $$ = Node\Identifier[$1]; }
51
;
52
 
53
reserved_non_modifiers_identifier:
54
      reserved_non_modifiers                                { $$ = Node\Identifier[$1]; }
55
;
56
 
57
namespace_declaration_name:
58
      T_STRING                                              { $$ = Name[$1]; }
59
    | semi_reserved                                         { $$ = Name[$1]; }
60
    | T_NAME_QUALIFIED                                      { $$ = Name[$1]; }
61
;
62
 
63
namespace_name:
64
      T_STRING                                              { $$ = Name[$1]; }
65
    | T_NAME_QUALIFIED                                      { $$ = Name[$1]; }
66
;
67
 
68
legacy_namespace_name:
69
      namespace_name                                        { $$ = $1; }
70
    | T_NAME_FULLY_QUALIFIED                                { $$ = Name[substr($1, 1)]; }
71
;
72
 
73
plain_variable:
74
      T_VARIABLE                                            { $$ = Expr\Variable[parseVar($1)]; }
75
;
76
 
77
semi:
78
      ';'                                                   { /* nothing */ }
79
    | error                                                 { /* nothing */ }
80
;
81
 
82
no_comma:
83
      /* empty */ { /* nothing */ }
84
    | ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); }
85
;
86
 
87
optional_comma:
88
      /* empty */
89
    | ','
90
;
91
 
92
attribute_decl:
93
      class_name                                            { $$ = Node\Attribute[$1, []]; }
94
    | class_name argument_list                              { $$ = Node\Attribute[$1, $2]; }
95
;
96
 
97
attribute_group:
98
      attribute_decl                                        { init($1); }
99
    | attribute_group ',' attribute_decl                    { push($1, $3); }
100
;
101
 
102
attribute:
103
      T_ATTRIBUTE attribute_group optional_comma ']'        { $$ = Node\AttributeGroup[$2]; }
104
;
105
 
106
attributes:
107
      attribute                                             { init($1); }
108
    | attributes attribute                                  { push($1, $2); }
109
;
110
 
111
optional_attributes:
112
      /* empty */                                           { $$ = []; }
113
    | attributes                                            { $$ = $1; }
114
;
115
 
116
top_statement:
117
      statement                                             { $$ = $1; }
118
    | function_declaration_statement                        { $$ = $1; }
119
    | class_declaration_statement                           { $$ = $1; }
120
    | T_HALT_COMPILER
121
          { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; }
122
    | T_NAMESPACE namespace_declaration_name semi
123
          { $$ = Stmt\Namespace_[$2, null];
124
            $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
125
            $this->checkNamespace($$); }
126
    | T_NAMESPACE namespace_declaration_name '{' top_statement_list '}'
127
          { $$ = Stmt\Namespace_[$2, $4];
128
            $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
129
            $this->checkNamespace($$); }
130
    | T_NAMESPACE '{' top_statement_list '}'
131
          { $$ = Stmt\Namespace_[null, $3];
132
            $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
133
            $this->checkNamespace($$); }
134
    | T_USE use_declarations semi                           { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; }
135
    | T_USE use_type use_declarations semi                  { $$ = Stmt\Use_[$3, $2]; }
136
    | group_use_declaration semi                            { $$ = $1; }
137
    | T_CONST constant_declaration_list semi                { $$ = Stmt\Const_[$2]; }
138
;
139
 
140
use_type:
141
      T_FUNCTION                                            { $$ = Stmt\Use_::TYPE_FUNCTION; }
142
    | T_CONST                                               { $$ = Stmt\Use_::TYPE_CONSTANT; }
143
;
144
 
145
group_use_declaration:
146
      T_USE use_type legacy_namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations '}'
147
          { $$ = Stmt\GroupUse[$3, $6, $2]; }
148
    | T_USE legacy_namespace_name T_NS_SEPARATOR '{' inline_use_declarations '}'
149
          { $$ = Stmt\GroupUse[$2, $5, Stmt\Use_::TYPE_UNKNOWN]; }
150
;
151
 
152
unprefixed_use_declarations:
153
      non_empty_unprefixed_use_declarations optional_comma  { $$ = $1; }
154
;
155
 
156
non_empty_unprefixed_use_declarations:
157
      non_empty_unprefixed_use_declarations ',' unprefixed_use_declaration
158
          { push($1, $3); }
159
    | unprefixed_use_declaration                            { init($1); }
160
;
161
 
162
use_declarations:
163
      non_empty_use_declarations no_comma                   { $$ = $1; }
164
;
165
 
166
non_empty_use_declarations:
167
      non_empty_use_declarations ',' use_declaration        { push($1, $3); }
168
    | use_declaration                                       { init($1); }
169
;
170
 
171
inline_use_declarations:
172
      non_empty_inline_use_declarations optional_comma      { $$ = $1; }
173
;
174
 
175
non_empty_inline_use_declarations:
176
      non_empty_inline_use_declarations ',' inline_use_declaration
177
          { push($1, $3); }
178
    | inline_use_declaration                                { init($1); }
179
;
180
 
181
unprefixed_use_declaration:
182
      namespace_name
183
          { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); }
184
    | namespace_name T_AS identifier_not_reserved
185
          { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); }
186
;
187
 
188
use_declaration:
189
      legacy_namespace_name
190
          { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); }
191
    | legacy_namespace_name T_AS identifier_not_reserved
192
          { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); }
193
;
194
 
195
inline_use_declaration:
196
      unprefixed_use_declaration                            { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; }
197
    | use_type unprefixed_use_declaration                   { $$ = $2; $$->type = $1; }
198
;
199
 
200
constant_declaration_list:
201
      non_empty_constant_declaration_list no_comma          { $$ = $1; }
202
;
203
 
204
non_empty_constant_declaration_list:
205
      non_empty_constant_declaration_list ',' constant_declaration
206
          { push($1, $3); }
207
    | constant_declaration                                  { init($1); }
208
;
209
 
210
constant_declaration:
211
    identifier_not_reserved '=' expr                        { $$ = Node\Const_[$1, $3]; }
212
;
213
 
214
class_const_list:
215
      non_empty_class_const_list no_comma                   { $$ = $1; }
216
;
217
 
218
non_empty_class_const_list:
219
      non_empty_class_const_list ',' class_const            { push($1, $3); }
220
    | class_const                                           { init($1); }
221
;
222
 
223
class_const:
224
    identifier_maybe_reserved '=' expr                      { $$ = Node\Const_[$1, $3]; }
225
;
226
 
227
inner_statement_list_ex:
228
      inner_statement_list_ex inner_statement               { pushNormalizing($1, $2); }
229
    | /* empty */                                           { init(); }
230
;
231
 
232
inner_statement_list:
233
      inner_statement_list_ex
234
          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
235
            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
236
;
237
 
238
inner_statement:
239
      statement                                             { $$ = $1; }
240
    | function_declaration_statement                        { $$ = $1; }
241
    | class_declaration_statement                           { $$ = $1; }
242
    | T_HALT_COMPILER
243
          { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); }
244
;
245
 
246
non_empty_statement:
247
      '{' inner_statement_list '}'
248
    {
249
        if ($2) {
250
            $$ = $2; prependLeadingComments($$);
251
        } else {
252
            makeNop($$, $this->startAttributeStack[#1], $this->endAttributes);
253
            if (null === $$) { $$ = array(); }
254
        }
255
    }
256
    | T_IF '(' expr ')' statement elseif_list else_single
257
          { $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; }
258
    | T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
259
          { $$ = Stmt\If_[$3, ['stmts' => $6, 'elseifs' => $7, 'else' => $8]]; }
260
    | T_WHILE '(' expr ')' while_statement                  { $$ = Stmt\While_[$3, $5]; }
261
    | T_DO statement T_WHILE '(' expr ')' ';'               { $$ = Stmt\Do_   [$5, toArray($2)]; }
262
    | T_FOR '(' for_expr ';'  for_expr ';' for_expr ')' for_statement
263
          { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; }
264
    | T_SWITCH '(' expr ')' switch_case_list                { $$ = Stmt\Switch_[$3, $5]; }
265
    | T_BREAK optional_expr semi                            { $$ = Stmt\Break_[$2]; }
266
    | T_CONTINUE optional_expr semi                         { $$ = Stmt\Continue_[$2]; }
267
    | T_RETURN optional_expr semi                           { $$ = Stmt\Return_[$2]; }
268
    | T_GLOBAL global_var_list semi                         { $$ = Stmt\Global_[$2]; }
269
    | T_STATIC static_var_list semi                         { $$ = Stmt\Static_[$2]; }
270
    | T_ECHO expr_list_forbid_comma semi                    { $$ = Stmt\Echo_[$2]; }
271
    | T_INLINE_HTML                                         { $$ = Stmt\InlineHTML[$1]; }
272
    | expr semi {
273
        $e = $1;
274
        if ($e instanceof Expr\Throw_) {
275
            // For backwards-compatibility reasons, convert throw in statement position into
276
            // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_).
277
            $$ = Stmt\Throw_[$e->expr];
278
        } else {
279
            $$ = Stmt\Expression[$e];
280
        }
281
    }
282
    | T_UNSET '(' variables_list ')' semi                   { $$ = Stmt\Unset_[$3]; }
283
    | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
284
          { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; }
285
    | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
286
          { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; }
287
    | T_FOREACH '(' expr error ')' foreach_statement
288
          { $$ = Stmt\Foreach_[$3, new Expr\Error(stackAttributes(#4)), ['stmts' => $6]]; }
289
    | T_DECLARE '(' declare_list ')' declare_statement      { $$ = Stmt\Declare_[$3, $5]; }
290
    | T_TRY '{' inner_statement_list '}' catches optional_finally
291
          { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); }
292
    | T_GOTO identifier_not_reserved semi                   { $$ = Stmt\Goto_[$2]; }
293
    | identifier_not_reserved ':'                           { $$ = Stmt\Label[$1]; }
294
    | error                                                 { $$ = array(); /* means: no statement */ }
295
;
296
 
297
statement:
298
      non_empty_statement                                   { $$ = $1; }
299
    | ';'
300
          { makeNop($$, $this->startAttributeStack[#1], $this->endAttributes);
301
            if ($$ === null) $$ = array(); /* means: no statement */ }
302
;
303
 
304
catches:
305
      /* empty */                                           { init(); }
306
    | catches catch                                         { push($1, $2); }
307
;
308
 
309
name_union:
310
      name                                                  { init($1); }
311
    | name_union '|' name                                   { push($1, $3); }
312
;
313
 
314
catch:
315
    T_CATCH '(' name_union optional_plain_variable ')' '{' inner_statement_list '}'
316
        { $$ = Stmt\Catch_[$3, $4, $7]; }
317
;
318
 
319
optional_finally:
320
      /* empty */                                           { $$ = null; }
321
    | T_FINALLY '{' inner_statement_list '}'                { $$ = Stmt\Finally_[$3]; }
322
;
323
 
324
variables_list:
325
      non_empty_variables_list optional_comma               { $$ = $1; }
326
;
327
 
328
non_empty_variables_list:
329
      variable                                              { init($1); }
330
    | non_empty_variables_list ',' variable                 { push($1, $3); }
331
;
332
 
333
optional_ref:
334
      /* empty */                                           { $$ = false; }
335
    | ampersand                                             { $$ = true; }
336
;
337
 
338
optional_arg_ref:
339
      /* empty */                                           { $$ = false; }
340
    | T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG                 { $$ = true; }
341
;
342
 
343
optional_ellipsis:
344
      /* empty */                                           { $$ = false; }
345
    | T_ELLIPSIS                                            { $$ = true; }
346
;
347
 
348
block_or_error:
349
      '{' inner_statement_list '}'                          { $$ = $2; }
350
    | error                                                 { $$ = []; }
351
;
352
 
353
function_declaration_statement:
354
      T_FUNCTION optional_ref identifier_not_reserved '(' parameter_list ')' optional_return_type block_or_error
355
          { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; }
356
    | attributes T_FUNCTION optional_ref identifier_not_reserved '(' parameter_list ')' optional_return_type block_or_error
357
          { $$ = Stmt\Function_[$4, ['byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; }
358
;
359
 
360
class_declaration_statement:
361
      optional_attributes class_entry_type identifier_not_reserved extends_from implements_list '{' class_statement_list '}'
362
          { $$ = Stmt\Class_[$3, ['type' => $2, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]];
363
            $this->checkClass($$, #3); }
364
    | optional_attributes T_INTERFACE identifier_not_reserved interface_extends_list '{' class_statement_list '}'
365
          { $$ = Stmt\Interface_[$3, ['extends' => $4, 'stmts' => $6, 'attrGroups' => $1]];
366
            $this->checkInterface($$, #3); }
367
    | optional_attributes T_TRAIT identifier_not_reserved '{' class_statement_list '}'
368
          { $$ = Stmt\Trait_[$3, ['stmts' => $5, 'attrGroups' => $1]]; }
369
    | optional_attributes T_ENUM identifier_not_reserved enum_scalar_type implements_list '{' class_statement_list '}'
370
          { $$ = Stmt\Enum_[$3, ['scalarType' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]];
371
            $this->checkEnum($$, #3); }
372
;
373
 
374
enum_scalar_type:
375
      /* empty */                                           { $$ = null; }
376
    | ':' type                                              { $$ = $2; }
377
 
378
enum_case_expr:
379
      /* empty */                                           { $$ = null; }
380
    | '=' expr                                              { $$ = $2; }
381
;
382
 
383
class_entry_type:
384
      T_CLASS                                               { $$ = 0; }
385
    | class_modifiers T_CLASS                               { $$ = $1; }
386
;
387
 
388
class_modifiers:
389
      class_modifier                                        { $$ = $1; }
390
    | class_modifiers class_modifier                        { $this->checkClassModifier($1, $2, #2); $$ = $1 | $2; }
391
;
392
 
393
class_modifier:
394
      T_ABSTRACT                                            { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
395
    | T_FINAL                                               { $$ = Stmt\Class_::MODIFIER_FINAL; }
396
    | T_READONLY                                            { $$ = Stmt\Class_::MODIFIER_READONLY; }
397
;
398
 
399
extends_from:
400
      /* empty */                                           { $$ = null; }
401
    | T_EXTENDS class_name                                  { $$ = $2; }
402
;
403
 
404
interface_extends_list:
405
      /* empty */                                           { $$ = array(); }
406
    | T_EXTENDS class_name_list                             { $$ = $2; }
407
;
408
 
409
implements_list:
410
      /* empty */                                           { $$ = array(); }
411
    | T_IMPLEMENTS class_name_list                          { $$ = $2; }
412
;
413
 
414
class_name_list:
415
      non_empty_class_name_list no_comma                    { $$ = $1; }
416
;
417
 
418
non_empty_class_name_list:
419
      class_name                                            { init($1); }
420
    | non_empty_class_name_list ',' class_name              { push($1, $3); }
421
;
422
 
423
for_statement:
424
      statement                                             { $$ = toArray($1); }
425
    | ':' inner_statement_list T_ENDFOR ';'                 { $$ = $2; }
426
;
427
 
428
foreach_statement:
429
      statement                                             { $$ = toArray($1); }
430
    | ':' inner_statement_list T_ENDFOREACH ';'             { $$ = $2; }
431
;
432
 
433
declare_statement:
434
      non_empty_statement                                   { $$ = toArray($1); }
435
    | ';'                                                   { $$ = null; }
436
    | ':' inner_statement_list T_ENDDECLARE ';'             { $$ = $2; }
437
;
438
 
439
declare_list:
440
      non_empty_declare_list no_comma                       { $$ = $1; }
441
;
442
 
443
non_empty_declare_list:
444
      declare_list_element                                  { init($1); }
445
    | non_empty_declare_list ',' declare_list_element       { push($1, $3); }
446
;
447
 
448
declare_list_element:
449
      identifier_not_reserved '=' expr                      { $$ = Stmt\DeclareDeclare[$1, $3]; }
450
;
451
 
452
switch_case_list:
453
      '{' case_list '}'                                     { $$ = $2; }
454
    | '{' ';' case_list '}'                                 { $$ = $3; }
455
    | ':' case_list T_ENDSWITCH ';'                         { $$ = $2; }
456
    | ':' ';' case_list T_ENDSWITCH ';'                     { $$ = $3; }
457
;
458
 
459
case_list:
460
      /* empty */                                           { init(); }
461
    | case_list case                                        { push($1, $2); }
462
;
463
 
464
case:
465
      T_CASE expr case_separator inner_statement_list_ex    { $$ = Stmt\Case_[$2, $4]; }
466
    | T_DEFAULT case_separator inner_statement_list_ex      { $$ = Stmt\Case_[null, $3]; }
467
;
468
 
469
case_separator:
470
      ':'
471
    | ';'
472
;
473
 
474
match:
475
      T_MATCH '(' expr ')' '{' match_arm_list '}'           { $$ = Expr\Match_[$3, $6]; }
476
;
477
 
478
match_arm_list:
479
      /* empty */                                           { $$ = []; }
480
    | non_empty_match_arm_list optional_comma               { $$ = $1; }
481
;
482
 
483
non_empty_match_arm_list:
484
      match_arm                                             { init($1); }
485
    | non_empty_match_arm_list ',' match_arm                { push($1, $3); }
486
;
487
 
488
match_arm:
489
      expr_list_allow_comma T_DOUBLE_ARROW expr             { $$ = Node\MatchArm[$1, $3]; }
490
    | T_DEFAULT optional_comma T_DOUBLE_ARROW expr          { $$ = Node\MatchArm[null, $4]; }
491
;
492
 
493
while_statement:
494
      statement                                             { $$ = toArray($1); }
495
    | ':' inner_statement_list T_ENDWHILE ';'               { $$ = $2; }
496
;
497
 
498
elseif_list:
499
      /* empty */                                           { init(); }
500
    | elseif_list elseif                                    { push($1, $2); }
501
;
502
 
503
elseif:
504
      T_ELSEIF '(' expr ')' statement                       { $$ = Stmt\ElseIf_[$3, toArray($5)]; }
505
;
506
 
507
new_elseif_list:
508
      /* empty */                                           { init(); }
509
    | new_elseif_list new_elseif                            { push($1, $2); }
510
;
511
 
512
new_elseif:
513
     T_ELSEIF '(' expr ')' ':' inner_statement_list         { $$ = Stmt\ElseIf_[$3, $6]; }
514
;
515
 
516
else_single:
517
      /* empty */                                           { $$ = null; }
518
    | T_ELSE statement                                      { $$ = Stmt\Else_[toArray($2)]; }
519
;
520
 
521
new_else_single:
522
      /* empty */                                           { $$ = null; }
523
    | T_ELSE ':' inner_statement_list                       { $$ = Stmt\Else_[$3]; }
524
;
525
 
526
foreach_variable:
527
      variable                                              { $$ = array($1, false); }
528
    | ampersand variable                                    { $$ = array($2, true); }
529
    | list_expr                                             { $$ = array($1, false); }
530
    | array_short_syntax                                    { $$ = array($1, false); }
531
;
532
 
533
parameter_list:
534
      non_empty_parameter_list optional_comma               { $$ = $1; }
535
    | /* empty */                                           { $$ = array(); }
536
;
537
 
538
non_empty_parameter_list:
539
      parameter                                             { init($1); }
540
    | non_empty_parameter_list ',' parameter                { push($1, $3); }
541
;
542
 
543
optional_property_modifiers:
544
      /* empty */               { $$ = 0; }
545
    | optional_property_modifiers property_modifier
546
          { $this->checkModifier($1, $2, #2); $$ = $1 | $2; }
547
;
548
 
549
property_modifier:
550
      T_PUBLIC                  { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
551
    | T_PROTECTED               { $$ = Stmt\Class_::MODIFIER_PROTECTED; }
552
    | T_PRIVATE                 { $$ = Stmt\Class_::MODIFIER_PRIVATE; }
553
    | T_READONLY                { $$ = Stmt\Class_::MODIFIER_READONLY; }
554
;
555
 
556
parameter:
557
      optional_attributes optional_property_modifiers optional_type_without_static
558
      optional_arg_ref optional_ellipsis plain_variable
559
          { $$ = new Node\Param($6, null, $3, $4, $5, attributes(), $2, $1);
560
            $this->checkParam($$); }
561
    | optional_attributes optional_property_modifiers optional_type_without_static
562
      optional_arg_ref optional_ellipsis plain_variable '=' expr
563
          { $$ = new Node\Param($6, $8, $3, $4, $5, attributes(), $2, $1);
564
            $this->checkParam($$); }
565
    | optional_attributes optional_property_modifiers optional_type_without_static
566
      optional_arg_ref optional_ellipsis error
567
          { $$ = new Node\Param(Expr\Error[], null, $3, $4, $5, attributes(), $2, $1); }
568
;
569
 
570
type_expr:
571
      type                                                  { $$ = $1; }
572
    | '?' type                                              { $$ = Node\NullableType[$2]; }
573
    | union_type                                            { $$ = Node\UnionType[$1]; }
574
    | intersection_type                                     { $$ = $1; }
575
;
576
 
577
type:
578
      type_without_static                                   { $$ = $1; }
579
    | T_STATIC                                              { $$ = Node\Name['static']; }
580
;
581
 
582
type_without_static:
583
      name                                                  { $$ = $this->handleBuiltinTypes($1); }
584
    | T_ARRAY                                               { $$ = Node\Identifier['array']; }
585
    | T_CALLABLE                                            { $$ = Node\Identifier['callable']; }
586
;
587
 
588
union_type_element:
589
                type { $$ = $1; }
590
        |        '(' intersection_type ')' { $$ = $2; }
591
;
592
 
593
union_type:
594
      union_type_element '|' union_type_element             { init($1, $3); }
595
    | union_type '|' union_type_element                     { push($1, $3); }
596
;
597
 
598
union_type_without_static_element:
599
                type_without_static { $$ = $1; }
600
        |        '(' intersection_type_without_static ')' { $$ = $2; }
601
;
602
 
603
union_type_without_static:
604
      union_type_without_static_element '|' union_type_without_static_element   { init($1, $3); }
605
    | union_type_without_static '|' union_type_without_static_element           { push($1, $3); }
606
;
607
 
608
intersection_type_list:
609
      type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type   { init($1, $3); }
610
    | intersection_type_list T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type
611
          { push($1, $3); }
612
;
613
 
614
intersection_type:
615
      intersection_type_list { $$ = Node\IntersectionType[$1]; }
616
;
617
 
618
intersection_type_without_static_list:
619
      type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static
620
          { init($1, $3); }
621
    | intersection_type_without_static_list T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static
622
          { push($1, $3); }
623
;
624
 
625
intersection_type_without_static:
626
      intersection_type_without_static_list { $$ = Node\IntersectionType[$1]; }
627
;
628
 
629
type_expr_without_static:
630
      type_without_static                                   { $$ = $1; }
631
    | '?' type_without_static                               { $$ = Node\NullableType[$2]; }
632
    | union_type_without_static                             { $$ = Node\UnionType[$1]; }
633
    | intersection_type_without_static                      { $$ = $1; }
634
;
635
 
636
optional_type_without_static:
637
      /* empty */                                           { $$ = null; }
638
    | type_expr_without_static                              { $$ = $1; }
639
;
640
 
641
optional_return_type:
642
      /* empty */                                           { $$ = null; }
643
    | ':' type_expr                                         { $$ = $2; }
644
    | ':' error                                             { $$ = null; }
645
;
646
 
647
argument_list:
648
      '(' ')'                                               { $$ = array(); }
649
    | '(' non_empty_argument_list optional_comma ')'        { $$ = $2; }
650
    | '(' variadic_placeholder ')'                          { init($2); }
651
;
652
 
653
variadic_placeholder:
654
      T_ELLIPSIS                                            { $$ = Node\VariadicPlaceholder[]; }
655
;
656
 
657
non_empty_argument_list:
658
      argument                                              { init($1); }
659
    | non_empty_argument_list ',' argument                  { push($1, $3); }
660
;
661
 
662
argument:
663
      expr                                                  { $$ = Node\Arg[$1, false, false]; }
664
    | ampersand variable                                    { $$ = Node\Arg[$2, true, false]; }
665
    | T_ELLIPSIS expr                                       { $$ = Node\Arg[$2, false, true]; }
666
    | identifier_maybe_reserved ':' expr
667
          { $$ = new Node\Arg($3, false, false, attributes(), $1); }
668
;
669
 
670
global_var_list:
671
      non_empty_global_var_list no_comma                    { $$ = $1; }
672
;
673
 
674
non_empty_global_var_list:
675
      non_empty_global_var_list ',' global_var              { push($1, $3); }
676
    | global_var                                            { init($1); }
677
;
678
 
679
global_var:
680
      simple_variable                                       { $$ = $1; }
681
;
682
 
683
static_var_list:
684
      non_empty_static_var_list no_comma                    { $$ = $1; }
685
;
686
 
687
non_empty_static_var_list:
688
      non_empty_static_var_list ',' static_var              { push($1, $3); }
689
    | static_var                                            { init($1); }
690
;
691
 
692
static_var:
693
      plain_variable                                        { $$ = Stmt\StaticVar[$1, null]; }
694
    | plain_variable '=' expr                               { $$ = Stmt\StaticVar[$1, $3]; }
695
;
696
 
697
class_statement_list_ex:
698
      class_statement_list_ex class_statement               { if ($2 !== null) { push($1, $2); } }
699
    | /* empty */                                           { init(); }
700
;
701
 
702
class_statement_list:
703
      class_statement_list_ex
704
          { makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
705
            if ($nop !== null) { $1[] = $nop; } $$ = $1; }
706
;
707
 
708
class_statement:
709
      optional_attributes variable_modifiers optional_type_without_static property_declaration_list semi
710
          { $$ = new Stmt\Property($2, $4, attributes(), $3, $1);
711
            $this->checkProperty($$, #2); }
712
    | optional_attributes method_modifiers T_CONST class_const_list semi
713
          { $$ = new Stmt\ClassConst($4, $2, attributes(), $1);
714
            $this->checkClassConst($$, #2); }
715
    | optional_attributes method_modifiers T_FUNCTION optional_ref identifier_maybe_reserved '(' parameter_list ')'
716
      optional_return_type method_body
717
          { $$ = Stmt\ClassMethod[$5, ['type' => $2, 'byRef' => $4, 'params' => $7, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]];
718
            $this->checkClassMethod($$, #2); }
719
    | T_USE class_name_list trait_adaptations               { $$ = Stmt\TraitUse[$2, $3]; }
720
    | optional_attributes T_CASE identifier_maybe_reserved enum_case_expr semi
721
         { $$ = Stmt\EnumCase[$3, $4, $1]; }
722
    | error                                                 { $$ = null; /* will be skipped */ }
723
;
724
 
725
trait_adaptations:
726
      ';'                                                   { $$ = array(); }
727
    | '{' trait_adaptation_list '}'                         { $$ = $2; }
728
;
729
 
730
trait_adaptation_list:
731
      /* empty */                                           { init(); }
732
    | trait_adaptation_list trait_adaptation                { push($1, $2); }
733
;
734
 
735
trait_adaptation:
736
      trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';'
737
          { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; }
738
    | trait_method_reference T_AS member_modifier identifier_maybe_reserved ';'
739
          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; }
740
    | trait_method_reference T_AS member_modifier ';'
741
          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; }
742
    | trait_method_reference T_AS identifier_not_reserved ';'
743
          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
744
    | trait_method_reference T_AS reserved_non_modifiers_identifier ';'
745
          { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; }
746
;
747
 
748
trait_method_reference_fully_qualified:
749
      name T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved { $$ = array($1, $3); }
750
;
751
trait_method_reference:
752
      trait_method_reference_fully_qualified                { $$ = $1; }
753
    | identifier_maybe_reserved                             { $$ = array(null, $1); }
754
;
755
 
756
method_body:
757
      ';' /* abstract method */                             { $$ = null; }
758
    | block_or_error                                        { $$ = $1; }
759
;
760
 
761
variable_modifiers:
762
      non_empty_member_modifiers                            { $$ = $1; }
763
    | T_VAR                                                 { $$ = 0; }
764
;
765
 
766
method_modifiers:
767
      /* empty */                                           { $$ = 0; }
768
    | non_empty_member_modifiers                            { $$ = $1; }
769
;
770
 
771
non_empty_member_modifiers:
772
      member_modifier                                       { $$ = $1; }
773
    | non_empty_member_modifiers member_modifier            { $this->checkModifier($1, $2, #2); $$ = $1 | $2; }
774
;
775
 
776
member_modifier:
777
      T_PUBLIC                                              { $$ = Stmt\Class_::MODIFIER_PUBLIC; }
778
    | T_PROTECTED                                           { $$ = Stmt\Class_::MODIFIER_PROTECTED; }
779
    | T_PRIVATE                                             { $$ = Stmt\Class_::MODIFIER_PRIVATE; }
780
    | T_STATIC                                              { $$ = Stmt\Class_::MODIFIER_STATIC; }
781
    | T_ABSTRACT                                            { $$ = Stmt\Class_::MODIFIER_ABSTRACT; }
782
    | T_FINAL                                               { $$ = Stmt\Class_::MODIFIER_FINAL; }
783
    | T_READONLY                                            { $$ = Stmt\Class_::MODIFIER_READONLY; }
784
;
785
 
786
property_declaration_list:
787
      non_empty_property_declaration_list no_comma          { $$ = $1; }
788
;
789
 
790
non_empty_property_declaration_list:
791
      property_declaration                                  { init($1); }
792
    | non_empty_property_declaration_list ',' property_declaration
793
          { push($1, $3); }
794
;
795
 
796
property_decl_name:
797
      T_VARIABLE                                            { $$ = Node\VarLikeIdentifier[parseVar($1)]; }
798
;
799
 
800
property_declaration:
801
      property_decl_name                                    { $$ = Stmt\PropertyProperty[$1, null]; }
802
    | property_decl_name '=' expr                           { $$ = Stmt\PropertyProperty[$1, $3]; }
803
;
804
 
805
expr_list_forbid_comma:
806
      non_empty_expr_list no_comma                          { $$ = $1; }
807
;
808
 
809
expr_list_allow_comma:
810
      non_empty_expr_list optional_comma                    { $$ = $1; }
811
;
812
 
813
non_empty_expr_list:
814
      non_empty_expr_list ',' expr                          { push($1, $3); }
815
    | expr                                                  { init($1); }
816
;
817
 
818
for_expr:
819
      /* empty */                                           { $$ = array(); }
820
    | expr_list_forbid_comma                                { $$ = $1; }
821
;
822
 
823
expr:
824
      variable                                              { $$ = $1; }
825
    | list_expr '=' expr                                    { $$ = Expr\Assign[$1, $3]; }
826
    | array_short_syntax '=' expr                           { $$ = Expr\Assign[$1, $3]; }
827
    | variable '=' expr                                     { $$ = Expr\Assign[$1, $3]; }
828
    | variable '=' ampersand variable                       { $$ = Expr\AssignRef[$1, $4]; }
829
    | new_expr                                              { $$ = $1; }
830
    | match                                                 { $$ = $1; }
831
    | T_CLONE expr                                          { $$ = Expr\Clone_[$2]; }
832
    | variable T_PLUS_EQUAL expr                            { $$ = Expr\AssignOp\Plus      [$1, $3]; }
833
    | variable T_MINUS_EQUAL expr                           { $$ = Expr\AssignOp\Minus     [$1, $3]; }
834
    | variable T_MUL_EQUAL expr                             { $$ = Expr\AssignOp\Mul       [$1, $3]; }
835
    | variable T_DIV_EQUAL expr                             { $$ = Expr\AssignOp\Div       [$1, $3]; }
836
    | variable T_CONCAT_EQUAL expr                          { $$ = Expr\AssignOp\Concat    [$1, $3]; }
837
    | variable T_MOD_EQUAL expr                             { $$ = Expr\AssignOp\Mod       [$1, $3]; }
838
    | variable T_AND_EQUAL expr                             { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; }
839
    | variable T_OR_EQUAL expr                              { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; }
840
    | variable T_XOR_EQUAL expr                             { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; }
841
    | variable T_SL_EQUAL expr                              { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; }
842
    | variable T_SR_EQUAL expr                              { $$ = Expr\AssignOp\ShiftRight[$1, $3]; }
843
    | variable T_POW_EQUAL expr                             { $$ = Expr\AssignOp\Pow       [$1, $3]; }
844
    | variable T_COALESCE_EQUAL expr                        { $$ = Expr\AssignOp\Coalesce  [$1, $3]; }
845
    | variable T_INC                                        { $$ = Expr\PostInc[$1]; }
846
    | T_INC variable                                        { $$ = Expr\PreInc [$2]; }
847
    | variable T_DEC                                        { $$ = Expr\PostDec[$1]; }
848
    | T_DEC variable                                        { $$ = Expr\PreDec [$2]; }
849
    | expr T_BOOLEAN_OR expr                                { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; }
850
    | expr T_BOOLEAN_AND expr                               { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; }
851
    | expr T_LOGICAL_OR expr                                { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; }
852
    | expr T_LOGICAL_AND expr                               { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; }
853
    | expr T_LOGICAL_XOR expr                               { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; }
854
    | expr '|' expr                                         { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; }
855
    | expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr   { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
856
    | expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr       { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; }
857
    | expr '^' expr                                         { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; }
858
    | expr '.' expr                                         { $$ = Expr\BinaryOp\Concat    [$1, $3]; }
859
    | expr '+' expr                                         { $$ = Expr\BinaryOp\Plus      [$1, $3]; }
860
    | expr '-' expr                                         { $$ = Expr\BinaryOp\Minus     [$1, $3]; }
861
    | expr '*' expr                                         { $$ = Expr\BinaryOp\Mul       [$1, $3]; }
862
    | expr '/' expr                                         { $$ = Expr\BinaryOp\Div       [$1, $3]; }
863
    | expr '%' expr                                         { $$ = Expr\BinaryOp\Mod       [$1, $3]; }
864
    | expr T_SL expr                                        { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; }
865
    | expr T_SR expr                                        { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; }
866
    | expr T_POW expr                                       { $$ = Expr\BinaryOp\Pow       [$1, $3]; }
867
    | '+' expr %prec T_INC                                  { $$ = Expr\UnaryPlus [$2]; }
868
    | '-' expr %prec T_INC                                  { $$ = Expr\UnaryMinus[$2]; }
869
    | '!' expr                                              { $$ = Expr\BooleanNot[$2]; }
870
    | '~' expr                                              { $$ = Expr\BitwiseNot[$2]; }
871
    | expr T_IS_IDENTICAL expr                              { $$ = Expr\BinaryOp\Identical     [$1, $3]; }
872
    | expr T_IS_NOT_IDENTICAL expr                          { $$ = Expr\BinaryOp\NotIdentical  [$1, $3]; }
873
    | expr T_IS_EQUAL expr                                  { $$ = Expr\BinaryOp\Equal         [$1, $3]; }
874
    | expr T_IS_NOT_EQUAL expr                              { $$ = Expr\BinaryOp\NotEqual      [$1, $3]; }
875
    | expr T_SPACESHIP expr                                 { $$ = Expr\BinaryOp\Spaceship     [$1, $3]; }
876
    | expr '<' expr                                         { $$ = Expr\BinaryOp\Smaller       [$1, $3]; }
877
    | expr T_IS_SMALLER_OR_EQUAL expr                       { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; }
878
    | expr '>' expr                                         { $$ = Expr\BinaryOp\Greater       [$1, $3]; }
879
    | expr T_IS_GREATER_OR_EQUAL expr                       { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; }
880
    | expr T_INSTANCEOF class_name_reference                { $$ = Expr\Instanceof_[$1, $3]; }
881
    | '(' expr ')'                                          { $$ = $2; }
882
    | expr '?' expr ':' expr                                { $$ = Expr\Ternary[$1, $3,   $5]; }
883
    | expr '?' ':' expr                                     { $$ = Expr\Ternary[$1, null, $4]; }
884
    | expr T_COALESCE expr                                  { $$ = Expr\BinaryOp\Coalesce[$1, $3]; }
885
    | T_ISSET '(' expr_list_allow_comma ')'                 { $$ = Expr\Isset_[$3]; }
886
    | T_EMPTY '(' expr ')'                                  { $$ = Expr\Empty_[$3]; }
887
    | T_INCLUDE expr                                        { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; }
888
    | T_INCLUDE_ONCE expr                                   { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; }
889
    | T_EVAL '(' expr ')'                                   { $$ = Expr\Eval_[$3]; }
890
    | T_REQUIRE expr                                        { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; }
891
    | T_REQUIRE_ONCE expr                                   { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; }
892
    | T_INT_CAST expr                                       { $$ = Expr\Cast\Int_    [$2]; }
893
    | T_DOUBLE_CAST expr
894
          { $attrs = attributes();
895
            $attrs['kind'] = $this->getFloatCastKind($1);
896
            $$ = new Expr\Cast\Double($2, $attrs); }
897
    | T_STRING_CAST expr                                    { $$ = Expr\Cast\String_ [$2]; }
898
    | T_ARRAY_CAST expr                                     { $$ = Expr\Cast\Array_  [$2]; }
899
    | T_OBJECT_CAST expr                                    { $$ = Expr\Cast\Object_ [$2]; }
900
    | T_BOOL_CAST expr                                      { $$ = Expr\Cast\Bool_   [$2]; }
901
    | T_UNSET_CAST expr                                     { $$ = Expr\Cast\Unset_  [$2]; }
902
    | T_EXIT exit_expr
903
          { $attrs = attributes();
904
            $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
905
            $$ = new Expr\Exit_($2, $attrs); }
906
    | '@' expr                                              { $$ = Expr\ErrorSuppress[$2]; }
907
    | scalar                                                { $$ = $1; }
908
    | '`' backticks_expr '`'                                { $$ = Expr\ShellExec[$2]; }
909
    | T_PRINT expr                                          { $$ = Expr\Print_[$2]; }
910
    | T_YIELD                                               { $$ = Expr\Yield_[null, null]; }
911
    | T_YIELD expr                                          { $$ = Expr\Yield_[$2, null]; }
912
    | T_YIELD expr T_DOUBLE_ARROW expr                      { $$ = Expr\Yield_[$4, $2]; }
913
    | T_YIELD_FROM expr                                     { $$ = Expr\YieldFrom[$2]; }
914
    | T_THROW expr                                          { $$ = Expr\Throw_[$2]; }
915
 
916
    | T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW
917
          { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8, 'attrGroups' => []]]; }
918
    | T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW
919
          { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => []]]; }
920
    | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error
921
          { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; }
922
    | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type       block_or_error
923
          { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => []]]; }
924
 
925
    | attributes T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW
926
          { $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => $1]]; }
927
    | attributes T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW
928
          { $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $4, 'params' => $6, 'returnType' => $8, 'expr' => $10, 'attrGroups' => $1]]; }
929
    | attributes T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error
930
          { $$ = Expr\Closure[['static' => false, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; }
931
    | attributes T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type       block_or_error
932
          { $$ = Expr\Closure[['static' => true, 'byRef' => $4, 'params' => $6, 'uses' => $8, 'returnType' => $9, 'stmts' => $10, 'attrGroups' => $1]]; }
933
;
934
 
935
anonymous_class:
936
      optional_attributes T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}'
937
          { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]], $3);
938
            $this->checkClass($$[0], -1); }
939
;
940
 
941
new_expr:
942
      T_NEW class_name_reference ctor_arguments             { $$ = Expr\New_[$2, $3]; }
943
    | T_NEW anonymous_class
944
          { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; }
945
;
946
 
947
lexical_vars:
948
      /* empty */                                           { $$ = array(); }
949
    | T_USE '(' lexical_var_list ')'                        { $$ = $3; }
950
;
951
 
952
lexical_var_list:
953
      non_empty_lexical_var_list optional_comma             { $$ = $1; }
954
;
955
 
956
non_empty_lexical_var_list:
957
      lexical_var                                           { init($1); }
958
    | non_empty_lexical_var_list ',' lexical_var            { push($1, $3); }
959
;
960
 
961
lexical_var:
962
      optional_ref plain_variable                           { $$ = Expr\ClosureUse[$2, $1]; }
963
;
964
 
965
function_call:
966
      name argument_list                                    { $$ = Expr\FuncCall[$1, $2]; }
967
    | callable_expr argument_list                           { $$ = Expr\FuncCall[$1, $2]; }
968
    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
969
          { $$ = Expr\StaticCall[$1, $3, $4]; }
970
;
971
 
972
class_name:
973
      T_STATIC                                              { $$ = Name[$1]; }
974
    | name                                                  { $$ = $1; }
975
;
976
 
977
name:
978
      T_STRING                                              { $$ = Name[$1]; }
979
    | T_NAME_QUALIFIED                                      { $$ = Name[$1]; }
980
    | T_NAME_FULLY_QUALIFIED                                { $$ = Name\FullyQualified[substr($1, 1)]; }
981
    | T_NAME_RELATIVE                                       { $$ = Name\Relative[substr($1, 10)]; }
982
;
983
 
984
class_name_reference:
985
      class_name                                            { $$ = $1; }
986
    | new_variable                                          { $$ = $1; }
987
    | '(' expr ')'                                          { $$ = $2; }
988
    | error                                                 { $$ = Expr\Error[]; $this->errorState = 2; }
989
;
990
 
991
class_name_or_var:
992
      class_name                                            { $$ = $1; }
993
    | fully_dereferencable                                  { $$ = $1; }
994
;
995
 
996
exit_expr:
997
      /* empty */                                           { $$ = null; }
998
    | '(' optional_expr ')'                                 { $$ = $2; }
999
;
1000
 
1001
backticks_expr:
1002
      /* empty */                                           { $$ = array(); }
1003
    | T_ENCAPSED_AND_WHITESPACE
1004
          { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`')]); }
1005
    | encaps_list                                           { parseEncapsed($1, '`', true); $$ = $1; }
1006
;
1007
 
1008
ctor_arguments:
1009
      /* empty */                                           { $$ = array(); }
1010
    | argument_list                                         { $$ = $1; }
1011
;
1012
 
1013
constant:
1014
      name                                                  { $$ = Expr\ConstFetch[$1]; }
1015
    | T_LINE                                                { $$ = Scalar\MagicConst\Line[]; }
1016
    | T_FILE                                                { $$ = Scalar\MagicConst\File[]; }
1017
    | T_DIR                                                 { $$ = Scalar\MagicConst\Dir[]; }
1018
    | T_CLASS_C                                             { $$ = Scalar\MagicConst\Class_[]; }
1019
    | T_TRAIT_C                                             { $$ = Scalar\MagicConst\Trait_[]; }
1020
    | T_METHOD_C                                            { $$ = Scalar\MagicConst\Method[]; }
1021
    | T_FUNC_C                                              { $$ = Scalar\MagicConst\Function_[]; }
1022
    | T_NS_C                                                { $$ = Scalar\MagicConst\Namespace_[]; }
1023
;
1024
 
1025
class_constant:
1026
      class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved
1027
          { $$ = Expr\ClassConstFetch[$1, $3]; }
1028
    /* We interpret an isolated FOO:: as an unfinished class constant fetch. It could also be
1029
       an unfinished static property fetch or unfinished scoped call. */
1030
    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error
1031
          { $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; }
1032
;
1033
 
1034
array_short_syntax:
1035
      '[' array_pair_list ']'
1036
          { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT;
1037
            $$ = new Expr\Array_($2, $attrs); }
1038
;
1039
 
1040
dereferencable_scalar:
1041
      T_ARRAY '(' array_pair_list ')'
1042
          { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG;
1043
            $$ = new Expr\Array_($3, $attrs); }
1044
    | array_short_syntax                                    { $$ = $1; }
1045
    | T_CONSTANT_ENCAPSED_STRING                            { $$ = Scalar\String_::fromString($1, attributes()); }
1046
    | '"' encaps_list '"'
1047
          { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
1048
            parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); }
1049
;
1050
 
1051
scalar:
1052
      T_LNUMBER                                             { $$ = $this->parseLNumber($1, attributes()); }
1053
    | T_DNUMBER                                             { $$ = Scalar\DNumber::fromString($1, attributes()); }
1054
    | dereferencable_scalar                                 { $$ = $1; }
1055
    | constant                                              { $$ = $1; }
1056
    | class_constant                                        { $$ = $1; }
1057
    | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
1058
          { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); }
1059
    | T_START_HEREDOC T_END_HEREDOC
1060
          { $$ = $this->parseDocString($1, '', $2, attributes(), stackAttributes(#2), true); }
1061
    | T_START_HEREDOC encaps_list T_END_HEREDOC
1062
          { $$ = $this->parseDocString($1, $2, $3, attributes(), stackAttributes(#3), true); }
1063
;
1064
 
1065
optional_expr:
1066
      /* empty */                                           { $$ = null; }
1067
    | expr                                                  { $$ = $1; }
1068
;
1069
 
1070
fully_dereferencable:
1071
      variable                                              { $$ = $1; }
1072
    | '(' expr ')'                                          { $$ = $2; }
1073
    | dereferencable_scalar                                 { $$ = $1; }
1074
    | class_constant                                        { $$ = $1; }
1075
;
1076
 
1077
array_object_dereferencable:
1078
      fully_dereferencable                                  { $$ = $1; }
1079
    | constant                                              { $$ = $1; }
1080
;
1081
 
1082
callable_expr:
1083
      callable_variable                                     { $$ = $1; }
1084
    | '(' expr ')'                                          { $$ = $2; }
1085
    | dereferencable_scalar                                 { $$ = $1; }
1086
;
1087
 
1088
callable_variable:
1089
      simple_variable                                       { $$ = $1; }
1090
    | array_object_dereferencable '[' optional_expr ']'     { $$ = Expr\ArrayDimFetch[$1, $3]; }
1091
    | array_object_dereferencable '{' expr '}'              { $$ = Expr\ArrayDimFetch[$1, $3]; }
1092
    | function_call                                         { $$ = $1; }
1093
    | array_object_dereferencable T_OBJECT_OPERATOR property_name argument_list
1094
          { $$ = Expr\MethodCall[$1, $3, $4]; }
1095
    | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name argument_list
1096
          { $$ = Expr\NullsafeMethodCall[$1, $3, $4]; }
1097
;
1098
 
1099
optional_plain_variable:
1100
      /* empty */                                           { $$ = null; }
1101
    | plain_variable                                        { $$ = $1; }
1102
;
1103
 
1104
variable:
1105
      callable_variable                                     { $$ = $1; }
1106
    | static_member                                         { $$ = $1; }
1107
    | array_object_dereferencable T_OBJECT_OPERATOR property_name
1108
          { $$ = Expr\PropertyFetch[$1, $3]; }
1109
    | array_object_dereferencable T_NULLSAFE_OBJECT_OPERATOR property_name
1110
          { $$ = Expr\NullsafePropertyFetch[$1, $3]; }
1111
;
1112
 
1113
simple_variable:
1114
      plain_variable                                        { $$ = $1; }
1115
    | '$' '{' expr '}'                                      { $$ = Expr\Variable[$3]; }
1116
    | '$' simple_variable                                   { $$ = Expr\Variable[$2]; }
1117
    | '$' error                                             { $$ = Expr\Variable[Expr\Error[]]; $this->errorState = 2; }
1118
;
1119
 
1120
static_member_prop_name:
1121
      simple_variable
1122
          { $var = $1->name; $$ = \is_string($var) ? Node\VarLikeIdentifier[$var] : $var; }
1123
;
1124
 
1125
static_member:
1126
      class_name_or_var T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name
1127
          { $$ = Expr\StaticPropertyFetch[$1, $3]; }
1128
;
1129
 
1130
new_variable:
1131
      simple_variable                                       { $$ = $1; }
1132
    | new_variable '[' optional_expr ']'                    { $$ = Expr\ArrayDimFetch[$1, $3]; }
1133
    | new_variable '{' expr '}'                             { $$ = Expr\ArrayDimFetch[$1, $3]; }
1134
    | new_variable T_OBJECT_OPERATOR property_name          { $$ = Expr\PropertyFetch[$1, $3]; }
1135
    | new_variable T_NULLSAFE_OBJECT_OPERATOR property_name { $$ = Expr\NullsafePropertyFetch[$1, $3]; }
1136
    | class_name T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name
1137
          { $$ = Expr\StaticPropertyFetch[$1, $3]; }
1138
    | new_variable T_PAAMAYIM_NEKUDOTAYIM static_member_prop_name
1139
          { $$ = Expr\StaticPropertyFetch[$1, $3]; }
1140
;
1141
 
1142
member_name:
1143
      identifier_maybe_reserved                             { $$ = $1; }
1144
    | '{' expr '}'                                          { $$ = $2; }
1145
    | simple_variable                                       { $$ = $1; }
1146
;
1147
 
1148
property_name:
1149
      identifier_not_reserved                               { $$ = $1; }
1150
    | '{' expr '}'                                          { $$ = $2; }
1151
    | simple_variable                                       { $$ = $1; }
1152
    | error                                                 { $$ = Expr\Error[]; $this->errorState = 2; }
1153
;
1154
 
1155
list_expr:
1156
      T_LIST '(' inner_array_pair_list ')'                  { $$ = Expr\List_[$3]; }
1157
;
1158
 
1159
array_pair_list:
1160
      inner_array_pair_list
1161
          { $$ = $1; $end = count($$)-1; if ($$[$end] === null) array_pop($$); }
1162
;
1163
 
1164
comma_or_error:
1165
      ','
1166
    | error
1167
          { /* do nothing -- prevent default action of $$=$1. See #551. */ }
1168
;
1169
 
1170
inner_array_pair_list:
1171
      inner_array_pair_list comma_or_error array_pair       { push($1, $3); }
1172
    | array_pair                                            { init($1); }
1173
;
1174
 
1175
array_pair:
1176
      expr                                                  { $$ = Expr\ArrayItem[$1, null, false]; }
1177
    | ampersand variable                                    { $$ = Expr\ArrayItem[$2, null, true]; }
1178
    | list_expr                                             { $$ = Expr\ArrayItem[$1, null, false]; }
1179
    | expr T_DOUBLE_ARROW expr                              { $$ = Expr\ArrayItem[$3, $1,   false]; }
1180
    | expr T_DOUBLE_ARROW ampersand variable                { $$ = Expr\ArrayItem[$4, $1,   true]; }
1181
    | expr T_DOUBLE_ARROW list_expr                         { $$ = Expr\ArrayItem[$3, $1,   false]; }
1182
    | T_ELLIPSIS expr                                       { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
1183
    | /* empty */                                           { $$ = null; }
1184
;
1185
 
1186
encaps_list:
1187
      encaps_list encaps_var                                { push($1, $2); }
1188
    | encaps_list encaps_string_part                        { push($1, $2); }
1189
    | encaps_var                                            { init($1); }
1190
    | encaps_string_part encaps_var                         { init($1, $2); }
1191
;
1192
 
1193
encaps_string_part:
1194
      T_ENCAPSED_AND_WHITESPACE                             { $$ = Scalar\EncapsedStringPart[$1]; }
1195
;
1196
 
1197
encaps_str_varname:
1198
      T_STRING_VARNAME                                      { $$ = Expr\Variable[$1]; }
1199
;
1200
 
1201
encaps_var:
1202
      plain_variable                                        { $$ = $1; }
1203
    | plain_variable '[' encaps_var_offset ']'              { $$ = Expr\ArrayDimFetch[$1, $3]; }
1204
    | plain_variable T_OBJECT_OPERATOR identifier_not_reserved
1205
          { $$ = Expr\PropertyFetch[$1, $3]; }
1206
    | plain_variable T_NULLSAFE_OBJECT_OPERATOR identifier_not_reserved
1207
          { $$ = Expr\NullsafePropertyFetch[$1, $3]; }
1208
    | T_DOLLAR_OPEN_CURLY_BRACES expr '}'                   { $$ = Expr\Variable[$2]; }
1209
    | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}'       { $$ = Expr\Variable[$2]; }
1210
    | T_DOLLAR_OPEN_CURLY_BRACES encaps_str_varname '[' expr ']' '}'
1211
          { $$ = Expr\ArrayDimFetch[$2, $4]; }
1212
    | T_CURLY_OPEN variable '}'                             { $$ = $2; }
1213
;
1214
 
1215
encaps_var_offset:
1216
      T_STRING                                              { $$ = Scalar\String_[$1]; }
1217
    | T_NUM_STRING                                          { $$ = $this->parseNumString($1, attributes()); }
1218
    | '-' T_NUM_STRING                                      { $$ = $this->parseNumString('-' . $2, attributes()); }
1219
    | plain_variable                                        { $$ = $1; }
1220
;
1221
 
1222
%%