You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1289 lines
57 KiB

27 years ago
13 years ago
27 years ago
24 years ago
24 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
27 years ago
27 years ago
27 years ago
27 years ago
23 years ago
27 years ago
18 years ago
27 years ago
18 years ago
18 years ago
27 years ago
18 years ago
18 years ago
24 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
24 years ago
24 years ago
24 years ago
24 years ago
Implemented Traits for PHP as proposed in the RFC [TRAITS] # RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior # Ok, here we go, I guess that will result in more discussion, which is fine # by me. But now, the patch is here, and properly archived. # # See below a list of notes to the patch, it also includes a list of # points which should be fixed # # Internals of the Traits Patch # ----------------------------- # # Open TODOs # """""""""" # # - Reflection API # - support for traits for internal classes # - currently destroy_zend_class does not handle that case # # Introduced Structures # """"""""""""""""""""" # # Data structures to encode the composition information specified in the # source: # - zend_trait_method_reference # - zend_trait_precedence # - zend_trait_alias # # Changes # """"""" # # zend_class_entry # - uses NULL terminated lists of pointers for # - trait_aliases # - trait_precedences # - do you prefer an explicit counter? # - the information is only necessary during class composition # but might be interesting for reflection # - did not want to blow up class further with not really necessary length counters # # added keywords # - trait # - insteadof # # Added opcodes # ZEND_ADD_TRAIT # - similar to ZEND_ADD_INTERFACE # - adds the trait to the list of traits of a class, no actual composition done # ZEND_BIND_TRAITS # - emitted in zend_do_end_class_declaration # - concludes the class definition and will initiate the trait composition # when the class definition is encountered during runtime # # Added Flags # ZEND_ACC_TRAIT = 0x120 # ZEND_ACC_IMPLEMENT_TRAITS = 0x400000 # ZEND_FETCH_CLASS_TRAIT = 14 # # zend_vm_execute.h # - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER, # ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective # # zend_compile.c # - refactored do_inherit_method_check # split into do_inherit_method_check and do_inheritance_check_on_method # - added helper functions use a '_' as prefix and are not mentioned in the # headers # - _copy_functions # prepare hash-maps of functions which should be merged into a class # here the aliases are handled # - _merge_functions # builds a hash-table of the methods which need to be added to a class # does the conflict detection # - reused php_runkit_function_copy_ctor # - it is not identical with the original code anymore, needed to update it # think I fixed some bugs, not sure whether all have been reported back to runkit # - has to be renamed, left the name for the moment, to make its origin obvious # - here might be optimization potential # - not sure whether everything needs to be copied # - copying the literals might be broken # - added it since the literals array is freed by efree and gave problems # with doubled frees # - all immutable parts of the zend_op array should not be copied # - am not sure which parts are immutable # - and not sure how to avoid doubled frees on the same arrays on shutdown # - _merge_functions_to_class # does the final merging with the target class to handle inherited # and overridden methods # - small helper for NULL terminated lists # zend_init_list, zend_add_to_list # # zend_language_parser.y # - reused class definition for traits # - there should be something with regard to properties # - if they get explicitly defined, it might be worthwhile to # check that there are no collisions with other traits in a composition # (however, I would not introduce elaborate language features to control that # but a notice for such conflicts might be nice to the developers)
16 years ago
18 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
24 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
24 years ago
Implemented Traits for PHP as proposed in the RFC [TRAITS] # RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior # Ok, here we go, I guess that will result in more discussion, which is fine # by me. But now, the patch is here, and properly archived. # # See below a list of notes to the patch, it also includes a list of # points which should be fixed # # Internals of the Traits Patch # ----------------------------- # # Open TODOs # """""""""" # # - Reflection API # - support for traits for internal classes # - currently destroy_zend_class does not handle that case # # Introduced Structures # """"""""""""""""""""" # # Data structures to encode the composition information specified in the # source: # - zend_trait_method_reference # - zend_trait_precedence # - zend_trait_alias # # Changes # """"""" # # zend_class_entry # - uses NULL terminated lists of pointers for # - trait_aliases # - trait_precedences # - do you prefer an explicit counter? # - the information is only necessary during class composition # but might be interesting for reflection # - did not want to blow up class further with not really necessary length counters # # added keywords # - trait # - insteadof # # Added opcodes # ZEND_ADD_TRAIT # - similar to ZEND_ADD_INTERFACE # - adds the trait to the list of traits of a class, no actual composition done # ZEND_BIND_TRAITS # - emitted in zend_do_end_class_declaration # - concludes the class definition and will initiate the trait composition # when the class definition is encountered during runtime # # Added Flags # ZEND_ACC_TRAIT = 0x120 # ZEND_ACC_IMPLEMENT_TRAITS = 0x400000 # ZEND_FETCH_CLASS_TRAIT = 14 # # zend_vm_execute.h # - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER, # ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective # # zend_compile.c # - refactored do_inherit_method_check # split into do_inherit_method_check and do_inheritance_check_on_method # - added helper functions use a '_' as prefix and are not mentioned in the # headers # - _copy_functions # prepare hash-maps of functions which should be merged into a class # here the aliases are handled # - _merge_functions # builds a hash-table of the methods which need to be added to a class # does the conflict detection # - reused php_runkit_function_copy_ctor # - it is not identical with the original code anymore, needed to update it # think I fixed some bugs, not sure whether all have been reported back to runkit # - has to be renamed, left the name for the moment, to make its origin obvious # - here might be optimization potential # - not sure whether everything needs to be copied # - copying the literals might be broken # - added it since the literals array is freed by efree and gave problems # with doubled frees # - all immutable parts of the zend_op array should not be copied # - am not sure which parts are immutable # - and not sure how to avoid doubled frees on the same arrays on shutdown # - _merge_functions_to_class # does the final merging with the target class to handle inherited # and overridden methods # - small helper for NULL terminated lists # zend_init_list, zend_add_to_list # # zend_language_parser.y # - reused class definition for traits # - there should be something with regard to properties # - if they get explicitly defined, it might be worthwhile to # check that there are no collisions with other traits in a composition # (however, I would not introduce elaborate language features to control that # but a notice for such conflicts might be nice to the developers)
16 years ago
27 years ago
Implemented Traits for PHP as proposed in the RFC [TRAITS] # RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior # Ok, here we go, I guess that will result in more discussion, which is fine # by me. But now, the patch is here, and properly archived. # # See below a list of notes to the patch, it also includes a list of # points which should be fixed # # Internals of the Traits Patch # ----------------------------- # # Open TODOs # """""""""" # # - Reflection API # - support for traits for internal classes # - currently destroy_zend_class does not handle that case # # Introduced Structures # """"""""""""""""""""" # # Data structures to encode the composition information specified in the # source: # - zend_trait_method_reference # - zend_trait_precedence # - zend_trait_alias # # Changes # """"""" # # zend_class_entry # - uses NULL terminated lists of pointers for # - trait_aliases # - trait_precedences # - do you prefer an explicit counter? # - the information is only necessary during class composition # but might be interesting for reflection # - did not want to blow up class further with not really necessary length counters # # added keywords # - trait # - insteadof # # Added opcodes # ZEND_ADD_TRAIT # - similar to ZEND_ADD_INTERFACE # - adds the trait to the list of traits of a class, no actual composition done # ZEND_BIND_TRAITS # - emitted in zend_do_end_class_declaration # - concludes the class definition and will initiate the trait composition # when the class definition is encountered during runtime # # Added Flags # ZEND_ACC_TRAIT = 0x120 # ZEND_ACC_IMPLEMENT_TRAITS = 0x400000 # ZEND_FETCH_CLASS_TRAIT = 14 # # zend_vm_execute.h # - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER, # ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective # # zend_compile.c # - refactored do_inherit_method_check # split into do_inherit_method_check and do_inheritance_check_on_method # - added helper functions use a '_' as prefix and are not mentioned in the # headers # - _copy_functions # prepare hash-maps of functions which should be merged into a class # here the aliases are handled # - _merge_functions # builds a hash-table of the methods which need to be added to a class # does the conflict detection # - reused php_runkit_function_copy_ctor # - it is not identical with the original code anymore, needed to update it # think I fixed some bugs, not sure whether all have been reported back to runkit # - has to be renamed, left the name for the moment, to make its origin obvious # - here might be optimization potential # - not sure whether everything needs to be copied # - copying the literals might be broken # - added it since the literals array is freed by efree and gave problems # with doubled frees # - all immutable parts of the zend_op array should not be copied # - am not sure which parts are immutable # - and not sure how to avoid doubled frees on the same arrays on shutdown # - _merge_functions_to_class # does the final merging with the target class to handle inherited # and overridden methods # - small helper for NULL terminated lists # zend_init_list, zend_add_to_list # # zend_language_parser.y # - reused class definition for traits # - there should be something with regard to properties # - if they get explicitly defined, it might be worthwhile to # check that there are no collisions with other traits in a composition # (however, I would not introduce elaborate language features to control that # but a notice for such conflicts might be nice to the developers)
16 years ago
Implemented Traits for PHP as proposed in the RFC [TRAITS] # RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior # Ok, here we go, I guess that will result in more discussion, which is fine # by me. But now, the patch is here, and properly archived. # # See below a list of notes to the patch, it also includes a list of # points which should be fixed # # Internals of the Traits Patch # ----------------------------- # # Open TODOs # """""""""" # # - Reflection API # - support for traits for internal classes # - currently destroy_zend_class does not handle that case # # Introduced Structures # """"""""""""""""""""" # # Data structures to encode the composition information specified in the # source: # - zend_trait_method_reference # - zend_trait_precedence # - zend_trait_alias # # Changes # """"""" # # zend_class_entry # - uses NULL terminated lists of pointers for # - trait_aliases # - trait_precedences # - do you prefer an explicit counter? # - the information is only necessary during class composition # but might be interesting for reflection # - did not want to blow up class further with not really necessary length counters # # added keywords # - trait # - insteadof # # Added opcodes # ZEND_ADD_TRAIT # - similar to ZEND_ADD_INTERFACE # - adds the trait to the list of traits of a class, no actual composition done # ZEND_BIND_TRAITS # - emitted in zend_do_end_class_declaration # - concludes the class definition and will initiate the trait composition # when the class definition is encountered during runtime # # Added Flags # ZEND_ACC_TRAIT = 0x120 # ZEND_ACC_IMPLEMENT_TRAITS = 0x400000 # ZEND_FETCH_CLASS_TRAIT = 14 # # zend_vm_execute.h # - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER, # ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective # # zend_compile.c # - refactored do_inherit_method_check # split into do_inherit_method_check and do_inheritance_check_on_method # - added helper functions use a '_' as prefix and are not mentioned in the # headers # - _copy_functions # prepare hash-maps of functions which should be merged into a class # here the aliases are handled # - _merge_functions # builds a hash-table of the methods which need to be added to a class # does the conflict detection # - reused php_runkit_function_copy_ctor # - it is not identical with the original code anymore, needed to update it # think I fixed some bugs, not sure whether all have been reported back to runkit # - has to be renamed, left the name for the moment, to make its origin obvious # - here might be optimization potential # - not sure whether everything needs to be copied # - copying the literals might be broken # - added it since the literals array is freed by efree and gave problems # with doubled frees # - all immutable parts of the zend_op array should not be copied # - am not sure which parts are immutable # - and not sure how to avoid doubled frees on the same arrays on shutdown # - _merge_functions_to_class # does the final merging with the target class to handle inherited # and overridden methods # - small helper for NULL terminated lists # zend_init_list, zend_add_to_list # # zend_language_parser.y # - reused class definition for traits # - there should be something with regard to properties # - if they get explicitly defined, it might be worthwhile to # check that there are no collisions with other traits in a composition # (however, I would not introduce elaborate language features to control that # but a notice for such conflicts might be nice to the developers)
16 years ago
Implemented Traits for PHP as proposed in the RFC [TRAITS] # RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior # Ok, here we go, I guess that will result in more discussion, which is fine # by me. But now, the patch is here, and properly archived. # # See below a list of notes to the patch, it also includes a list of # points which should be fixed # # Internals of the Traits Patch # ----------------------------- # # Open TODOs # """""""""" # # - Reflection API # - support for traits for internal classes # - currently destroy_zend_class does not handle that case # # Introduced Structures # """"""""""""""""""""" # # Data structures to encode the composition information specified in the # source: # - zend_trait_method_reference # - zend_trait_precedence # - zend_trait_alias # # Changes # """"""" # # zend_class_entry # - uses NULL terminated lists of pointers for # - trait_aliases # - trait_precedences # - do you prefer an explicit counter? # - the information is only necessary during class composition # but might be interesting for reflection # - did not want to blow up class further with not really necessary length counters # # added keywords # - trait # - insteadof # # Added opcodes # ZEND_ADD_TRAIT # - similar to ZEND_ADD_INTERFACE # - adds the trait to the list of traits of a class, no actual composition done # ZEND_BIND_TRAITS # - emitted in zend_do_end_class_declaration # - concludes the class definition and will initiate the trait composition # when the class definition is encountered during runtime # # Added Flags # ZEND_ACC_TRAIT = 0x120 # ZEND_ACC_IMPLEMENT_TRAITS = 0x400000 # ZEND_FETCH_CLASS_TRAIT = 14 # # zend_vm_execute.h # - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER, # ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective # # zend_compile.c # - refactored do_inherit_method_check # split into do_inherit_method_check and do_inheritance_check_on_method # - added helper functions use a '_' as prefix and are not mentioned in the # headers # - _copy_functions # prepare hash-maps of functions which should be merged into a class # here the aliases are handled # - _merge_functions # builds a hash-table of the methods which need to be added to a class # does the conflict detection # - reused php_runkit_function_copy_ctor # - it is not identical with the original code anymore, needed to update it # think I fixed some bugs, not sure whether all have been reported back to runkit # - has to be renamed, left the name for the moment, to make its origin obvious # - here might be optimization potential # - not sure whether everything needs to be copied # - copying the literals might be broken # - added it since the literals array is freed by efree and gave problems # with doubled frees # - all immutable parts of the zend_op array should not be copied # - am not sure which parts are immutable # - and not sure how to avoid doubled frees on the same arrays on shutdown # - _merge_functions_to_class # does the final merging with the target class to handle inherited # and overridden methods # - small helper for NULL terminated lists # zend_init_list, zend_add_to_list # # zend_language_parser.y # - reused class definition for traits # - there should be something with regard to properties # - if they get explicitly defined, it might be worthwhile to # check that there are no collisions with other traits in a composition # (however, I would not introduce elaborate language features to control that # but a notice for such conflicts might be nice to the developers)
16 years ago
Implemented Traits for PHP as proposed in the RFC [TRAITS] # RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior # Ok, here we go, I guess that will result in more discussion, which is fine # by me. But now, the patch is here, and properly archived. # # See below a list of notes to the patch, it also includes a list of # points which should be fixed # # Internals of the Traits Patch # ----------------------------- # # Open TODOs # """""""""" # # - Reflection API # - support for traits for internal classes # - currently destroy_zend_class does not handle that case # # Introduced Structures # """"""""""""""""""""" # # Data structures to encode the composition information specified in the # source: # - zend_trait_method_reference # - zend_trait_precedence # - zend_trait_alias # # Changes # """"""" # # zend_class_entry # - uses NULL terminated lists of pointers for # - trait_aliases # - trait_precedences # - do you prefer an explicit counter? # - the information is only necessary during class composition # but might be interesting for reflection # - did not want to blow up class further with not really necessary length counters # # added keywords # - trait # - insteadof # # Added opcodes # ZEND_ADD_TRAIT # - similar to ZEND_ADD_INTERFACE # - adds the trait to the list of traits of a class, no actual composition done # ZEND_BIND_TRAITS # - emitted in zend_do_end_class_declaration # - concludes the class definition and will initiate the trait composition # when the class definition is encountered during runtime # # Added Flags # ZEND_ACC_TRAIT = 0x120 # ZEND_ACC_IMPLEMENT_TRAITS = 0x400000 # ZEND_FETCH_CLASS_TRAIT = 14 # # zend_vm_execute.h # - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER, # ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective # # zend_compile.c # - refactored do_inherit_method_check # split into do_inherit_method_check and do_inheritance_check_on_method # - added helper functions use a '_' as prefix and are not mentioned in the # headers # - _copy_functions # prepare hash-maps of functions which should be merged into a class # here the aliases are handled # - _merge_functions # builds a hash-table of the methods which need to be added to a class # does the conflict detection # - reused php_runkit_function_copy_ctor # - it is not identical with the original code anymore, needed to update it # think I fixed some bugs, not sure whether all have been reported back to runkit # - has to be renamed, left the name for the moment, to make its origin obvious # - here might be optimization potential # - not sure whether everything needs to be copied # - copying the literals might be broken # - added it since the literals array is freed by efree and gave problems # with doubled frees # - all immutable parts of the zend_op array should not be copied # - am not sure which parts are immutable # - and not sure how to avoid doubled frees on the same arrays on shutdown # - _merge_functions_to_class # does the final merging with the target class to handle inherited # and overridden methods # - small helper for NULL terminated lists # zend_init_list, zend_add_to_list # # zend_language_parser.y # - reused class definition for traits # - there should be something with regard to properties # - if they get explicitly defined, it might be worthwhile to # check that there are no collisions with other traits in a composition # (however, I would not introduce elaborate language features to control that # but a notice for such conflicts might be nice to the developers)
16 years ago
Implemented Traits for PHP as proposed in the RFC [TRAITS] # RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior # Ok, here we go, I guess that will result in more discussion, which is fine # by me. But now, the patch is here, and properly archived. # # See below a list of notes to the patch, it also includes a list of # points which should be fixed # # Internals of the Traits Patch # ----------------------------- # # Open TODOs # """""""""" # # - Reflection API # - support for traits for internal classes # - currently destroy_zend_class does not handle that case # # Introduced Structures # """"""""""""""""""""" # # Data structures to encode the composition information specified in the # source: # - zend_trait_method_reference # - zend_trait_precedence # - zend_trait_alias # # Changes # """"""" # # zend_class_entry # - uses NULL terminated lists of pointers for # - trait_aliases # - trait_precedences # - do you prefer an explicit counter? # - the information is only necessary during class composition # but might be interesting for reflection # - did not want to blow up class further with not really necessary length counters # # added keywords # - trait # - insteadof # # Added opcodes # ZEND_ADD_TRAIT # - similar to ZEND_ADD_INTERFACE # - adds the trait to the list of traits of a class, no actual composition done # ZEND_BIND_TRAITS # - emitted in zend_do_end_class_declaration # - concludes the class definition and will initiate the trait composition # when the class definition is encountered during runtime # # Added Flags # ZEND_ACC_TRAIT = 0x120 # ZEND_ACC_IMPLEMENT_TRAITS = 0x400000 # ZEND_FETCH_CLASS_TRAIT = 14 # # zend_vm_execute.h # - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER, # ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective # # zend_compile.c # - refactored do_inherit_method_check # split into do_inherit_method_check and do_inheritance_check_on_method # - added helper functions use a '_' as prefix and are not mentioned in the # headers # - _copy_functions # prepare hash-maps of functions which should be merged into a class # here the aliases are handled # - _merge_functions # builds a hash-table of the methods which need to be added to a class # does the conflict detection # - reused php_runkit_function_copy_ctor # - it is not identical with the original code anymore, needed to update it # think I fixed some bugs, not sure whether all have been reported back to runkit # - has to be renamed, left the name for the moment, to make its origin obvious # - here might be optimization potential # - not sure whether everything needs to be copied # - copying the literals might be broken # - added it since the literals array is freed by efree and gave problems # with doubled frees # - all immutable parts of the zend_op array should not be copied # - am not sure which parts are immutable # - and not sure how to avoid doubled frees on the same arrays on shutdown # - _merge_functions_to_class # does the final merging with the target class to handle inherited # and overridden methods # - small helper for NULL terminated lists # zend_init_list, zend_add_to_list # # zend_language_parser.y # - reused class definition for traits # - there should be something with regard to properties # - if they get explicitly defined, it might be worthwhile to # check that there are no collisions with other traits in a composition # (however, I would not introduce elaborate language features to control that # but a notice for such conflicts might be nice to the developers)
16 years ago
Implemented Traits for PHP as proposed in the RFC [TRAITS] # RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior # Ok, here we go, I guess that will result in more discussion, which is fine # by me. But now, the patch is here, and properly archived. # # See below a list of notes to the patch, it also includes a list of # points which should be fixed # # Internals of the Traits Patch # ----------------------------- # # Open TODOs # """""""""" # # - Reflection API # - support for traits for internal classes # - currently destroy_zend_class does not handle that case # # Introduced Structures # """"""""""""""""""""" # # Data structures to encode the composition information specified in the # source: # - zend_trait_method_reference # - zend_trait_precedence # - zend_trait_alias # # Changes # """"""" # # zend_class_entry # - uses NULL terminated lists of pointers for # - trait_aliases # - trait_precedences # - do you prefer an explicit counter? # - the information is only necessary during class composition # but might be interesting for reflection # - did not want to blow up class further with not really necessary length counters # # added keywords # - trait # - insteadof # # Added opcodes # ZEND_ADD_TRAIT # - similar to ZEND_ADD_INTERFACE # - adds the trait to the list of traits of a class, no actual composition done # ZEND_BIND_TRAITS # - emitted in zend_do_end_class_declaration # - concludes the class definition and will initiate the trait composition # when the class definition is encountered during runtime # # Added Flags # ZEND_ACC_TRAIT = 0x120 # ZEND_ACC_IMPLEMENT_TRAITS = 0x400000 # ZEND_FETCH_CLASS_TRAIT = 14 # # zend_vm_execute.h # - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER, # ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective # # zend_compile.c # - refactored do_inherit_method_check # split into do_inherit_method_check and do_inheritance_check_on_method # - added helper functions use a '_' as prefix and are not mentioned in the # headers # - _copy_functions # prepare hash-maps of functions which should be merged into a class # here the aliases are handled # - _merge_functions # builds a hash-table of the methods which need to be added to a class # does the conflict detection # - reused php_runkit_function_copy_ctor # - it is not identical with the original code anymore, needed to update it # think I fixed some bugs, not sure whether all have been reported back to runkit # - has to be renamed, left the name for the moment, to make its origin obvious # - here might be optimization potential # - not sure whether everything needs to be copied # - copying the literals might be broken # - added it since the literals array is freed by efree and gave problems # with doubled frees # - all immutable parts of the zend_op array should not be copied # - am not sure which parts are immutable # - and not sure how to avoid doubled frees on the same arrays on shutdown # - _merge_functions_to_class # does the final merging with the target class to handle inherited # and overridden methods # - small helper for NULL terminated lists # zend_init_list, zend_add_to_list # # zend_language_parser.y # - reused class definition for traits # - there should be something with regard to properties # - if they get explicitly defined, it might be worthwhile to # check that there are no collisions with other traits in a composition # (however, I would not introduce elaborate language features to control that # but a notice for such conflicts might be nice to the developers)
16 years ago
27 years ago
27 years ago
24 years ago
27 years ago
27 years ago
25 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
24 years ago
18 years ago
27 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
25 years ago
27 years ago
27 years ago
27 years ago
27 years ago
18 years ago
27 years ago
18 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
18 years ago
27 years ago
  1. %{
  2. /*
  3. +----------------------------------------------------------------------+
  4. | Zend Engine |
  5. +----------------------------------------------------------------------+
  6. | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 2.00 of the Zend license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.zend.com/license/2_00.txt. |
  12. | If you did not receive a copy of the Zend license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@zend.com so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. | Authors: Andi Gutmans <andi@zend.com> |
  17. | Zeev Suraski <zeev@zend.com> |
  18. +----------------------------------------------------------------------+
  19. */
  20. /* $Id$ */
  21. /*
  22. * LALR shift/reduce conflicts and how they are resolved:
  23. *
  24. * - 2 shift/reduce conflicts due to the dangling elseif/else ambiguity. Solved by shift.
  25. *
  26. */
  27. #include "zend_compile.h"
  28. #include "zend.h"
  29. #include "zend_list.h"
  30. #include "zend_globals.h"
  31. #include "zend_API.h"
  32. #include "zend_constants.h"
  33. #define YYSIZE_T size_t
  34. #define yytnamerr zend_yytnamerr
  35. static YYSIZE_T zend_yytnamerr(char*, const char*);
  36. #define YYERROR_VERBOSE
  37. #define YYSTYPE znode
  38. #ifdef ZTS
  39. # define YYPARSE_PARAM tsrm_ls
  40. # define YYLEX_PARAM tsrm_ls
  41. #endif
  42. %}
  43. %pure_parser
  44. %expect 3
  45. %token END 0 "end of file"
  46. %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
  47. %token T_INCLUDE "include (T_INCLUDE)"
  48. %token T_INCLUDE_ONCE "include_once (T_INCLUDE_ONCE)"
  49. %token T_EVAL "eval (T_EVAL)"
  50. %token T_REQUIRE "require (T_REQUIRE)"
  51. %token T_REQUIRE_ONCE "require_once (T_REQUIRE_ONCE)"
  52. %left ','
  53. %left T_LOGICAL_OR
  54. %token T_LOGICAL_OR "or (T_LOGICAL_OR)"
  55. %left T_LOGICAL_XOR
  56. %token T_LOGICAL_XOR "xor (T_LOGICAL_XOR)"
  57. %left T_LOGICAL_AND
  58. %token T_LOGICAL_AND "and (T_LOGICAL_AND)"
  59. %right T_PRINT
  60. %token T_PRINT "print (T_PRINT)"
  61. %right T_YIELD
  62. %token T_YIELD "yield (T_YIELD)"
  63. %left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL
  64. %token T_PLUS_EQUAL "+= (T_PLUS_EQUAL)"
  65. %token T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
  66. %token T_MUL_EQUAL "*= (T_MUL_EQUAL)"
  67. %token T_DIV_EQUAL "/= (T_DIV_EQUAL)"
  68. %token T_CONCAT_EQUAL ".= (T_CONCAT_EQUAL)"
  69. %token T_MOD_EQUAL "%= (T_MOD_EQUAL)"
  70. %token T_AND_EQUAL "&= (T_AND_EQUAL)"
  71. %token T_OR_EQUAL "|= (T_OR_EQUAL)"
  72. %token T_XOR_EQUAL "^= (T_XOR_EQUAL)"
  73. %token T_SL_EQUAL "<<= (T_SL_EQUAL)"
  74. %token T_SR_EQUAL ">>= (T_SR_EQUAL)"
  75. %left '?' ':'
  76. %left T_BOOLEAN_OR
  77. %token T_BOOLEAN_OR "|| (T_BOOLEAN_OR)"
  78. %left T_BOOLEAN_AND
  79. %token T_BOOLEAN_AND "&& (T_BOOLEAN_AND)"
  80. %left '|'
  81. %left '^'
  82. %left '&'
  83. %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL
  84. %token T_IS_EQUAL "== (T_IS_EQUAL)"
  85. %token T_IS_NOT_EQUAL "!= (T_IS_NOT_EQUAL)"
  86. %token T_IS_IDENTICAL "=== (T_IS_IDENTICAL)"
  87. %token T_IS_NOT_IDENTICAL "!== (T_IS_NOT_IDENTICAL)"
  88. %nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
  89. %token T_IS_SMALLER_OR_EQUAL "<= (T_IS_SMALLER_OR_EQUAL)"
  90. %token T_IS_GREATER_OR_EQUAL ">= (T_IS_GREATER_OR_EQUAL)"
  91. %left T_SL T_SR
  92. %token T_SL "<< (T_SL)"
  93. %token T_SR ">> (T_SR)"
  94. %left '+' '-' '.'
  95. %left '*' '/' '%'
  96. %right '!'
  97. %nonassoc T_INSTANCEOF
  98. %token T_INSTANCEOF "instanceof (T_INSTANCEOF)"
  99. %right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
  100. %token T_INC "++ (T_INC)"
  101. %token T_DEC "-- (T_DEC)"
  102. %token T_INT_CAST "(int) (T_INT_CAST)"
  103. %token T_DOUBLE_CAST "(double) (T_DOUBLE_CAST)"
  104. %token T_STRING_CAST "(string) (T_STRING_CAST)"
  105. %token T_ARRAY_CAST "(array) (T_ARRAY_CAST)"
  106. %token T_OBJECT_CAST "(object) (T_OBJECT_CAST)"
  107. %token T_BOOL_CAST "(bool) (T_BOOL_CAST)"
  108. %token T_UNSET_CAST "(unset) (T_UNSET_CAST)"
  109. %right '['
  110. %nonassoc T_NEW T_CLONE
  111. %token T_NEW "new (T_NEW)"
  112. %token T_CLONE "clone (T_CLONE)"
  113. %token T_EXIT "exit (T_EXIT)"
  114. %token T_IF "if (T_IF)"
  115. %left T_ELSEIF
  116. %token T_ELSEIF "elseif (T_ELSEIF)"
  117. %left T_ELSE
  118. %token T_ELSE "else (T_ELSE)"
  119. %left T_ENDIF
  120. %token T_ENDIF "endif (T_ENDIF)"
  121. %token T_LNUMBER "integer number (T_LNUMBER)"
  122. %token T_DNUMBER "floating-point number (T_DNUMBER)"
  123. %token T_STRING "identifier (T_STRING)"
  124. %token T_STRING_VARNAME "variable name (T_STRING_VARNAME)"
  125. %token T_VARIABLE "variable (T_VARIABLE)"
  126. %token T_NUM_STRING "number (T_NUM_STRING)"
  127. %token T_INLINE_HTML
  128. %token T_CHARACTER
  129. %token T_BAD_CHARACTER
  130. %token T_ENCAPSED_AND_WHITESPACE "quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE)"
  131. %token T_CONSTANT_ENCAPSED_STRING "quoted-string (T_CONSTANT_ENCAPSED_STRING)"
  132. %token T_ECHO "echo (T_ECHO)"
  133. %token T_DO "do (T_DO)"
  134. %token T_WHILE "while (T_WHILE)"
  135. %token T_ENDWHILE "endwhile (T_ENDWHILE)"
  136. %token T_FOR "for (T_FOR)"
  137. %token T_ENDFOR "endfor (T_ENDFOR)"
  138. %token T_FOREACH "foreach (T_FOREACH)"
  139. %token T_ENDFOREACH "endforeach (T_ENDFOREACH)"
  140. %token T_DECLARE "declare (T_DECLARE)"
  141. %token T_ENDDECLARE "enddeclare (T_ENDDECLARE)"
  142. %token T_AS "as (T_AS)"
  143. %token T_SWITCH "switch (T_SWITCH)"
  144. %token T_ENDSWITCH "endswitch (T_ENDSWITCH)"
  145. %token T_CASE "case (T_CASE)"
  146. %token T_DEFAULT "default (T_DEFAULT)"
  147. %token T_BREAK "break (T_BREAK)"
  148. %token T_CONTINUE "continue (T_CONTINUE)"
  149. %token T_GOTO "goto (T_GOTO)"
  150. %token T_FUNCTION "function (T_FUNCTION)"
  151. %token T_CONST "const (T_CONST)"
  152. %token T_RETURN "return (T_RETURN)"
  153. %token T_TRY "try (T_TRY)"
  154. %token T_CATCH "catch (T_CATCH)"
  155. %token T_FINALLY "finally (T_FINALLY)"
  156. %token T_THROW "throw (T_THROW)"
  157. %token T_USE "use (T_USE)"
  158. %token T_INSTEADOF "insteadof (T_INSTEADOF)"
  159. %token T_GLOBAL "global (T_GLOBAL)"
  160. %right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
  161. %token T_STATIC "static (T_STATIC)"
  162. %token T_ABSTRACT "abstract (T_ABSTRACT)"
  163. %token T_FINAL "final (T_FINAL)"
  164. %token T_PRIVATE "private (T_PRIVATE)"
  165. %token T_PROTECTED "protected (T_PROTECTED)"
  166. %token T_PUBLIC "public (T_PUBLIC)"
  167. %token T_VAR "var (T_VAR)"
  168. %token T_UNSET "unset (T_UNSET)"
  169. %token T_ISSET "isset (T_ISSET)"
  170. %token T_EMPTY "empty (T_EMPTY)"
  171. %token T_HALT_COMPILER "__halt_compiler (T_HALT_COMPILER)"
  172. %token T_CLASS "class (T_CLASS)"
  173. %token T_TRAIT "trait (T_TRAIT)"
  174. %token T_INTERFACE "interface (T_INTERFACE)"
  175. %token T_EXTENDS "extends (T_EXTENDS)"
  176. %token T_IMPLEMENTS "implements (T_IMPLEMENTS)"
  177. %token T_OBJECT_OPERATOR "-> (T_OBJECT_OPERATOR)"
  178. %token T_DOUBLE_ARROW "=> (T_DOUBLE_ARROW)"
  179. %token T_LIST "list (T_LIST)"
  180. %token T_ARRAY "array (T_ARRAY)"
  181. %token T_CALLABLE "callable (T_CALLABLE)"
  182. %token T_CLASS_C "__CLASS__ (T_CLASS_C)"
  183. %token T_TRAIT_C "__TRAIT__ (T_TRAIT_C)"
  184. %token T_METHOD_C "__METHOD__ (T_METHOD_C)"
  185. %token T_FUNC_C "__FUNCTION__ (T_FUNC_C)"
  186. %token T_LINE "__LINE__ (T_LINE)"
  187. %token T_FILE "__FILE__ (T_FILE)"
  188. %token T_COMMENT "comment (T_COMMENT)"
  189. %token T_DOC_COMMENT "doc comment (T_DOC_COMMENT)"
  190. %token T_OPEN_TAG "open tag (T_OPEN_TAG)"
  191. %token T_OPEN_TAG_WITH_ECHO "open tag with echo (T_OPEN_TAG_WITH_ECHO)"
  192. %token T_CLOSE_TAG "close tag (T_CLOSE_TAG)"
  193. %token T_WHITESPACE "whitespace (T_WHITESPACE)"
  194. %token T_START_HEREDOC "heredoc start (T_START_HEREDOC)"
  195. %token T_END_HEREDOC "heredoc end (T_END_HEREDOC)"
  196. %token T_DOLLAR_OPEN_CURLY_BRACES "${ (T_DOLLAR_OPEN_CURLY_BRACES)"
  197. %token T_CURLY_OPEN "{$ (T_CURLY_OPEN)"
  198. %token T_PAAMAYIM_NEKUDOTAYIM ":: (T_PAAMAYIM_NEKUDOTAYIM)"
  199. %token T_NAMESPACE "namespace (T_NAMESPACE)"
  200. %token T_NS_C "__NAMESPACE__ (T_NS_C)"
  201. %token T_DIR "__DIR__ (T_DIR)"
  202. %token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)"
  203. %% /* Rules */
  204. start:
  205. top_statement_list { zend_do_end_compilation(TSRMLS_C); }
  206. ;
  207. top_statement_list:
  208. top_statement_list { zend_do_extended_info(TSRMLS_C); } top_statement { HANDLE_INTERACTIVE(); }
  209. | /* empty */
  210. ;
  211. namespace_name:
  212. T_STRING { $$ = $1; }
  213. | namespace_name T_NS_SEPARATOR T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
  214. ;
  215. top_statement:
  216. statement { zend_verify_namespace(TSRMLS_C); }
  217. | function_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); }
  218. | class_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); }
  219. | T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
  220. | T_NAMESPACE namespace_name ';' { zend_do_begin_namespace(&$2, 0 TSRMLS_CC); }
  221. | T_NAMESPACE namespace_name '{' { zend_do_begin_namespace(&$2, 1 TSRMLS_CC); }
  222. top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); }
  223. | T_NAMESPACE '{' { zend_do_begin_namespace(NULL, 1 TSRMLS_CC); }
  224. top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); }
  225. | T_USE use_declarations ';' { zend_verify_namespace(TSRMLS_C); }
  226. | constant_declaration ';' { zend_verify_namespace(TSRMLS_C); }
  227. ;
  228. use_declarations:
  229. use_declarations ',' use_declaration
  230. | use_declaration
  231. ;
  232. use_declaration:
  233. namespace_name { zend_do_use(&$1, NULL, 0 TSRMLS_CC); }
  234. | namespace_name T_AS T_STRING { zend_do_use(&$1, &$3, 0 TSRMLS_CC); }
  235. | T_NS_SEPARATOR namespace_name { zend_do_use(&$2, NULL, 1 TSRMLS_CC); }
  236. | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use(&$2, &$4, 1 TSRMLS_CC); }
  237. ;
  238. constant_declaration:
  239. constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); }
  240. | T_CONST T_STRING '=' static_scalar { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); }
  241. ;
  242. inner_statement_list:
  243. inner_statement_list { zend_do_extended_info(TSRMLS_C); } inner_statement { HANDLE_INTERACTIVE(); }
  244. | /* empty */
  245. ;
  246. inner_statement:
  247. statement
  248. | function_declaration_statement
  249. | class_declaration_statement
  250. | T_HALT_COMPILER '(' ')' ';' { zend_error(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope"); }
  251. ;
  252. statement:
  253. unticked_statement { DO_TICKS(); }
  254. | T_STRING ':' { zend_do_label(&$1 TSRMLS_CC); }
  255. ;
  256. unticked_statement:
  257. '{' inner_statement_list '}'
  258. | T_IF parenthesis_expr { zend_do_if_cond(&$2, &$1 TSRMLS_CC); } statement { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); }
  259. | T_IF parenthesis_expr ':' { zend_do_if_cond(&$2, &$1 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); }
  260. | T_WHILE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr { zend_do_while_cond(&$3, &$$ TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$4 TSRMLS_CC); }
  261. | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE { $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr ';' { zend_do_do_while_end(&$1, &$4, &$6 TSRMLS_CC); }
  262. | T_FOR
  263. '('
  264. for_expr
  265. ';' { zend_do_free(&$3 TSRMLS_CC); $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); }
  266. for_expr
  267. ';' { zend_do_extended_info(TSRMLS_C); zend_do_for_cond(&$6, &$7 TSRMLS_CC); }
  268. for_expr
  269. ')' { zend_do_free(&$9 TSRMLS_CC); zend_do_for_before_statement(&$4, &$7 TSRMLS_CC); }
  270. for_statement { zend_do_for_end(&$7 TSRMLS_CC); }
  271. | T_SWITCH parenthesis_expr { zend_do_switch_cond(&$2 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$4 TSRMLS_CC); }
  272. | T_BREAK ';' { zend_do_brk_cont(ZEND_BRK, NULL TSRMLS_CC); }
  273. | T_BREAK expr ';' { zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); }
  274. | T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); }
  275. | T_CONTINUE expr ';' { zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); }
  276. | T_RETURN ';' { zend_do_return(NULL, 0 TSRMLS_CC); }
  277. | T_RETURN expr_without_variable ';' { zend_do_return(&$2, 0 TSRMLS_CC); }
  278. | T_RETURN variable ';' { zend_do_return(&$2, 1 TSRMLS_CC); }
  279. | yield_expr ';' { zend_do_free(&$1 TSRMLS_CC); }
  280. | T_GLOBAL global_var_list ';'
  281. | T_STATIC static_var_list ';'
  282. | T_ECHO echo_expr_list ';'
  283. | T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); }
  284. | expr ';' { zend_do_free(&$1 TSRMLS_CC); }
  285. | T_UNSET '(' unset_variables ')' ';'
  286. | T_FOREACH '(' variable T_AS
  287. { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
  288. foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
  289. foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
  290. | T_FOREACH '(' expr_without_variable T_AS
  291. { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
  292. foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
  293. foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
  294. | T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
  295. | ';' /* empty statement */
  296. | T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
  297. catch_statement { zend_do_bind_catch(&$1, &$6 TSRMLS_CC); }
  298. finally_statement { zend_do_end_finally(&$1, &$6, &$8 TSRMLS_CC); }
  299. | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
  300. | T_GOTO T_STRING ';' { zend_do_goto(&$2 TSRMLS_CC); }
  301. ;
  302. catch_statement:
  303. /* empty */ { $$.op_type = IS_UNUSED; }
  304. | T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); }
  305. fully_qualified_class_name { zend_do_first_catch(&$2 TSRMLS_CC); }
  306. T_VARIABLE ')' { zend_do_begin_catch(&$1, &$4, &$6, &$2 TSRMLS_CC); }
  307. '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
  308. additional_catches { zend_do_mark_last_catch(&$2, &$13 TSRMLS_CC); $$ = $1;}
  309. finally_statement:
  310. /* empty */ { $$.op_type = IS_UNUSED; }
  311. | T_FINALLY { zend_do_finally(&$1 TSRMLS_CC); } '{' inner_statement_list '}' { $$ = $1; }
  312. ;
  313. additional_catches:
  314. non_empty_additional_catches { $$ = $1; }
  315. | /* empty */ { $$.u.op.opline_num = -1; }
  316. ;
  317. non_empty_additional_catches:
  318. additional_catch { $$ = $1; }
  319. | non_empty_additional_catches additional_catch { $$ = $2; }
  320. ;
  321. additional_catch:
  322. T_CATCH '(' fully_qualified_class_name { $$.u.op.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
  323. ;
  324. unset_variables:
  325. unset_variable
  326. | unset_variables ',' unset_variable
  327. ;
  328. unset_variable:
  329. variable { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
  330. ;
  331. function_declaration_statement:
  332. unticked_function_declaration_statement { DO_TICKS(); }
  333. ;
  334. class_declaration_statement:
  335. unticked_class_declaration_statement { DO_TICKS(); }
  336. ;
  337. is_reference:
  338. /* empty */ { $$.op_type = ZEND_RETURN_VAL; }
  339. | '&' { $$.op_type = ZEND_RETURN_REF; }
  340. ;
  341. unticked_function_declaration_statement:
  342. function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); }
  343. '(' parameter_list ')'
  344. '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
  345. ;
  346. unticked_class_declaration_statement:
  347. class_entry_type T_STRING extends_from
  348. { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); }
  349. implements_list
  350. '{'
  351. class_statement_list
  352. '}' { zend_do_end_class_declaration(&$1, &$3 TSRMLS_CC); }
  353. | interface_entry T_STRING
  354. { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); }
  355. interface_extends_list
  356. '{'
  357. class_statement_list
  358. '}' { zend_do_end_class_declaration(&$1, NULL TSRMLS_CC); }
  359. ;
  360. class_entry_type:
  361. T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = 0; }
  362. | T_ABSTRACT T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
  363. | T_TRAIT { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_TRAIT; }
  364. | T_FINAL T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_FINAL_CLASS; }
  365. ;
  366. extends_from:
  367. /* empty */ { $$.op_type = IS_UNUSED; }
  368. | T_EXTENDS fully_qualified_class_name { zend_do_fetch_class(&$$, &$2 TSRMLS_CC); }
  369. ;
  370. interface_entry:
  371. T_INTERFACE { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_INTERFACE; }
  372. ;
  373. interface_extends_list:
  374. /* empty */
  375. | T_EXTENDS interface_list
  376. ;
  377. implements_list:
  378. /* empty */
  379. | T_IMPLEMENTS interface_list
  380. ;
  381. interface_list:
  382. fully_qualified_class_name { zend_do_implements_interface(&$1 TSRMLS_CC); }
  383. | interface_list ',' fully_qualified_class_name { zend_do_implements_interface(&$3 TSRMLS_CC); }
  384. ;
  385. foreach_optional_arg:
  386. /* empty */ { $$.op_type = IS_UNUSED; }
  387. | T_DOUBLE_ARROW foreach_variable { $$ = $2; }
  388. ;
  389. foreach_variable:
  390. variable { zend_check_writable_variable(&$1); $$ = $1; }
  391. | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; }
  392. | T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' { $$ = $1; $$.EA = ZEND_PARSED_LIST_EXPR; }
  393. ;
  394. for_statement:
  395. statement
  396. | ':' inner_statement_list T_ENDFOR ';'
  397. ;
  398. foreach_statement:
  399. statement
  400. | ':' inner_statement_list T_ENDFOREACH ';'
  401. ;
  402. declare_statement:
  403. statement
  404. | ':' inner_statement_list T_ENDDECLARE ';'
  405. ;
  406. declare_list:
  407. T_STRING '=' static_scalar { zend_do_declare_stmt(&$1, &$3 TSRMLS_CC); }
  408. | declare_list ',' T_STRING '=' static_scalar { zend_do_declare_stmt(&$3, &$5 TSRMLS_CC); }
  409. ;
  410. switch_case_list:
  411. '{' case_list '}' { $$ = $2; }
  412. | '{' ';' case_list '}' { $$ = $3; }
  413. | ':' case_list T_ENDSWITCH ';' { $$ = $2; }
  414. | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; }
  415. ;
  416. case_list:
  417. /* empty */ { $$.op_type = IS_UNUSED; }
  418. | case_list T_CASE expr case_separator { zend_do_extended_info(TSRMLS_C); zend_do_case_before_statement(&$1, &$2, &$3 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
  419. | case_list T_DEFAULT case_separator { zend_do_extended_info(TSRMLS_C); zend_do_default_before_statement(&$1, &$2 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
  420. ;
  421. case_separator:
  422. ':'
  423. | ';'
  424. ;
  425. while_statement:
  426. statement
  427. | ':' inner_statement_list T_ENDWHILE ';'
  428. ;
  429. elseif_list:
  430. /* empty */
  431. | elseif_list T_ELSEIF parenthesis_expr { zend_do_if_cond(&$3, &$2 TSRMLS_CC); } statement { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); }
  432. ;
  433. new_elseif_list:
  434. /* empty */
  435. | new_elseif_list T_ELSEIF parenthesis_expr ':' { zend_do_if_cond(&$3, &$2 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); }
  436. ;
  437. else_single:
  438. /* empty */
  439. | T_ELSE statement
  440. ;
  441. new_else_single:
  442. /* empty */
  443. | T_ELSE ':' inner_statement_list
  444. ;
  445. parameter_list:
  446. non_empty_parameter_list
  447. | /* empty */
  448. ;
  449. non_empty_parameter_list:
  450. optional_class_type T_VARIABLE { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$2, &$$, NULL, &$1, 0 TSRMLS_CC); }
  451. | optional_class_type '&' T_VARIABLE { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$3, &$$, NULL, &$1, 1 TSRMLS_CC); }
  452. | optional_class_type '&' T_VARIABLE '=' static_scalar { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV_INIT, &$3, &$$, &$5, &$1, 1 TSRMLS_CC); }
  453. | optional_class_type T_VARIABLE '=' static_scalar { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV_INIT, &$2, &$$, &$4, &$1, 0 TSRMLS_CC); }
  454. | non_empty_parameter_list ',' optional_class_type T_VARIABLE { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV, &$4, &$$, NULL, &$3, 0 TSRMLS_CC); }
  455. | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV, &$5, &$$, NULL, &$3, 1 TSRMLS_CC); }
  456. | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '=' static_scalar { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV_INIT, &$5, &$$, &$7, &$3, 1 TSRMLS_CC); }
  457. | non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV_INIT, &$4, &$$, &$6, &$3, 0 TSRMLS_CC); }
  458. ;
  459. optional_class_type:
  460. /* empty */ { $$.op_type = IS_UNUSED; }
  461. | T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; }
  462. | T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CALLABLE; }
  463. | fully_qualified_class_name { $$ = $1; }
  464. ;
  465. function_call_parameter_list:
  466. '(' ')' { Z_LVAL($$.u.constant) = 0; }
  467. | '(' non_empty_function_call_parameter_list ')' { $$ = $2; }
  468. | '(' yield_expr ')' { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$2, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
  469. ;
  470. non_empty_function_call_parameter_list:
  471. expr_without_variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$1, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
  472. | variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$1, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
  473. | '&' w_variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$2, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
  474. | non_empty_function_call_parameter_list ',' expr_without_variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$3, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
  475. | non_empty_function_call_parameter_list ',' variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$3, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
  476. | non_empty_function_call_parameter_list ',' '&' w_variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$4, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
  477. ;
  478. global_var_list:
  479. global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
  480. | global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
  481. ;
  482. global_var:
  483. T_VARIABLE { $$ = $1; }
  484. | '$' r_variable { $$ = $2; }
  485. | '$' '{' expr '}' { $$ = $3; }
  486. ;
  487. static_var_list:
  488. static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
  489. | static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
  490. | T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
  491. | T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); }
  492. ;
  493. class_statement_list:
  494. class_statement_list class_statement
  495. | /* empty */
  496. ;
  497. class_statement:
  498. variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';'
  499. | class_constant_declaration ';'
  500. | trait_use_statement
  501. | method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); }
  502. '(' parameter_list ')'
  503. method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
  504. ;
  505. trait_use_statement:
  506. T_USE trait_list trait_adaptations
  507. ;
  508. trait_list:
  509. fully_qualified_class_name { zend_do_use_trait(&$1 TSRMLS_CC); }
  510. | trait_list ',' fully_qualified_class_name { zend_do_use_trait(&$3 TSRMLS_CC); }
  511. ;
  512. trait_adaptations:
  513. ';'
  514. | '{' trait_adaptation_list '}'
  515. ;
  516. trait_adaptation_list:
  517. /* empty */
  518. | non_empty_trait_adaptation_list
  519. ;
  520. non_empty_trait_adaptation_list:
  521. trait_adaptation_statement
  522. | non_empty_trait_adaptation_list trait_adaptation_statement
  523. ;
  524. trait_adaptation_statement:
  525. trait_precedence ';'
  526. | trait_alias ';'
  527. ;
  528. trait_precedence:
  529. trait_method_reference_fully_qualified T_INSTEADOF trait_reference_list { zend_add_trait_precedence(&$1, &$3 TSRMLS_CC); }
  530. ;
  531. trait_reference_list:
  532. fully_qualified_class_name { zend_resolve_class_name(&$1, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STRVAL($1.u.constant) TSRMLS_CC); }
  533. | trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name(&$3, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC); zend_add_to_list(&$1.u.op.ptr, Z_STRVAL($3.u.constant) TSRMLS_CC); $$ = $1; }
  534. ;
  535. trait_method_reference:
  536. T_STRING { zend_prepare_reference(&$$, NULL, &$1 TSRMLS_CC); }
  537. | trait_method_reference_fully_qualified { $$ = $1; }
  538. ;
  539. trait_method_reference_fully_qualified:
  540. fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_prepare_reference(&$$, &$1, &$3 TSRMLS_CC); }
  541. ;
  542. trait_alias:
  543. trait_method_reference T_AS trait_modifiers T_STRING { zend_add_trait_alias(&$1, &$3, &$4 TSRMLS_CC); }
  544. | trait_method_reference T_AS member_modifier { zend_add_trait_alias(&$1, &$3, NULL TSRMLS_CC); }
  545. ;
  546. trait_modifiers:
  547. /* empty */ { Z_LVAL($$.u.constant) = 0x0; } /* No change of methods visibility */
  548. | member_modifier { $$ = $1; } /* REM: Keep in mind, there are not only visibility modifiers */
  549. ;
  550. method_body:
  551. ';' /* abstract method */ { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
  552. | '{' inner_statement_list '}' { Z_LVAL($$.u.constant) = 0; }
  553. ;
  554. variable_modifiers:
  555. non_empty_member_modifiers { $$ = $1; }
  556. | T_VAR { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
  557. ;
  558. method_modifiers:
  559. /* empty */ { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
  560. | non_empty_member_modifiers { $$ = $1; if (!(Z_LVAL($$.u.constant) & ZEND_ACC_PPP_MASK)) { Z_LVAL($$.u.constant) |= ZEND_ACC_PUBLIC; } }
  561. ;
  562. non_empty_member_modifiers:
  563. member_modifier { $$ = $1; }
  564. | non_empty_member_modifiers member_modifier { Z_LVAL($$.u.constant) = zend_do_verify_access_types(&$1, &$2); }
  565. ;
  566. member_modifier:
  567. T_PUBLIC { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
  568. | T_PROTECTED { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; }
  569. | T_PRIVATE { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; }
  570. | T_STATIC { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; }
  571. | T_ABSTRACT { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
  572. | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; }
  573. ;
  574. class_variable_declaration:
  575. class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); }
  576. | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); }
  577. | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); }
  578. | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); }
  579. ;
  580. class_constant_declaration:
  581. class_constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_class_constant(&$3, &$5 TSRMLS_CC); }
  582. | T_CONST T_STRING '=' static_scalar { zend_do_declare_class_constant(&$2, &$4 TSRMLS_CC); }
  583. ;
  584. echo_expr_list:
  585. echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }
  586. | expr { zend_do_echo(&$1 TSRMLS_CC); }
  587. ;
  588. for_expr:
  589. /* empty */ { $$.op_type = IS_CONST; Z_TYPE($$.u.constant) = IS_BOOL; Z_LVAL($$.u.constant) = 1; }
  590. | non_empty_for_expr { $$ = $1; }
  591. ;
  592. non_empty_for_expr:
  593. non_empty_for_expr ',' { zend_do_free(&$1 TSRMLS_CC); } expr { $$ = $4; }
  594. | expr { $$ = $1; }
  595. ;
  596. chaining_method_or_property:
  597. chaining_method_or_property variable_property { $$.EA = $2.EA; }
  598. | variable_property { $$.EA = $1.EA; }
  599. ;
  600. chaining_dereference:
  601. chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  602. | '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); }
  603. ;
  604. chaining_instance_call:
  605. chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; }
  606. | chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; }
  607. | chaining_method_or_property { $$ = $1; }
  608. ;
  609. instance_call:
  610. /* empty */ { $$ = $0; }
  611. | { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
  612. chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); }
  613. ;
  614. new_expr:
  615. T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
  616. ;
  617. expr_without_variable:
  618. T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
  619. | variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
  620. | variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
  621. | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
  622. | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
  623. | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
  624. | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
  625. | variable T_MUL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
  626. | variable T_DIV_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); }
  627. | variable T_CONCAT_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
  628. | variable T_MOD_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); }
  629. | variable T_AND_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
  630. | variable T_OR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
  631. | variable T_XOR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
  632. | variable T_SL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); }
  633. | variable T_SR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); }
  634. | rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); }
  635. | T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); }
  636. | rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); }
  637. | T_DEC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_DEC TSRMLS_CC); }
  638. | expr T_BOOLEAN_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
  639. | expr T_BOOLEAN_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
  640. | expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
  641. | expr T_LOGICAL_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
  642. | expr T_LOGICAL_XOR expr { zend_do_binary_op(ZEND_BOOL_XOR, &$$, &$1, &$3 TSRMLS_CC); }
  643. | expr '|' expr { zend_do_binary_op(ZEND_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
  644. | expr '&' expr { zend_do_binary_op(ZEND_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
  645. | expr '^' expr { zend_do_binary_op(ZEND_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
  646. | expr '.' expr { zend_do_binary_op(ZEND_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
  647. | expr '+' expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); }
  648. | expr '-' expr { zend_do_binary_op(ZEND_SUB, &$$, &$1, &$3 TSRMLS_CC); }
  649. | expr '*' expr { zend_do_binary_op(ZEND_MUL, &$$, &$1, &$3 TSRMLS_CC); }
  650. | expr '/' expr { zend_do_binary_op(ZEND_DIV, &$$, &$1, &$3 TSRMLS_CC); }
  651. | expr '%' expr { zend_do_binary_op(ZEND_MOD, &$$, &$1, &$3 TSRMLS_CC); }
  652. | expr T_SL expr { zend_do_binary_op(ZEND_SL, &$$, &$1, &$3 TSRMLS_CC); }
  653. | expr T_SR expr { zend_do_binary_op(ZEND_SR, &$$, &$1, &$3 TSRMLS_CC); }
  654. | '+' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); zend_do_binary_op(ZEND_ADD, &$$, &$1, &$2 TSRMLS_CC); } }
  655. | '-' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); zend_do_binary_op(ZEND_SUB, &$$, &$1, &$2 TSRMLS_CC); } }
  656. | '!' expr { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$2 TSRMLS_CC); }
  657. | '~' expr { zend_do_unary_op(ZEND_BW_NOT, &$$, &$2 TSRMLS_CC); }
  658. | expr T_IS_IDENTICAL expr { zend_do_binary_op(ZEND_IS_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
  659. | expr T_IS_NOT_IDENTICAL expr { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
  660. | expr T_IS_EQUAL expr { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
  661. | expr T_IS_NOT_EQUAL expr { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
  662. | expr '<' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$1, &$3 TSRMLS_CC); }
  663. | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
  664. | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }
  665. | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
  666. | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
  667. | parenthesis_expr { $$ = $1; }
  668. | new_expr { $$ = $1; }
  669. | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; }
  670. | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
  671. expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
  672. expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
  673. | expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); }
  674. expr { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }
  675. | internal_functions_in_yacc { $$ = $1; }
  676. | T_INT_CAST expr { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); }
  677. | T_DOUBLE_CAST expr { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); }
  678. | T_STRING_CAST expr { zend_do_cast(&$$, &$2, IS_STRING TSRMLS_CC); }
  679. | T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); }
  680. | T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
  681. | T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); }
  682. | T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); }
  683. | T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); }
  684. | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
  685. | scalar { $$ = $1; }
  686. | combined_scalar_offset { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); }
  687. | combined_scalar { $$ = $1; }
  688. | '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
  689. | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
  690. | T_YIELD { zend_do_yield(&$$, NULL, NULL, 0 TSRMLS_CC); }
  691. | function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); }
  692. '(' parameter_list ')' lexical_vars
  693. '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $3; }
  694. | T_STATIC function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); }
  695. '(' parameter_list ')' lexical_vars
  696. '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $4; }
  697. ;
  698. yield_expr:
  699. T_YIELD expr_without_variable { zend_do_yield(&$$, &$2, NULL, 0 TSRMLS_CC); }
  700. | T_YIELD variable { zend_do_yield(&$$, &$2, NULL, 1 TSRMLS_CC); }
  701. | T_YIELD expr T_DOUBLE_ARROW expr_without_variable { zend_do_yield(&$$, &$4, &$2, 0 TSRMLS_CC); }
  702. | T_YIELD expr T_DOUBLE_ARROW variable { zend_do_yield(&$$, &$4, &$2, 1 TSRMLS_CC); }
  703. ;
  704. combined_scalar_offset:
  705. combined_scalar '[' dim_offset ']' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  706. | combined_scalar_offset '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  707. | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $1.EA = 0; zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  708. combined_scalar:
  709. T_ARRAY '(' array_pair_list ')' { $$ = $3; }
  710. | '[' array_pair_list ']' { $$ = $2; }
  711. function:
  712. T_FUNCTION { $$.u.op.opline_num = CG(zend_lineno); }
  713. ;
  714. lexical_vars:
  715. /* empty */
  716. | T_USE '(' lexical_var_list ')'
  717. ;
  718. lexical_var_list:
  719. lexical_var_list ',' T_VARIABLE { zend_do_fetch_lexical_variable(&$3, 0 TSRMLS_CC); }
  720. | lexical_var_list ',' '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$4, 1 TSRMLS_CC); }
  721. | T_VARIABLE { zend_do_fetch_lexical_variable(&$1, 0 TSRMLS_CC); }
  722. | '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$2, 1 TSRMLS_CC); }
  723. ;
  724. function_call:
  725. namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
  726. function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$3, 0, $2.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
  727. | T_NAMESPACE T_NS_SEPARATOR namespace_name { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant); zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $$.u.op.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); }
  728. function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$5, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
  729. | T_NS_SEPARATOR namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
  730. function_call_parameter_list { zend_do_end_function_call(&$2, &$$, &$4, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
  731. | class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { $$.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
  732. function_call_parameter_list { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, &$5, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
  733. | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
  734. function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
  735. | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
  736. function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
  737. | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
  738. function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
  739. | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
  740. function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$3, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
  741. ;
  742. class_name:
  743. T_STATIC { $$.op_type = IS_CONST; ZVAL_STRINGL(&$$.u.constant, "static", sizeof("static")-1, 1);}
  744. | namespace_name { $$ = $1; }
  745. | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
  746. | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); $$ = $2; }
  747. ;
  748. fully_qualified_class_name:
  749. namespace_name { $$ = $1; }
  750. | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
  751. | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); $$ = $2; }
  752. ;
  753. class_name_reference:
  754. class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
  755. | dynamic_class_name_reference { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
  756. ;
  757. dynamic_class_name_reference:
  758. base_variable T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
  759. object_property { zend_do_push_object(&$4 TSRMLS_CC); } dynamic_class_name_variable_properties
  760. { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = ZEND_PARSED_MEMBER; }
  761. | base_variable { $$ = $1; }
  762. ;
  763. dynamic_class_name_variable_properties:
  764. dynamic_class_name_variable_properties dynamic_class_name_variable_property
  765. | /* empty */
  766. ;
  767. dynamic_class_name_variable_property:
  768. T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); }
  769. ;
  770. exit_expr:
  771. /* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
  772. | '(' ')' { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
  773. | parenthesis_expr { $$ = $1; }
  774. ;
  775. backticks_expr:
  776. /* empty */ { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
  777. | T_ENCAPSED_AND_WHITESPACE { $$ = $1; }
  778. | encaps_list { $$ = $1; }
  779. ;
  780. ctor_arguments:
  781. /* empty */ { Z_LVAL($$.u.constant) = 0; }
  782. | function_call_parameter_list { $$ = $1; }
  783. ;
  784. common_scalar:
  785. T_LNUMBER { $$ = $1; }
  786. | T_DNUMBER { $$ = $1; }
  787. | T_CONSTANT_ENCAPSED_STRING { $$ = $1; }
  788. | T_LINE { $$ = $1; }
  789. | T_FILE { $$ = $1; }
  790. | T_DIR { $$ = $1; }
  791. | T_TRAIT_C { $$ = $1; }
  792. | T_METHOD_C { $$ = $1; }
  793. | T_FUNC_C { $$ = $1; }
  794. | T_NS_C { $$ = $1; }
  795. | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; }
  796. | T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
  797. ;
  798. static_scalar: /* compile-time evaluated scalars */
  799. common_scalar { $$ = $1; }
  800. | static_class_name_scalar { $$ = $1; }
  801. | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
  802. | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); }
  803. | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
  804. | '+' static_scalar { ZVAL_LONG(&$1.u.constant, 0); add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
  805. | '-' static_scalar { ZVAL_LONG(&$1.u.constant, 0); sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
  806. | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
  807. | '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
  808. | static_class_constant { $$ = $1; }
  809. | T_CLASS_C { $$ = $1; }
  810. ;
  811. static_class_constant:
  812. class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
  813. ;
  814. scalar:
  815. T_STRING_VARNAME { $$ = $1; }
  816. | class_name_scalar { $$ = $1; }
  817. | class_constant { $$ = $1; }
  818. | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); }
  819. | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_RT, 0 TSRMLS_CC); }
  820. | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); }
  821. | common_scalar { $$ = $1; }
  822. | '"' encaps_list '"' { $$ = $2; }
  823. | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; }
  824. | T_CLASS_C { if (Z_TYPE($1.u.constant) == IS_CONSTANT) {zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC);} else {$$ = $1;} }
  825. ;
  826. static_array_pair_list:
  827. /* empty */ { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); }
  828. | non_empty_static_array_pair_list possible_comma { $$ = $1; }
  829. ;
  830. possible_comma:
  831. /* empty */
  832. | ','
  833. ;
  834. non_empty_static_array_pair_list:
  835. non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW static_scalar { zend_do_add_static_array_element(&$$, &$3, &$5); }
  836. | non_empty_static_array_pair_list ',' static_scalar { zend_do_add_static_array_element(&$$, NULL, &$3); }
  837. | static_scalar T_DOUBLE_ARROW static_scalar { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); zend_do_add_static_array_element(&$$, &$1, &$3); }
  838. | static_scalar { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); zend_do_add_static_array_element(&$$, NULL, &$1); }
  839. ;
  840. expr:
  841. r_variable { $$ = $1; }
  842. | expr_without_variable { $$ = $1; }
  843. ;
  844. parenthesis_expr:
  845. '(' expr ')' { $$ = $2; }
  846. | '(' yield_expr ')' { $$ = $2; }
  847. ;
  848. r_variable:
  849. variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
  850. ;
  851. w_variable:
  852. variable { zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $$ = $1;
  853. zend_check_writable_variable(&$1); }
  854. ;
  855. rw_variable:
  856. variable { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); $$ = $1;
  857. zend_check_writable_variable(&$1); }
  858. ;
  859. variable:
  860. base_variable_with_function_calls T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
  861. object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties
  862. { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = $1.EA | ($7.EA ? $7.EA : $6.EA); }
  863. | base_variable_with_function_calls { $$ = $1; }
  864. ;
  865. variable_properties:
  866. variable_properties variable_property { $$.EA = $2.EA; }
  867. | /* empty */ { $$.EA = 0; }
  868. ;
  869. variable_property:
  870. T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } method_or_not { $$.EA = $4.EA; }
  871. ;
  872. array_method_dereference:
  873. array_method_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  874. | method '[' dim_offset ']' { $1.EA = ZEND_PARSED_METHOD_CALL; fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  875. ;
  876. method:
  877. { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_begin_method_call(&$$ TSRMLS_CC); }
  878. function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$2, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
  879. ;
  880. method_or_not:
  881. method { $$ = $1; $$.EA = ZEND_PARSED_METHOD_CALL; zend_do_push_object(&$$ TSRMLS_CC); }
  882. | array_method_dereference { $$ = $1; zend_do_push_object(&$$ TSRMLS_CC); }
  883. | /* empty */ { $$.EA = ZEND_PARSED_MEMBER; }
  884. ;
  885. variable_without_objects:
  886. reference_variable { $$ = $1; }
  887. | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); }
  888. ;
  889. static_member:
  890. class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
  891. | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
  892. ;
  893. variable_class_name:
  894. reference_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$=$1;; }
  895. ;
  896. array_function_dereference:
  897. array_function_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  898. | function_call { zend_do_begin_variable_parse(TSRMLS_C); $1.EA = ZEND_PARSED_FUNCTION_CALL; }
  899. '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$4 TSRMLS_CC); }
  900. ;
  901. base_variable_with_function_calls:
  902. base_variable { $$ = $1; }
  903. | array_function_dereference { $$ = $1; }
  904. | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.EA = ZEND_PARSED_FUNCTION_CALL; }
  905. ;
  906. base_variable:
  907. reference_variable { $$ = $1; $$.EA = ZEND_PARSED_VARIABLE; }
  908. | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); $$.EA = ZEND_PARSED_VARIABLE; }
  909. | static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; }
  910. ;
  911. reference_variable:
  912. reference_variable '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  913. | reference_variable '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); }
  914. | compound_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
  915. ;
  916. compound_variable:
  917. T_VARIABLE { $$ = $1; }
  918. | '$' '{' expr '}' { $$ = $3; }
  919. ;
  920. dim_offset:
  921. /* empty */ { $$.op_type = IS_UNUSED; }
  922. | expr { $$ = $1; }
  923. ;
  924. object_property:
  925. object_dim_list { $$ = $1; }
  926. | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
  927. ;
  928. object_dim_list:
  929. object_dim_list '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
  930. | object_dim_list '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); }
  931. | variable_name { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
  932. ;
  933. variable_name:
  934. T_STRING { $$ = $1; }
  935. | '{' expr '}' { $$ = $2; }
  936. ;
  937. simple_indirect_reference:
  938. '$' { Z_LVAL($$.u.constant) = 1; }
  939. | simple_indirect_reference '$' { Z_LVAL($$.u.constant)++; }
  940. ;
  941. assignment_list:
  942. assignment_list ',' assignment_list_element
  943. | assignment_list_element
  944. ;
  945. assignment_list_element:
  946. variable { zend_do_add_list_element(&$1 TSRMLS_CC); }
  947. | T_LIST '(' { zend_do_new_list_begin(TSRMLS_C); } assignment_list ')' { zend_do_new_list_end(TSRMLS_C); }
  948. | /* empty */ { zend_do_add_list_element(NULL TSRMLS_CC); }
  949. ;
  950. array_pair_list:
  951. /* empty */ { zend_do_init_array(&$$, NULL, NULL, 0 TSRMLS_CC); }
  952. | non_empty_array_pair_list possible_comma { $$ = $1; }
  953. ;
  954. non_empty_array_pair_list:
  955. non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { zend_do_add_array_element(&$$, &$5, &$3, 0 TSRMLS_CC); }
  956. | non_empty_array_pair_list ',' expr { zend_do_add_array_element(&$$, &$3, NULL, 0 TSRMLS_CC); }
  957. | expr T_DOUBLE_ARROW expr { zend_do_init_array(&$$, &$3, &$1, 0 TSRMLS_CC); }
  958. | expr { zend_do_init_array(&$$, &$1, NULL, 0 TSRMLS_CC); }
  959. | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable { zend_do_add_array_element(&$$, &$6, &$3, 1 TSRMLS_CC); }
  960. | non_empty_array_pair_list ',' '&' w_variable { zend_do_add_array_element(&$$, &$4, NULL, 1 TSRMLS_CC); }
  961. | expr T_DOUBLE_ARROW '&' w_variable { zend_do_init_array(&$$, &$4, &$1, 1 TSRMLS_CC); }
  962. | '&' w_variable { zend_do_init_array(&$$, &$2, NULL, 1 TSRMLS_CC); }
  963. ;
  964. encaps_list:
  965. encaps_list encaps_var { zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
  966. | encaps_list T_ENCAPSED_AND_WHITESPACE { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
  967. | encaps_var { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, NULL, &$1 TSRMLS_CC); }
  968. | T_ENCAPSED_AND_WHITESPACE encaps_var { zend_do_add_string(&$$, NULL, &$1 TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$$, &$2 TSRMLS_CC); }
  969. ;
  970. encaps_var:
  971. T_VARIABLE { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
  972. | T_VARIABLE '[' { zend_do_begin_variable_parse(TSRMLS_C); } encaps_var_offset ']' { fetch_array_begin(&$$, &$1, &$4 TSRMLS_CC); }
  973. | T_VARIABLE T_OBJECT_OPERATOR T_STRING { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$2, &$1, 1 TSRMLS_CC); zend_do_fetch_property(&$$, &$2, &$3 TSRMLS_CC); }
  974. | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$2, 1 TSRMLS_CC); }
  975. | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_begin(&$$, &$2, &$4 TSRMLS_CC); }
  976. | T_CURLY_OPEN variable '}' { $$ = $2; }
  977. ;
  978. encaps_var_offset:
  979. T_STRING { $$ = $1; }
  980. | T_NUM_STRING { $$ = $1; }
  981. | T_VARIABLE { fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
  982. ;
  983. internal_functions_in_yacc:
  984. T_ISSET '(' isset_variables ')' { $$ = $3; }
  985. | T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); }
  986. | T_EMPTY '(' expr_without_variable ')' { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$3 TSRMLS_CC); }
  987. | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
  988. | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
  989. | T_EVAL '(' expr ')' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
  990. | T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
  991. | T_REQUIRE_ONCE expr { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }
  992. ;
  993. isset_variables:
  994. isset_variable { $$ = $1; }
  995. | isset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } isset_variable { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
  996. ;
  997. isset_variable:
  998. variable { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); }
  999. | expr_without_variable { zend_error(E_COMPILE_ERROR, "Cannot use isset() on the result of an expression (you can use \"null !== expression\" instead)"); }
  1000. ;
  1001. class_constant:
  1002. class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
  1003. | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
  1004. ;
  1005. static_class_name_scalar:
  1006. class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS { zend_do_resolve_class_name(&$$, &$1, 1 TSRMLS_CC); }
  1007. ;
  1008. class_name_scalar:
  1009. class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS { zend_do_resolve_class_name(&$$, &$1, 0 TSRMLS_CC); }
  1010. ;
  1011. %%
  1012. /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
  1013. quotes and backslashes, so that it's suitable for yyerror. The
  1014. heuristic is that double-quoting is unnecessary unless the string
  1015. contains an apostrophe, a comma, or backslash (other than
  1016. backslash-backslash). YYSTR is taken from yytname. If YYRES is
  1017. null, do not copy; instead, return the length of what the result
  1018. would have been. */
  1019. static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr)
  1020. {
  1021. if (!yyres) {
  1022. return yystrlen(yystr);
  1023. }
  1024. {
  1025. TSRMLS_FETCH();
  1026. if (CG(parse_error) == 0) {
  1027. char buffer[120];
  1028. const unsigned char *end, *str, *tok1 = NULL, *tok2 = NULL;
  1029. unsigned int len = 0, toklen = 0, yystr_len;
  1030. CG(parse_error) = 1;
  1031. if (LANG_SCNG(yy_text)[0] == 0 &&
  1032. LANG_SCNG(yy_leng) == 1 &&
  1033. memcmp(yystr, "\"end of file\"", sizeof("\"end of file\"") - 1) == 0) {
  1034. yystpcpy(yyres, "end of file");
  1035. return sizeof("end of file")-1;
  1036. }
  1037. str = LANG_SCNG(yy_text);
  1038. end = memchr(str, '\n', LANG_SCNG(yy_leng));
  1039. yystr_len = yystrlen(yystr);
  1040. if ((tok1 = memchr(yystr, '(', yystr_len)) != NULL
  1041. && (tok2 = zend_memrchr(yystr, ')', yystr_len)) != NULL) {
  1042. toklen = (tok2 - tok1) + 1;
  1043. } else {
  1044. tok1 = tok2 = NULL;
  1045. toklen = 0;
  1046. }
  1047. if (end == NULL) {
  1048. len = LANG_SCNG(yy_leng) > 30 ? 30 : LANG_SCNG(yy_leng);
  1049. } else {
  1050. len = (end - str) > 30 ? 30 : (end - str);
  1051. }
  1052. if (toklen) {
  1053. snprintf(buffer, sizeof(buffer), "'%.*s' %.*s", len, str, toklen, tok1);
  1054. } else {
  1055. snprintf(buffer, sizeof(buffer), "'%.*s'", len, str);
  1056. }
  1057. yystpcpy(yyres, buffer);
  1058. return len + (toklen ? toklen + 1 : 0) + 2;
  1059. }
  1060. }
  1061. if (*yystr == '"') {
  1062. YYSIZE_T yyn = 0;
  1063. const char *yyp = yystr;
  1064. for (; *++yyp != '"'; ++yyn) {
  1065. yyres[yyn] = *yyp;
  1066. }
  1067. yyres[yyn] = '\0';
  1068. return yyn;
  1069. }
  1070. yystpcpy(yyres, yystr);
  1071. return strlen(yystr);
  1072. }
  1073. /*
  1074. * Local variables:
  1075. * tab-width: 4
  1076. * c-basic-offset: 4
  1077. * indent-tabs-mode: t
  1078. * End:
  1079. */