@@ -291,18 +291,23 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
291291%type <ast> function_name non_empty_member_modifiers
292292%type <ast> property_hook property_hook_list optional_property_hook_list hooked_property property_hook_body
293293%type <ast> optional_parameter_list
294- %type <ast> generic_type_parameter_list
295- %type <ast> generic_type_parameters
294+ %type <ast> nested_generic_type_parameter_list
295+ %type <ast> nested_generic_type_parameters
296296%type <ast> generic_type
297297%type <ast> non_empty_generic_type_parameters
298+ %type <ast> generic_type_with_constraint
299+ %type <ast> generic_type_parameter_list_with_constraints
300+ %type <ast> class_or_fuction_decl_generic_type_parameters
301+ %type <ast> simple_generic_type
302+ %type <ast> simple_generic_type_parameter_list
303+ %type <ast> non_empty_simple_generic_type_parameters
298304
299305%type <num> returns_ref function fn is_reference is_variadic property_modifiers property_hook_modifiers
300306%type <num> method_modifiers class_const_modifiers member_modifier optional_cpp_modifiers
301307%type <num> class_modifiers class_modifier anonymous_class_modifiers anonymous_class_modifiers_optional use_type backup_fn_flags
302308
303309%type <ptr> backup_lex_pos
304310%type <str> backup_doc_comment
305- %type <str> generic_param_name
306311
307312%type <ident> reserved_non_modifiers semi_reserved
308313
@@ -607,25 +612,60 @@ is_variadic:
607612
608613class_declaration_statement :
609614 class_modifiers T_CLASS { $<num>$ = CG(zend_lineno); }
610- T_STRING generic_type_parameters extends_from implements_list backup_doc_comment ' {' class_statement_list ' }'
615+ T_STRING class_or_fuction_decl_generic_type_parameters extends_from implements_list backup_doc_comment ' {' class_statement_list ' }'
611616 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1 , $<num>3 , $8 , zend_ast_get_str($4 ), $6 , $7 , $10 , $5 , NULL ); }
612617 | T_CLASS { $<num>$ = CG(zend_lineno); }
613- T_STRING generic_type_parameters extends_from implements_list backup_doc_comment ' {' class_statement_list ' }'
618+ T_STRING class_or_fuction_decl_generic_type_parameters extends_from implements_list backup_doc_comment ' {' class_statement_list ' }'
614619 { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0 , $<num>2 , $7 , zend_ast_get_str($3 ), $5 , $6 , $9 , $4 , NULL ); }
615620;
616621
617- generic_type_parameters :
618- T_GENERIC_START generic_type_parameter_list possible_comma T_GENERIC_END { $$ = $2 ; }
622+ // only support e.g. "<T, S, A>"
623+ non_empty_simple_generic_type_parameters :
624+ T_GENERIC_START simple_generic_type_parameter_list T_GENERIC_END { $$ = $2 ; }
625+ ;
626+
627+ // only support e.g. "SomeType<T, S, A>"
628+ simple_generic_type :
629+ T_STRING { $$ = zend_ast_create_zval_from_str(zend_ast_get_str($1 )); }
630+ | T_STRING non_empty_simple_generic_type_parameters { $$ = zend_ast_create(ZEND_AST_GENERIC_TYPE, zend_ast_create_zval_from_str(zend_ast_get_str($1 )), $2 ); }
631+ ;
632+
633+ // only support e.g. "T, S, A"
634+ simple_generic_type_parameter_list :
635+ T_STRING { $$ = zend_ast_create_list(1 , ZEND_AST_GENERIC_TYPE_PARAM_LIST, $1 ); }
636+ | generic_type_parameter_list_with_constraints ' ,' T_STRING { $$ = zend_ast_list_add($1 , $3 ); }
637+ ;
638+
639+ // supports bounded types, e.g. "<T : SomeInterface, S : SomeClass>"
640+ class_or_fuction_decl_generic_type_parameters :
641+ T_GENERIC_START generic_type_parameter_list_with_constraints T_GENERIC_END { $$ = $2 ; }
619642 | %empty { $$ = NULL ; }
620643;
621644
622- generic_type_parameter_list :
645+ // supports bounded types, e.g. "T : SomeInterface, S : SomeClass"
646+ generic_type_parameter_list_with_constraints :
647+ generic_type_with_constraint { $$ = zend_ast_create_list(1 , ZEND_AST_GENERIC_TYPE_PARAM_LIST, $1 ); }
648+ | generic_type_parameter_list_with_constraints ' ,' generic_type_with_constraint { $$ = zend_ast_list_add($1 , $3 ); }
649+ ;
650+
651+ // supports bounded types, e.g. "T : SomeInterface"
652+ generic_type_with_constraint :
653+ T_STRING { $$ = zend_ast_create_zval_from_str(zend_ast_get_str($1 )); }
654+ | T_STRING ' :' simple_generic_type { $$ = zend_ast_create(ZEND_AST_GENERIC_TYPE, zend_ast_create_zval_from_str(zend_ast_get_str($1 )), $3 ); }
655+ ;
656+
657+ nested_generic_type_parameters :
658+ T_GENERIC_START nested_generic_type_parameter_list T_GENERIC_END { $$ = $2 ; }
659+ | %empty { $$ = NULL ; }
660+ ;
661+
662+ nested_generic_type_parameter_list :
623663 generic_type { $$ = zend_ast_create_list(1 , ZEND_AST_GENERIC_TYPE_PARAM_LIST, $1 ); }
624- | generic_type_parameter_list ' ,' generic_type { $$ = zend_ast_list_add($1 , $3 ); }
664+ | nested_generic_type_parameter_list ' ,' generic_type { $$ = zend_ast_list_add($1 , $3 ); }
625665;
626666
627667non_empty_generic_type_parameters :
628- T_GENERIC_START generic_type_parameter_list possible_comma T_GENERIC_END { $$ = $2 ; }
668+ T_GENERIC_START nested_generic_type_parameter_list T_GENERIC_END { $$ = $2 ; }
629669;
630670
631671generic_type :
@@ -896,9 +936,9 @@ type_expr_without_static:
896936
897937//TODO add generic type params to AST
898938type_without_static :
899- T_ARRAY generic_type_parameters { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); }
939+ T_ARRAY nested_generic_type_parameters { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); }
900940 | T_CALLABLE { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_CALLABLE); }
901- | name generic_type_parameters { $$ = $1 ; }
941+ | name nested_generic_type_parameters { $$ = $1 ; }
902942;
903943
904944union_type_without_static_element :
@@ -1390,10 +1430,6 @@ backup_doc_comment:
13901430 %empty { $$ = CG(doc_comment); CG(doc_comment) = NULL ; }
13911431;
13921432
1393- generic_param_name :
1394- %empty { $$ = CG(doc_comment); CG(doc_comment) = NULL ; }
1395- ;
1396-
13971433backup_fn_flags :
13981434 %prec PREC_ARROW_FUNCTION %empty { $$ = CG(extra_fn_flags); CG(extra_fn_flags) = 0 ; }
13991435;
0 commit comments