Skip to content

Commit

Permalink
Fix precedence of arrow functions
Browse files Browse the repository at this point in the history
Arrow functions should have lowest precedence.

Fixes #769.
  • Loading branch information
nikic committed Apr 25, 2021
1 parent ce91d13 commit e03d63c
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 21 deletions.
8 changes: 4 additions & 4 deletions grammar/php7.y
Original file line number Diff line number Diff line change
Expand Up @@ -843,18 +843,18 @@ expr:
| T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; }
| T_THROW expr { $$ = Expr\Throw_[$2]; }

| T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
| T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW
{ $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8, 'attrGroups' => []]]; }
| T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
| T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW
{ $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => []]]; }
| T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error
{ $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8, 'attrGroups' => []]]; }
| T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error
{ $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => []]]; }

| attributes T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
| attributes T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW
{ $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9, 'attrGroups' => $1]]; }
| attributes T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
| attributes T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr %prec T_THROW
{ $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $4, 'params' => $6, 'returnType' => $8, 'expr' => $10, 'attrGroups' => $1]]; }
| attributes T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type block_or_error
{ $$ = Expr\Closure[['static' => false, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9, 'attrGroups' => $1]]; }
Expand Down
2 changes: 1 addition & 1 deletion grammar/tokens.y
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,4 @@
%token T_NAME_QUALIFIED
%token T_NAME_RELATIVE
%token T_ATTRIBUTE
%token T_ENUM
%token T_ENUM
32 changes: 16 additions & 16 deletions lib/PhpParser/Parser/Php7.php
Original file line number Diff line number Diff line change
Expand Up @@ -504,8 +504,8 @@ class Php7 extends \PhpParser\ParserAbstract
1002, 1007, 916, 917, 757, 918, 919, 920, 921, 1003,
846, 998, 1004, 287, 287, 287, 287, 287, 287, 287,
287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
287, 287, 287, 287, 287, 636, 38, 135, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
287, 287, 287, 287, 287, 287, 287, 287, 287, 636,
38, 135, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 157, 157, 157, 204, 828, 828, 8, 602,
162, 948, 948, 948, 948, 948, 948, 948, 948, 948,
Expand Down Expand Up @@ -574,7 +574,7 @@ class Php7 extends \PhpParser\ParserAbstract
287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
287, 287, 287, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 287, 287, 287, 287, 287,
0, 0, 0, 0, 0, 0, 0, 0, 0, 287,
287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
287, 287, 287, 287, 287, 287, 695, 695, 287, 0,
Expand Down Expand Up @@ -618,10 +618,10 @@ class Php7 extends \PhpParser\ParserAbstract
32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
32767,32767,32767, 441, 420, 421, 423, 424, 355, 506,
560, 298, 557, 354, 143, 310, 300, 229, 301, 245,
246, 206, 272, 351, 147, 385, 438, 387, 436, 440,
386, 361, 366, 367, 368, 369, 370, 371, 372, 373,
374, 375, 376, 377, 378, 359, 360, 439, 442, 443,
446, 447, 417, 416, 415, 383,32767,32767, 384, 358,
442, 246, 443, 446, 447, 206, 272, 351, 147, 385,
438, 387, 436, 440, 386, 361, 366, 367, 368, 369,
370, 371, 372, 373, 374, 375, 376, 377, 378, 359,
360, 439, 417, 416, 415, 383,32767,32767, 384, 358,
388,32767,32767,32767,32767,32767,32767,32767,32767, 100,
32767, 390, 389, 406, 407, 404, 405, 408,32767, 409,
410, 411, 412,32767,32767,32767,32767, 336, 334, 397,
Expand Down Expand Up @@ -674,19 +674,19 @@ class Php7 extends \PhpParser\ParserAbstract
191, 191, 661, 403, 634, 453, 1237, 1238, 397, 300,
301, 321, 555, 306, 402, 322, 404, 613, 1038, 1039,
669, 315, 315, 315, 315, 162, 162, 162, 162, 188,
188, 172, 174, 211, 192, 206, 188, 188, 188, 188,
188, 172, 174, 215, 192, 210, 188, 188, 188, 188,
188, 189, 189, 189, 189, 189, 189, 183, 184, 185,
186, 187, 208, 206, 209, 513, 514, 393, 515, 517,
186, 187, 212, 210, 213, 513, 514, 393, 515, 517,
518, 519, 520, 521, 522, 523, 524, 1065, 163, 164,
165, 190, 166, 167, 168, 161, 169, 170, 171, 173,
205, 207, 210, 232, 235, 238, 240, 251, 252, 253,
209, 211, 214, 232, 235, 238, 240, 251, 252, 253,
254, 255, 256, 257, 259, 260, 261, 262, 269, 270,
303, 304, 305, 398, 399, 400, 560, 212, 213, 214,
215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
225, 226, 175, 227, 176, 193, 194, 195, 233, 183,
184, 185, 186, 187, 208, 1065, 196, 177, 178, 179,
197, 193, 180, 234, 198, 160, 199, 228, 181, 200,
229, 230, 182, 231, 201, 202, 203, 204, 814, 586,
303, 304, 305, 398, 399, 400, 560, 216, 217, 218,
219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
229, 230, 175, 231, 176, 193, 194, 195, 233, 183,
184, 185, 186, 187, 212, 1065, 196, 177, 178, 179,
197, 193, 180, 234, 198, 160, 199, 200, 181, 201,
202, 203, 182, 204, 205, 206, 207, 208, 814, 586,
600, 603, 604, 605, 606, 625, 626, 627, 671, 811,
599, 599, 539, 530, 577, 1194, 1194, 1194, 1194, 1194,
1194, 1194, 1194, 1194, 1194, 280, 280, 280, 280, 997,
Expand Down
89 changes: 89 additions & 0 deletions test/code/parser/expr/arrow_function.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ static fn(&$x) => $x;
fn&($x) => $x;
fn($x, ...$rest) => $rest;
fn(): int => $x;

