Skip to content

Commit da5f184

Browse files
iluuu1994Girgias
authored andcommitted
Gross intersection type in parameter types syntax ambiguity workaround
1 parent da18f55 commit da5f184

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

Zend/zend_language_parser.y

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
6868
%left T_BOOLEAN_AND
6969
%left '|'
7070
%left '^'
71-
%left '&'
71+
%left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
7272
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP
7373
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
7474
%left '.'
@@ -231,6 +231,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
231231
%token T_COALESCE "'??'"
232232
%token T_POW "'**'"
233233
%token T_POW_EQUAL "'**='"
234+
%token T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG "'&'"
235+
%token T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG "'&''"
234236
%token T_BAD_CHARACTER "invalid character"
235237

236238
/* Token used to force a parse error from the lexer */
@@ -264,7 +266,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
264266
%type <ast> lexical_var_list encaps_list
265267
%type <ast> array_pair non_empty_array_pair_list array_pair_list possible_array_pair
266268
%type <ast> isset_variable type return_type type_expr type_without_static
267-
%type <ast> identifier type_expr_without_static union_type_without_static
269+
%type <ast> identifier type_expr_without_static union_type_without_static intersection_type_without_static
268270
%type <ast> inline_function union_type intersection_type
269271
%type <ast> attributed_statement attributed_class_statement attributed_parameter
270272
%type <ast> attribute_decl attribute attributes attribute_group namespace_declaration_name
@@ -301,6 +303,11 @@ semi_reserved:
301303
| T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC
302304
;
303305

306+
ampersand:
307+
T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
308+
| T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG
309+
;
310+
304311
identifier:
305312
T_STRING { $$ = $1; }
306313
| semi_reserved {
@@ -555,7 +562,7 @@ function_declaration_statement:
555562

556563
is_reference:
557564
%empty { $$ = 0; }
558-
| '&' { $$ = ZEND_PARAM_REF; }
565+
| T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG { $$ = ZEND_PARAM_REF; }
559566
;
560567

561568
is_variadic:
@@ -633,7 +640,7 @@ implements_list:
633640

634641
foreach_variable:
635642
variable { $$ = $1; }
636-
| '&' variable { $$ = zend_ast_create(ZEND_AST_REF, $2); }
643+
| ampersand variable { $$ = zend_ast_create(ZEND_AST_REF, $2); }
637644
| T_LIST '(' array_pair_list ')' { $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_LIST; }
638645
| '[' array_pair_list ']' { $$ = $2; $$->attr = ZEND_ARRAY_SYNTAX_SHORT; }
639646
;
@@ -799,8 +806,8 @@ union_type:
799806
;
800807

801808
intersection_type:
802-
type '&' type { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_INTERSECTION, $1, $3); }
803-
| intersection_type '&' type { $$ = zend_ast_list_add($1, $3); }
809+
type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_INTERSECTION, $1, $3); }
810+
| intersection_type T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type { $$ = zend_ast_list_add($1, $3); }
804811
;
805812