fn($a, $b) => $a and $b;
fn($a, $b) => $a && $b;
-----
!!php7
array(
Expand Down Expand Up @@ -172,4 +175,90 @@ array(
)
)
)
6: Stmt_Expression(
expr: Expr_ArrowFunction(
attrGroups: array(
)
static: false
byRef: false
params: array(
0: Param(
attrGroups: array(
)
flags: 0
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: a
)
default: null
)
1: Param(
attrGroups: array(
)
flags: 0
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: b
)
default: null
)
)
returnType: null
expr: Expr_BinaryOp_LogicalAnd(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
)
)
7: Stmt_Expression(
expr: Expr_ArrowFunction(
attrGroups: array(
)
static: false
byRef: false
params: array(
0: Param(
attrGroups: array(
)
flags: 0
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: a
)
default: null
)
1: Param(
attrGroups: array(
)
flags: 0
type: null
byRef: false
variadic: false
var: Expr_Variable(
name: b
)
default: null
)
)
returnType: null
expr: Expr_BinaryOp_BooleanAnd(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
)
)
)
4 changes: 4 additions & 0 deletions test/code/prettyPrinter/expr/arrow_function.test
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ fn(&$x) => $x;
fn&($x) => $x;
static fn($x, ...$rest) => $rest;
fn(): int => $x;
fn($a, $b) => $a and $b;
fn($a, $b) => $a && $b;
-----
!!php7
fn($a) => $a;
Expand All @@ -16,3 +18,5 @@ fn(&$x) => $x;
fn&($x) => $x;
static fn($x, ...$rest) => $rest;
fn(): int => $x;
fn($a, $b) => $a and $b;
fn($a, $b) => $a && $b;

0 comments on commit e03d63c

Please sign in to comment.