806813
/* Duplicate the type rules without "static",
@@ -810,6 +817,7 @@ type_expr_without_static:
810817
type_without_static { $$ = $1; }
811818
| '?' type_without_static { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; }
812819
| union_type_without_static { $$ = $1; }
820+
| intersection_type_without_static { $$ = $1; }
813821
;
814822

815823
type_without_static:
@@ -825,7 +833,12 @@ union_type_without_static:
825833
{ $$ = zend_ast_list_add($1, $3); }
826834
;
827835

828-
// TODO Check if need to do intersection without static (seems weird)
836+
intersection_type_without_static:
837+
type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static
838+
{ $$ = zend_ast_create_list(2, ZEND_AST_TYPE_INTERSECTION, $1, $3); }
839+
| intersection_type_without_static T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG type_without_static
840+
{ $$ = zend_ast_list_add($1, $3); }
841+
;
829842

830843
return_type:
831844
%empty { $$ = NULL; }
@@ -1055,7 +1068,7 @@ expr:
10551068
{ $2->attr = ZEND_ARRAY_SYNTAX_SHORT; $$ = zend_ast_create(ZEND_AST_ASSIGN, $2, $5); }
10561069
| variable '=' expr
10571070
{ $$ = zend_ast_create(ZEND_AST_ASSIGN, $1, $3); }
1058-
| variable '=' '&' variable
1071+
| variable '=' ampersand variable
10591072
{ $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); }
10601073
| T_CLONE expr { $$ = zend_ast_create(ZEND_AST_CLONE, $2); }
10611074
| variable T_PLUS_EQUAL expr
@@ -1099,7 +1112,8 @@ expr:
10991112
| expr T_LOGICAL_XOR expr
11001113
{ $$ = zend_ast_create_binary_op(ZEND_BOOL_XOR, $1, $3); }
11011114
| expr '|' expr { $$ = zend_ast_create_binary_op(ZEND_BW_OR, $1, $3); }
1102-
| expr '&' expr { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); }
1115+
| expr T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); }
1116+
| expr T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG expr { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); }
11031117
| expr '^' expr { $$ = zend_ast_create_binary_op(ZEND_BW_XOR, $1, $3); }
11041118
| expr '.' expr { $$ = zend_ast_create_binary_op(ZEND_CONCAT, $1, $3); }
11051119
| expr '+' expr { $$ = zend_ast_create_binary_op(ZEND_ADD, $1, $3); }
@@ -1209,7 +1223,7 @@ backup_lex_pos:
12091223

12101224
returns_ref:
12111225
%empty { $$ = 0; }
1212-
| '&' { $$ = ZEND_ACC_RETURN_REFERENCE; }
1226+
| ampersand { $$ = ZEND_ACC_RETURN_REFERENCE; }
12131227
;
12141228

12151229
lexical_vars:
@@ -1224,7 +1238,7 @@ lexical_var_list:
12241238

12251239
lexical_var:
12261240
T_VARIABLE { $$ = $1; }
1227-
| '&' T_VARIABLE { $$ = $2; $$->attr = ZEND_BIND_REF; }
1241+
| ampersand T_VARIABLE { $$ = $2; $$->attr = ZEND_BIND_REF; }
12281242
;
12291243

12301244
function_call:
@@ -1424,9 +1438,9 @@ array_pair:
14241438
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); }
14251439
| expr
14261440
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $1, NULL); }
1427-
| expr T_DOUBLE_ARROW '&' variable
1441+
| expr T_DOUBLE_ARROW ampersand variable
14281442
{ $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $4, $1); }
1429-
| '&' variable
1443+
| ampersand variable
14301444
{ $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $2, NULL); }
14311445
| T_ELLIPSIS expr
14321446
{ $$ = zend_ast_create(ZEND_AST_UNPACK, $2); }

Zend/zend_language_scanner.l

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,15 @@ NEWLINE ("\r"|"\n"|"\r\n")
18571857
RETURN_TOKEN(T_SR);
18581858
}
18591859

1860+
<ST_IN_SCRIPTING>"&"{TABS_AND_SPACES}("$"|"...") {
1861+
yyless(1);
1862+
RETURN_TOKEN(T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG);
1863+
}
1864+
1865+
<ST_IN_SCRIPTING>"&" {
1866+
RETURN_TOKEN(T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG);
1867+
}
1868+
18601869
<ST_IN_SCRIPTING>"]"|")" {
18611870
/* Check that ] and ) match up properly with a preceding [ or ( */
18621871
RETURN_EXIT_NESTING_TOKEN(yytext[0]);

ext/tokenizer/tokenizer_data.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
5353
REGISTER_LONG_CONSTANT("T_COALESCE", T_COALESCE, CONST_CS | CONST_PERSISTENT);
5454
REGISTER_LONG_CONSTANT("T_BOOLEAN_OR", T_BOOLEAN_OR, CONST_CS | CONST_PERSISTENT);
5555
REGISTER_LONG_CONSTANT("T_BOOLEAN_AND", T_BOOLEAN_AND, CONST_CS | CONST_PERSISTENT);
56+
REGISTER_LONG_CONSTANT("T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG", T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, CONST_CS | CONST_PERSISTENT);
57+
REGISTER_LONG_CONSTANT("T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG", T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG, CONST_CS | CONST_PERSISTENT);
5658
REGISTER_LONG_CONSTANT("T_IS_EQUAL", T_IS_EQUAL, CONST_CS | CONST_PERSISTENT);
5759
REGISTER_LONG_CONSTANT("T_IS_NOT_EQUAL", T_IS_NOT_EQUAL, CONST_CS | CONST_PERSISTENT);
5860
REGISTER_LONG_CONSTANT("T_IS_IDENTICAL", T_IS_IDENTICAL, CONST_CS | CONST_PERSISTENT);
@@ -203,6 +205,8 @@ char *get_token_type_name(int token_type)
203205
case T_COALESCE: return "T_COALESCE";
204206
case T_BOOLEAN_OR: return "T_BOOLEAN_OR";
205207
case T_BOOLEAN_AND: return "T_BOOLEAN_AND";
208+
case T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG: return "T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG";
209+
case T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG: return "T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG";
206210
case T_IS_EQUAL: return "T_IS_EQUAL";
207211
case T_IS_NOT_EQUAL: return "T_IS_NOT_EQUAL";
208212
case T_IS_IDENTICAL: return "T_IS_IDENTICAL";

0 commit comments

Comments
 (0)