]> granicus.if.org Git - php/commitdiff
Implemented Traits for PHP as proposed in the RFC [TRAITS]
authorStefan Marr <gron@php.net>
Thu, 22 Apr 2010 22:05:56 +0000 (22:05 +0000)
committerStefan Marr <gron@php.net>
Thu, 22 Apr 2010 22:05:56 +0000 (22:05 +0000)
# 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)

12 files changed:
Zend/zend.h
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute_API.c
Zend/zend_language_parser.y
Zend/zend_language_scanner.c
Zend/zend_language_scanner.l
Zend/zend_language_scanner_defs.h
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.h

index 7efa9f4825d886e2ba59e26eb6b46625cde59224..c077cb1c53012a5ba4831a2ee84379b50f4306cf 100644 (file)
@@ -420,6 +420,44 @@ struct _zend_unserialize_data;
 typedef struct _zend_serialize_data zend_serialize_data;
 typedef struct _zend_unserialize_data zend_unserialize_data;
 
+struct _zend_trait_method_reference {
+       char* method_name;
+       unsigned int mname_len;
+       
+       zend_class_entry *ce;
+       
+       char* class_name;
+       unsigned int cname_len;
+};
+typedef struct _zend_trait_method_reference    zend_trait_method_reference;
+
+struct _zend_trait_precedence {
+       zend_trait_method_reference *trait_method;
+       
+       zend_class_entry** exclude_from_classes;
+       
+       union _zend_function* function;
+};
+typedef struct _zend_trait_precedence zend_trait_precedence;
+
+struct _zend_trait_alias {
+       zend_trait_method_reference *trait_method;
+       
+       /**
+       * name for method to be added
+       */
+       char* alias;
+       unsigned int alias_len;
+       
+       /**
+       * modifiers to be set on trait method
+       */
+       zend_uint modifiers;
+       
+       union _zend_function* function;
+};
+typedef struct _zend_trait_alias zend_trait_alias;
+
 struct _zend_class_entry {
        char type;
        char *name;
@@ -464,6 +502,11 @@ struct _zend_class_entry {
 
        zend_class_entry **interfaces;
        zend_uint num_interfaces;
+       
+       zend_class_entry **traits;
+       zend_uint num_traits;
+       zend_trait_alias **trait_aliases;
+       zend_trait_precedence **trait_precedences;
 
        char *filename;
        zend_uint line_start;
index 9909643795e27674d23b04f9e3d2ff98d63d8023..9077b278e76396a14bddf2ad9636ef095a322598 100644 (file)
@@ -2851,20 +2851,11 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
 }
 /* }}} */
 
-static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
+static void do_inheritance_check_on_method(zend_function *child, zend_function *parent)
 {
        zend_uint child_flags;
-       zend_uint parent_flags = parent->common.fn_flags;
-       zend_function *child;
-       TSRMLS_FETCH();
-
-       if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
-               if (parent_flags & (ZEND_ACC_ABSTRACT)) {
-                       child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
-               }
-               return 1; /* method doesn't exist in child, copy from parent */
-       }
-
+    zend_uint parent_flags = parent->common.fn_flags;
+       
        if (parent->common.fn_flags & ZEND_ACC_ABSTRACT
                && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
                && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
@@ -2926,7 +2917,23 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
                        zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(parent), parent->common.function_name);
                }
        }
+}
+
+static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
+{
+       zend_uint parent_flags = parent->common.fn_flags;
+       zend_function *child;
+       TSRMLS_FETCH();
 
+       if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
+               if (parent_flags & (ZEND_ACC_ABSTRACT)) {
+                       child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
+               }
+               return 1; /* method doesn't exist in child, copy from parent */
+       }
+       
+       do_inheritance_check_on_method(child, parent);
+       
        return 0;
 }
 /* }}} */
@@ -3111,7 +3118,8 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
 
        if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
                ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
-       } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)) {
+       } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)
+                               && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
                /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
                zend_verify_abstract_class(ce TSRMLS_CC);
        }
@@ -3182,6 +3190,537 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
 }
 /* }}} */
 
+ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
+{
+       zend_uint i, ignore = 0;
+       zend_uint current_trait_num = ce->num_traits;
+       zend_uint parent_trait_num  = ce->parent ? ce->parent->num_traits : 0;
+
+       for (i = 0; i < ce->num_traits; i++) {
+               if (ce->traits[i] == NULL) {
+                       memmove(ce->traits + i, ce->traits + i + 1, sizeof(zend_class_entry*) * (--ce->num_traits - i));
+                       i--;
+               } else if (ce->traits[i] == trait) {
+                       if (i < parent_trait_num) {
+                               ignore = 1;
+                       }
+               }
+       }
+       if (!ignore) {
+               if (ce->num_traits >= current_trait_num) {
+                       if (ce->type == ZEND_INTERNAL_CLASS) {
+                               ce->traits = (zend_class_entry **) realloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
+                       } else {
+                               ce->traits = (zend_class_entry **) erealloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
+                       }
+               }
+               ce->traits[ce->num_traits++] = trait;
+       }
+}
+/* }}} */
+
+static int _merge_functions(zend_function *fn, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+       size_t current;
+       size_t i;
+       size_t count;
+       HashTable* resulting_table;
+       HashTable** function_tables;
+       zend_class_entry *ce;
+       //zstr lcname;
+       size_t collision = 0;
+       size_t abstract_solved = 0;
+       //unsigned int name_len;
+       zend_function* other_trait_fn;
+
+       current                 = va_arg(args, size_t);  // index of current trait
+       count                   = va_arg(args, size_t);
+       resulting_table = va_arg(args, HashTable*);
+       function_tables = va_arg(args, HashTable**);
+       ce                              = va_arg(args, zend_class_entry*);
+
+       for (i = 0; i < count; i++) {
+               if (i == current) {
+                       continue; // just skip this, cause its the table this function is applied on
+               }
+
+               if (zend_hash_find(function_tables[i], hash_key->arKey, hash_key->nKeyLength, &other_trait_fn) == SUCCESS) {
+                       // if it is an abstract method, there is no collision
+                       if (other_trait_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+                               // we can savely free and remove it from other table
+                               zend_function_dtor(other_trait_fn);
+                               zend_hash_del(function_tables[i], hash_key->arKey, hash_key->nKeyLength);
+                       } else {
+                               // if it is not an abstract method, there is still no collision
+                               // iff fn is an abstract method
+                               if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+                                       // just mark as solved, will be added if its own trait is processed
+                                       abstract_solved = 1;
+                               } else {
+                                       // but else, we have a collision of non-abstract methods
+                                       collision++;
+                                       zend_function_dtor(other_trait_fn);
+                                       zend_hash_del(function_tables[i], hash_key->arKey, hash_key->nKeyLength);
+                               }
+                       }
+               }
+       }
+
+       if (collision) {
+               zend_function* class_fn;
+               // make sure method is not already overridden in class
+
+               if (zend_hash_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, &class_fn) == FAILURE
+                       || class_fn->common.scope != ce) {
+                               zend_error(E_WARNING, "Trait method %s has not been applied, because there are collisions with other trait methods on %s",
+                   fn->common.function_name, ce->name);
+               }
+
+               zend_function_dtor(fn);
+       } else if (abstract_solved) {
+               zend_function_dtor(fn);
+       } else {
+               // Add it to result function table
+               if (zend_hash_add(resulting_table, hash_key->arKey, hash_key->nKeyLength,
+                      fn, sizeof(zend_function), NULL)==FAILURE) {
+                       zend_error(E_ERROR, "Trait method %s has not been applied, because failure occured during updating resulting trait method table.",
+                 fn->common.function_name);
+               }
+       }
+
+       //efree(lcname.v);
+       return ZEND_HASH_APPLY_REMOVE;
+}
+/* }}} */
+
+#define IS_EQUAL(mname, mname_len, str) \
+      strncmp(mname, str, mname_len)
+
+#define _ADD_MAGIC_METHOD(ce, mname, mname_len, fe) { \
+       if (IS_EQUAL(mname, mname_len, "__clone"))      {       (ce)->clone                     = (fe); (fe)->common.fn_flags = ZEND_ACC_CLONE; } \
+       else if (IS_EQUAL(mname, mname_len, "__get"))           (ce)->__get                     = (fe); \
+       else if (IS_EQUAL(mname, mname_len, "__set"))           (ce)->__set                     = (fe); \
+       else if (IS_EQUAL(mname, mname_len, "__call"))          (ce)->__call            = (fe); \
+       else if (IS_EQUAL(mname, mname_len, "__unset"))         (ce)->__unset           = (fe); \
+       else if (IS_EQUAL(mname, mname_len, "__isset"))         (ce)->__isset           = (fe); \
+       else if (IS_EQUAL(mname, mname_len, "__callstatic"))(ce)->__callstatic  = (fe); \
+       else if (IS_EQUAL(mname, mname_len, "__tostring"))      (ce)->__tostring        = (fe); \
+       else if (IS_EQUAL(mname, mname_len, "serialize_func"))  (ce)->serialize_func    = (fe); \
+       else if (IS_EQUAL(mname, mname_len, "unserialize_func"))(ce)->unserialize_func  = (fe); \
+}
+
+/* {{{ php_runkit_function_copy_ctor
+       Duplicate structures in an op_array where necessary to make an outright duplicate */
+void php_runkit_function_copy_ctor(zend_function *fe, char *newname)
+{
+       zend_compiled_variable *dupvars;
+       zend_op *opcode_copy;
+       int i;
+
+       if (fe->op_array.static_variables) {
+               HashTable *tmpHash;
+               zval tmpZval;
+
+               ALLOC_HASHTABLE(tmpHash);
+               zend_hash_init(tmpHash, 2, NULL, ZVAL_PTR_DTOR, 0);
+               zend_hash_copy(tmpHash, fe->op_array.static_variables, ZVAL_COPY_CTOR, &tmpZval, sizeof(zval));
+               fe->op_array.static_variables = tmpHash;
+       }
+
+       fe->op_array.refcount = emalloc(sizeof(zend_uint));
+       *(fe->op_array.refcount) = 1;
+
+       i = fe->op_array.last_var;
+       dupvars = safe_emalloc(fe->op_array.last_var, sizeof(zend_compiled_variable), 0);
+       while (i > 0) {
+               i--;
+               dupvars[i].name = estrndup(fe->op_array.vars[i].name, fe->op_array.vars[i].name_len);
+               dupvars[i].name_len = fe->op_array.vars[i].name_len;
+               dupvars[i].hash_value = fe->op_array.vars[i].hash_value;
+       }
+       fe->op_array.vars = dupvars;
+
+       opcode_copy = safe_emalloc(sizeof(zend_op), fe->op_array.last, 0);
+       for(i = 0; i < fe->op_array.last; i++) {
+               opcode_copy[i] = fe->op_array.opcodes[i];
+               if (opcode_copy[i].op1_type == IS_CONST) {
+                       zval_copy_ctor(&opcode_copy[i].op1.constant);
+               } else {
+                       if (opcode_copy[i].op1.jmp_addr >= fe->op_array.opcodes &&
+                               opcode_copy[i].op1.jmp_addr <  fe->op_array.opcodes + fe->op_array.last) {
+                               opcode_copy[i].op1.jmp_addr =  opcode_copy + (fe->op_array.opcodes[i].op1.jmp_addr - fe->op_array.opcodes);
+                       }
+        }
+
+               if (opcode_copy[i].op2_type == IS_CONST) {
+                       zval_copy_ctor(&opcode_copy[i].op2.constant);
+               } else {
+                       if (opcode_copy[i].op2.jmp_addr >= fe->op_array.opcodes &&
+                               opcode_copy[i].op2.jmp_addr <  fe->op_array.opcodes + fe->op_array.last) {
+                               opcode_copy[i].op2.jmp_addr =  opcode_copy + (fe->op_array.opcodes[i].op2.jmp_addr - fe->op_array.opcodes);
+                       }
+               }
+       }
+       fe->op_array.opcodes = opcode_copy;
+       fe->op_array.start_op = fe->op_array.opcodes;
+       fe->op_array.function_name = newname;
+
+       //fe->op_array.prototype = fe->op_array.prototype;  //was setting it to fe which does not work since fe is stack allocated and not a stable address
+
+       if (fe->op_array.arg_info) {
+               zend_arg_info *tmpArginfo;
+
+               tmpArginfo = safe_emalloc(sizeof(zend_arg_info), fe->op_array.num_args, 0);
+               for(i = 0; i < fe->op_array.num_args; i++) {
+                       tmpArginfo[i] = fe->op_array.arg_info[i];
+
+                       tmpArginfo[i].name = estrndup(tmpArginfo[i].name, tmpArginfo[i].name_len);
+                       if (tmpArginfo[i].class_name) {
+                               tmpArginfo[i].class_name = estrndup(tmpArginfo[i].class_name, tmpArginfo[i].class_name_len);
+                       }
+               }
+               fe->op_array.arg_info = tmpArginfo;
+       }
+
+       fe->op_array.doc_comment = estrndup(fe->op_array.doc_comment,
+                                      fe->op_array.doc_comment_len);
+       fe->op_array.try_catch_array = (zend_try_catch_element*)estrndup((char*)fe->op_array.try_catch_array, sizeof(zend_try_catch_element) * fe->op_array.last_try_catch);
+
+       fe->op_array.brk_cont_array = (zend_brk_cont_element*)estrndup((char*)fe->op_array.brk_cont_array, sizeof(zend_brk_cont_element) * fe->op_array.last_brk_cont);
+  
+  // TODO: check whether there is something similar and whether that is ok
+  zend_literal* literals_copy = (zend_literal*)emalloc(fe->op_array.size_literal * sizeof(zend_literal));
+  
+  for (i = 0; i < fe->op_array.size_literal; i++) {
+    literals_copy[i] = fe->op_array.literals[i];
+  }
+  fe->op_array.literals = literals_copy;
+}
+/* }}}} */
+
+static int _merge_functions_to_class(zend_function *fn, int num_args, va_list args, zend_hash_key *hash_key TSRMLS_DC)
+{
+       zend_class_entry *ce = va_arg(args, zend_class_entry*);
+       int add = 0;
+       zend_function* existing_fn;
+       zend_function* prototype = NULL;                // is used to determine the prototype according to the inheritance chain
+
+       if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &existing_fn) == FAILURE) {
+               add = 1; // not found
+       } else if (existing_fn->common.scope != ce) {
+               add = 1; // or inherited from other class or interface
+               // prototype = existing_fn;  // it is just a reference which was added to the subclass while doing the inheritance
+               // function_add_ref(prototype);  //memory is scrambled anyway????
+               zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h);
+       }
+
+       if (add) {
+               zend_function* parent_function;
+               if (ce->parent && zend_hash_quick_find(&ce->parent->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &parent_function) != FAILURE) {
+                       prototype = parent_function; //->common.fn_flags |= ZEND_ACC_ABSTRACT;
+               }
+
+               fn->common.scope = ce;
+               fn->common.prototype = prototype;
+
+               if (prototype
+                       && (prototype->common.fn_flags & ZEND_ACC_IMPLEMENTED_ABSTRACT
+                               || prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
+                       fn->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
+               }
+               else // remove ZEND_ACC_IMPLEMENTED_ABSTRACT flag, think it shouldn't be copied to class
+               if (fn->common.fn_flags & ZEND_ACC_IMPLEMENTED_ABSTRACT) {
+                       fn->common.fn_flags = fn->common.fn_flags - ZEND_ACC_IMPLEMENTED_ABSTRACT;
+               }
+
+               // check whether the trait method fullfills the inheritance requirements
+               if (prototype) {
+                       do_inheritance_check_on_method(fn, prototype);
+               }
+
+               if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
+                       ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
+               }
+
+               if (zend_hash_update(&ce->function_table, hash_key->arKey, hash_key->nKeyLength,
+                      fn, sizeof(zend_function), NULL)==FAILURE) {
+                       zend_error(E_ERROR, "Trait method %s has not been applied, because failure occured during updating class method table.", hash_key->arKey);
+               }
+
+               _ADD_MAGIC_METHOD(ce, hash_key->arKey, hash_key->nKeyLength, fn);
+               //it could be necessary to update child classes as well
+               //zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t)php_runkit_update_children_methods, 5, dce, dce, &dfe, dfunc, dfunc_len);
+       } else {
+               zend_function_dtor(fn);
+               //efree(fn);
+       }
+
+       //efree(lcname.v);
+       return ZEND_HASH_APPLY_REMOVE;
+}
+
+static int _copy_functions(zend_function *fn, int num_args, va_list args, zend_hash_key *hash_key)
+{
+       HashTable* target;
+       zend_trait_alias** aliases;
+       HashTable* exclude_table;
+       char* lcname;
+       unsigned int lcname_len;
+       unsigned int fnname_len;
+       zend_function fn_copy;
+
+       size_t i = 0;
+       target = va_arg(args, HashTable*);
+       aliases = va_arg(args, zend_trait_alias**);
+       exclude_table = va_arg(args, HashTable*);
+
+       fnname_len = strlen(fn->common.function_name);
+
+       // apply aliases which are qualified with a class name, there should not be any ambiguatty
+       if (aliases) {
+               while (aliases[i]) {
+                       if (fn->common.scope == aliases[i]->trait_method->ce &&
+                               (zend_binary_strcasecmp(aliases[i]->trait_method->method_name,
+                                 aliases[i]->trait_method->mname_len,
+                                 fn->common.function_name, fnname_len) == 0)) {
+                               if (aliases[i]->alias) {
+                                       fn_copy = *fn;
+                                       php_runkit_function_copy_ctor(&fn_copy, estrndup(aliases[i]->alias, aliases[i]->alias_len));
+
+                                       if (aliases[i]->modifiers) { // if it is 0, no modifieres has been changed
+                                               fn_copy.common.fn_flags = aliases[i]->modifiers;
+                                               if (!(aliases[i]->modifiers & ZEND_ACC_PPP_MASK)) {
+                                                       fn_copy.common.fn_flags |= ZEND_ACC_PUBLIC;
+                                               }
+                                       }
+
+                                       lcname_len = aliases[i]->alias_len;
+                                       lcname = zend_str_tolower_dup(aliases[i]->alias, lcname_len);
+
+                                       if (zend_hash_add(target, lcname, lcname_len+1, &fn_copy, sizeof(zend_function), NULL)==FAILURE) {
+                                               zend_error(E_ERROR, "Failed to added aliased trait method (%s) to trait table. Propably there is already a trait method with same name\n",
+                       fn_copy.common.function_name);
+                                       }
+                                       //aliases[i]->function = fn_copy;
+                                       efree(lcname);
+                               }
+                       }
+                       i++;
+               }
+       }
+
+       lcname_len = strlen(fn->common.function_name);
+       lcname = zend_str_tolower_dup(fn->common.function_name, fnname_len);
+       void* dummy;
+       if (zend_hash_find(exclude_table, lcname, lcname_len, &dummy) == FAILURE) {
+               // is not in hashtable, thus, function is not to be excluded
+               fn_copy = *fn;
+               php_runkit_function_copy_ctor(&fn_copy, estrndup(fn->common.function_name, fnname_len));
+
+               // apply aliases which are not qualified by a class name, or which have not alias name, just setting visibility
+               // TODO: i am still not sure, that there will be no ambigousities...
+
+               if (aliases) {
+                       i = 0;
+                       while (aliases[i]) {
+                               if ((!aliases[i]->trait_method->ce || fn->common.scope == aliases[i]->trait_method->ce) &&
+                                       (zend_binary_strcasecmp(aliases[i]->trait_method->method_name,
+                                   aliases[i]->trait_method->mname_len,
+                                   fn->common.function_name, fnname_len) == 0)) {
+                                       if (aliases[i]->alias) {
+                                               zend_function fn_copy2 = *fn;
+                                               php_runkit_function_copy_ctor(&fn_copy2, estrndup(aliases[i]->alias, aliases[i]->alias_len));
+
+                                               if (aliases[i]->modifiers) { // if it is 0, no modifieres has been changed
+                                                       fn_copy2.common.fn_flags = aliases[i]->modifiers;
+                                                       if (!(aliases[i]->modifiers & ZEND_ACC_PPP_MASK)) {
+                                                               fn_copy2.common.fn_flags |= ZEND_ACC_PUBLIC;
+                                                       }
+                                               }
+
+                                               zend_uint lcname2_len = aliases[i]->alias_len;
+                                               char* lcname2 = zend_str_tolower_dup(aliases[i]->alias, lcname2_len);
+
+                                               if (zend_hash_add(target, lcname2, lcname2_len+1, &fn_copy2, sizeof(zend_function), NULL)==FAILURE) {
+                                                       zend_error(E_ERROR, "Failed to added aliased trait method (%s) to trait table. Propably there is already a trait method with same name\n",
+                         fn_copy2.common.function_name);
+                                               }
+                                               efree(lcname2);
+                                       } else {
+                                               if (aliases[i]->modifiers) { // if it is 0, no modifieres has been changed
+                                                       fn_copy.common.fn_flags = aliases[i]->modifiers;
+                                                       if (!(aliases[i]->modifiers & ZEND_ACC_PPP_MASK)) {
+                                                               fn_copy.common.fn_flags |= ZEND_ACC_PUBLIC;
+                                                       }
+                                               }
+                                       }
+                               }
+                               i++;
+                       }
+               }
+
+
+               if (zend_hash_add(target, lcname, lcname_len+1, &fn_copy, sizeof(zend_function), NULL)==FAILURE) {
+                       zend_error(E_ERROR, "Failed to added trait method (%s) to trait table. Propably there is already a trait method with same name\n",
+                 fn_copy.common.function_name);
+               }
+       }
+
+       efree(lcname);
+
+       return ZEND_HASH_APPLY_KEEP;
+}
+
+/**
+* Copies function table entries to target function table with applied aliasing
+*/
+void copy_trait_function_table(HashTable *target, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table) {
+       zend_hash_apply_with_arguments(source, (apply_func_args_t)_copy_functions, 3, //3 is number of args for apply_func
+                       target, aliases, exclude_table);
+}
+
+void init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+{
+       size_t i, j = 0;
+       zend_trait_precedence *cur_precedence;
+       zend_trait_method_reference *cur_method_ref;
+       zend_class_entry *cur_ce;
+
+       // resolve class references
+
+       if (ce->trait_precedences) {
+               i = 0;
+               while ((cur_precedence = ce->trait_precedences[i])) {
+                       cur_ce = zend_fetch_class(cur_precedence->trait_method->class_name, cur_precedence->trait_method->cname_len, ZEND_FETCH_CLASS_TRAIT TSRMLS_CC);
+                       cur_precedence->trait_method->ce = cur_ce;
+
+                       if (cur_precedence->exclude_from_classes) {
+                               j = 0;
+                               while (cur_precedence->exclude_from_classes[j]) {
+                                       char* class_name = (char*)cur_precedence->exclude_from_classes[j];
+          zend_uint name_length = strlen(class_name);
+                                       cur_ce = zend_fetch_class(class_name, name_length, ZEND_FETCH_CLASS_TRAIT TSRMLS_CC);
+                                       efree(class_name);
+                                       cur_precedence->exclude_from_classes[j] = cur_ce;
+                                       j++;
+                               }
+                       }
+                       i++;
+               }
+       }
+
+       if (ce->trait_aliases) {
+               i = 0;
+               while (ce->trait_aliases[i]) {
+                       cur_method_ref = ce->trait_aliases[i]->trait_method;
+                       if (cur_method_ref->class_name) {
+                               cur_method_ref->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len, ZEND_FETCH_CLASS_TRAIT TSRMLS_CC);
+                       }
+                       i++;
+               }
+       }
+}
+/* }}} */
+
+void compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait) {
+       size_t i, j;
+       if (precedences) {
+               i = 0;
+               while (precedences[i]) {
+                       if (precedences[i]->exclude_from_classes) {
+                               j = 0;
+                               while (precedences[i]->exclude_from_classes[j]) {
+                                       if (precedences[i]->exclude_from_classes[j] == trait) {
+                                               zend_uint lcname_len = precedences[i]->trait_method->mname_len;
+                                               char* lcname = zend_str_tolower_dup(precedences[i]->trait_method->method_name,
+                                                lcname_len);
+                                               if (zend_hash_add(exclude_table, lcname, lcname_len, NULL, 0, NULL)==FAILURE) {
+                                                       zend_error(E_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times.\n",
+                         precedences[i]->trait_method->method_name, trait->name);
+                                               }
+                                               efree(lcname);
+                                       }
+                                       j++;
+                               }
+                       }
+                       i++;
+               }
+       }
+}
+
+ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+{
+       HashTable** function_tables;
+       HashTable* resulting_table;
+       HashTable exclude_table;
+       size_t i;
+
+       if (ce->num_traits <= 0) { return; }
+
+//     zend_error(E_NOTICE, "Do bind Traits on %v with %d traits.\n Class has already %d methods.\n",
+//                        ce->name.s, ce->num_traits, ce->function_table.nNumOfElements);
+
+       // complete initialization of trait strutures in ce
+       init_trait_structures(ce);
+
+       // prepare copies of trait function tables for combination
+       function_tables = malloc(sizeof(HashTable*) * ce->num_traits);
+       resulting_table = (HashTable *) malloc(sizeof(HashTable));
+       zend_hash_init_ex(resulting_table, 10, // TODO: revisit this start size, may be its not optimal
+                                                 //NULL, ZEND_FUNCTION_DTOR, 0, 0);
+                                                 NULL, NULL, 0, 0);
+
+       for (i = 0; i < ce->num_traits; i++) {
+               function_tables[i] = (HashTable *) malloc(sizeof(HashTable));
+       zend_hash_init_ex(function_tables[i], ce->traits[i]->function_table.nNumOfElements,
+                                                 //NULL, ZEND_FUNCTION_DTOR, 0, 0);
+                                                 NULL, NULL, 0, 0);
+
+               zend_hash_init_ex(&exclude_table, 2, // TODO: revisit this start size, may be its not optimal
+                                                       NULL, NULL, 0, 0);
+               compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
+
+               // copies functions, applies defined aliasing, and excludes unused trait methods
+               copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table);
+               zend_hash_graceful_destroy(&exclude_table);
+       }
+
+       // now merge trait methods
+       for (i = 0; i < ce->num_traits; i++) {
+               zend_hash_apply_with_arguments(function_tables[i], (apply_func_args_t)_merge_functions, 5, //5 is number of args for apply_func
+                                               i, ce->num_traits, resulting_table, function_tables, ce);
+       }
+
+       // now the resulting_table contains all trait methods we would have to
+       // add to the class
+       // in the following step the methods are inserted into the method table
+       // if there is already a method with the same name it is replaced iff ce != fn.scope
+       // --> all inherited methods are overridden, methods defined in the class are leaved
+       // untouched
+       zend_hash_apply_with_arguments(resulting_table, (apply_func_args_t)_merge_functions_to_class, 1, ce TSRMLS_CC);
+
+       // free temporary function tables
+       for (i = 0; i < ce->num_traits; i++) {
+               //zend_hash_destroy(function_tables[i]); //
+               zend_hash_graceful_destroy(function_tables[i]);
+               free(function_tables[i]);
+       }
+       free(function_tables);
+
+       // free temporary resulting table
+       //zend_hash_destroy(resulting_table); //
+       zend_hash_graceful_destroy(resulting_table);
+       free(resulting_table);
+
+       zend_verify_abstract_class(ce TSRMLS_CC);
+       // now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed
+       if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
+               ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
+       }
+}
+/* }}} */
+
+
 ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
 {
        zend_function *function;
@@ -3219,6 +3758,96 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, Ha
 }
 /* }}} */
 
+
+void zend_add_trait_precedence(znode *precedence_znode TSRMLS_DC) /* {{{ */
+{
+       zend_class_entry *ce = CG(active_class_entry);
+       zend_add_to_list(&ce->trait_precedences,precedence_znode->u.op.ptr);
+}
+/* }}} */
+
+void zend_add_trait_alias(znode *alias_znode TSRMLS_DC) /* {{{ */
+{
+       zend_class_entry *ce = CG(active_class_entry);
+       zend_add_to_list(&ce->trait_aliases, alias_znode->u.op.ptr);
+}
+/* }}} */
+
+void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
+{
+       zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
+       method_ref->ce = NULL;
+
+       // REM: There should not be a need for copying, 
+  //      zend_do_begin_class_declaration is also just using that string
+       if (class_name) {
+               method_ref->class_name = Z_STRVAL(class_name->u.constant);
+               method_ref->cname_len  = Z_STRLEN(class_name->u.constant);
+       } else {
+               method_ref->class_name = NULL;
+               method_ref->cname_len  = 0;
+       }
+
+       method_ref->method_name = Z_STRVAL(method_name->u.constant);
+       method_ref->mname_len   = Z_STRLEN(method_name->u.constant);
+
+       result->u.op.ptr = method_ref;
+  result->op_type = IS_TMP_VAR;
+}
+/* }}} */
+
+
+void zend_prepare_trait_alias(znode *result, znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC) /* {{{ */
+{
+       zend_trait_alias *trait_alias = emalloc(sizeof(zend_trait_alias));
+
+       trait_alias->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
+       trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
+
+       if (alias) {
+               trait_alias->alias = Z_STRVAL(alias->u.constant);
+               trait_alias->alias_len = Z_STRLEN(alias->u.constant);
+       } else {
+               trait_alias->alias = NULL;
+       }
+       trait_alias->function = NULL;
+
+       result->u.op.ptr = trait_alias;
+}
+/* }}} */
+
+//void init_trait_alias(znode* result, const znode* method_name, const znode* alias, const znode* modifiers TSRMLS_DC) /* {{{ */
+/*{
+       zend_trait_alias* trait_alias = emalloc(sizeof(zend_trait_alias));
+       trait_alias->method_name = Z_UNIVAL(method_name->u.constant);
+
+       // may be method is only excluded, then the alias node is NULL
+       if (alias) {
+               trait_alias->alias = Z_UNIVAL(alias->u.constant);
+               trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
+       } else {
+
+       }
+       trait_alias->function = NULL;
+
+
+       result->u.var = trait_alias;
+}
+/* }}} */
+
+void zend_prepare_trait_precedence(znode *result, znode *method_reference, znode *trait_list TSRMLS_DC) /* {{{ */
+{
+       zend_trait_precedence *trait_precedence = emalloc(sizeof(zend_trait_precedence));
+
+       trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
+       trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr;
+
+       trait_precedence->function = NULL;
+
+       result->u.op.ptr = trait_precedence;
+}
+/* }}} */
+
 ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
 {
        zend_class_entry *ce, **pce;
@@ -3361,7 +3990,10 @@ void zend_do_early_binding(TSRMLS_D) /* {{{ */
                        }
                case ZEND_VERIFY_ABSTRACT_CLASS:
                case ZEND_ADD_INTERFACE:
+               case ZEND_ADD_TRAIT:
+               case ZEND_BIND_TRAITS:
                        /* We currently don't early-bind classes that implement interfaces */
+                       /* Classes with traits are handled exactly the same, no early-bind here */
                        return;
                default:
                        zend_error(E_COMPILE_ERROR, "Invalid binding type");
@@ -3802,6 +4434,22 @@ void zend_do_end_class_declaration(const znode *class_token, const znode *parent
                ce->num_interfaces = 0;
                ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
        }
+
+       /* Check for traits and proceed like with interfaces.
+        * The only difference will be a combined handling of them in the end.
+        * Thus, we need another opcode here. */
+       if (ce->num_traits > 0) {
+               ce->traits = NULL;
+               ce->num_traits = 0;
+               ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
+
+               // opcode generation:
+               zend_op *opline;
+               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+               opline->opcode = ZEND_BIND_TRAITS;
+    SET_NODE(opline->op1, &CG(implementing_class));
+       }
+
        CG(active_class_entry) = NULL;
 }
 /* }}} */
@@ -3810,6 +4458,13 @@ void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
 {
        zend_op *opline;
 
+       // Traits can not implement interfaces
+       if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
+               zend_error(E_COMPILE_ERROR, "Cannot use '%s' as interface on '%s' since it is a Trait",
+               Z_STRVAL(interface_name->u.constant),
+               CG(active_class_entry)->name);
+       }
+
        switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
                case ZEND_FETCH_CLASS_SELF:
                case ZEND_FETCH_CLASS_PARENT:
@@ -3831,6 +4486,30 @@ void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
 }
 /* }}} */
 
+void zend_do_implements_trait(znode *trait_name TSRMLS_DC) /* {{{ */
+{
+       zend_op *opline;
+
+       switch (zend_get_class_fetch_type(Z_STRVAL(trait_name->u.constant), Z_STRLEN(trait_name->u.constant))) {
+               case ZEND_FETCH_CLASS_SELF:
+               case ZEND_FETCH_CLASS_PARENT:
+               case ZEND_FETCH_CLASS_STATIC:
+                       zend_error(E_COMPILE_ERROR, "Cannot use '%s' as trait name as it is reserved", Z_STRVAL(trait_name->u.constant));
+                       break;
+               default:
+                       break;
+       }
+
+       opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+       opline->opcode = ZEND_ADD_TRAIT;
+  SET_NODE(opline->op1, &CG(implementing_class));
+       zend_resolve_class_name(trait_name, &opline->extended_value, 0 TSRMLS_CC);
+       opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_TRAIT;
+       SET_NODE(opline->op2, trait_name);
+       CG(active_class_entry)->num_traits++;
+}
+/* }}} */
+
 ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal) /* {{{ */
 {
        char *prop_name;
@@ -4476,6 +5155,33 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) /* {{{ */
 }
 /* }}} */
 
+void zend_init_list(void *result, void *item TSRMLS_DC) /* {{{ */
+{
+       void** list = emalloc(sizeof(void*) * 2);
+
+       list[0] = item;
+       list[1] = NULL;
+
+       *(void**)result = list;
+}
+/* }}} */
+
+void zend_add_to_list(void *result, void *item TSRMLS_DC) /* {{{ */
+{
+       void** list = *(void**)result;
+       size_t n = 0;
+
+       while (list && list[n]) { n++; }
+
+       list = erealloc(list, sizeof(void*) * (n+2));
+
+       list[n]   = item;
+       list[n+1] = NULL;
+
+       *(void**)result = list;
+}
+/* }}} */
+
 void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
 {
        zval *tmp;
@@ -5303,6 +6009,10 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
                ce->parent = NULL;
                ce->num_interfaces = 0;
                ce->interfaces = NULL;
+               ce->num_traits = 0;
+               ce->traits = NULL;
+               ce->trait_aliases = NULL;
+               ce->trait_precedences = NULL;
                ce->module = NULL;
                ce->serialize = NULL;
                ce->unserialize = NULL;
index eda42ab76752c26135781cccb9ca9bacc9bdea5f..8744de08b8f5c6086142e56b5caf2d4deef11e36 100644 (file)
@@ -69,6 +69,7 @@ typedef union _znode_op {
        zend_op       *jmp_addr;
        zval          *zv;
        zend_literal  *literal;
+  void          *ptr;        /* Used for passing pointers from the compile to execution phase, currently used for traits */
 } znode_op;
 
 typedef struct _znode { /* used only during compilation */ 
@@ -136,6 +137,7 @@ typedef struct _zend_try_catch_element {
 #define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS       0x20
 #define ZEND_ACC_FINAL_CLASS               0x40
 #define ZEND_ACC_INTERFACE                         0x80
+#define ZEND_ACC_TRAIT                                         0x120
 
 /* op_array flags */
 #define ZEND_ACC_INTERACTIVE                           0x10
@@ -166,6 +168,7 @@ typedef struct _zend_try_catch_element {
 
 /* class implement interface(s) flag */
 #define ZEND_ACC_IMPLEMENT_INTERFACES 0x80000
+#define ZEND_ACC_IMPLEMENT_TRAITS        0x400000
 
 #define ZEND_ACC_CLOSURE              0x100000
 
@@ -466,6 +469,24 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_
 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC);
 void zend_do_implements_interface(znode *interface_znode TSRMLS_DC);
 
+/* Trait related functions */
+void zend_add_trait_precedence(znode *precedence_znode TSRMLS_DC);
+void zend_add_trait_alias(znode *alias_znode TSRMLS_DC);
+
+
+void zend_do_implements_trait(znode *interface_znode /*, znode* aliases */ TSRMLS_DC);
+ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC);
+ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC);
+//void zend_do_binds_traits(TSRMLS_D);
+//ZEND_API void zend_do_add_trait_preparative_to_class(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC);
+void zend_prepare_trait_precedence(znode *result, znode *method_reference, znode *trait_list TSRMLS_DC);
+void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC);
+void zend_prepare_trait_alias(znode *result, znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC);
+
+void init_trait_alias_list(znode* result, const znode* trait_alias TSRMLS_DC);
+void add_trait_alias(znode* result, const znode* trait_alias TSRMLS_DC);
+void init_trait_alias(znode* result, const znode* method_name, const znode* alias, const znode* modifiers TSRMLS_DC);
+
 ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC);
 void zend_do_early_binding(TSRMLS_D);
 ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC);
@@ -515,6 +536,11 @@ void zend_do_add_list_element(const znode *element TSRMLS_DC);
 void zend_do_new_list_begin(TSRMLS_D);
 void zend_do_new_list_end(TSRMLS_D);
 
+/* Functions for a null terminated pointer list, used for traits parsing and compilation */
+void zend_init_list(void *result, void *item TSRMLS_DC);
+void zend_add_to_list(void *result, void *item TSRMLS_DC);
+
+
 void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC);
 void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC);
 
@@ -643,6 +669,7 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv);
 #define ZEND_FETCH_CLASS_AUTO          5
 #define ZEND_FETCH_CLASS_INTERFACE     6
 #define ZEND_FETCH_CLASS_STATIC                7
+#define ZEND_FETCH_CLASS_TRAIT         14
 #define ZEND_FETCH_CLASS_MASK        0x0f
 #define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
 #define ZEND_FETCH_CLASS_SILENT      0x0100
index 5203f4fe86d4d1e9c8c56189a0cacf1b04463892..b773a22c5b6e6a0f439211462ecc8249dfafe7b4 100644 (file)
@@ -1561,7 +1561,9 @@ check_fetch_type:
                        if (!silent && !EG(exception)) {
                                if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
                                        zend_error(E_ERROR, "Interface '%s' not found", class_name);
-                               } else {
+                               } else if (fetch_type == ZEND_FETCH_CLASS_TRAIT) {
+                       zend_error(E_ERROR, "Trait '%s' not found", class_name);
+                } else {
                                        zend_error(E_ERROR, "Class '%s' not found", class_name);
                                }       
                        }
index 2c9513182ac3cc6070fac08733b0ccccafeab7e5..5af8bbcdbb1b49e28d50047b75951ab6964ea5e3 100644 (file)
 %token T_CATCH
 %token T_THROW
 %token T_USE
+%token T_INSTEADOF
 %token T_GLOBAL
 %right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
 %token T_VAR
 %token T_EMPTY
 %token T_HALT_COMPILER
 %token T_CLASS
+%token T_TRAIT
 %token T_INTERFACE
 %token T_EXTENDS
 %token T_IMPLEMENTS
@@ -329,6 +331,7 @@ unticked_class_declaration_statement:
 class_entry_type:
                T_CLASS                 { $$.u.op.opline_num = CG(zend_lineno); $$.EA = 0; }
        |       T_ABSTRACT T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; }
+       |       T_TRAIT { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_TRAIT; }
        |       T_FINAL T_CLASS { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_FINAL_CLASS; }
 ;
 
@@ -514,10 +517,67 @@ class_statement_list:
 class_statement:
                variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';'
        |       class_constant_declaration ';'
+       |       trait_use_statement
        |       method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); } '('
                        parameter_list ')' method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
 ;
 
+trait_use_statement:
+               T_USE trait_list trait_adaptations
+;
+
+trait_list:
+               fully_qualified_class_name                                              { zend_do_implements_trait(&$1 TSRMLS_CC); }
+       |       trait_list ',' fully_qualified_class_name               { zend_do_implements_trait(&$3 TSRMLS_CC); }
+;
+
+trait_adaptations:
+               ';'
+       |       '{' trait_adaptation_list '}'
+;
+
+trait_adaptation_list:
+               /* empty */
+       |       non_empty_trait_adaptation_list
+;
+
+non_empty_trait_adaptation_list:
+               trait_adaptation_statement
+       |       non_empty_trait_adaptation_list trait_adaptation_statement
+;
+
+trait_adaptation_statement:
+               trait_precedence ';'                                                            { zend_add_trait_precedence(&$1 TSRMLS_CC); }
+       |       trait_alias ';'                                                                         { zend_add_trait_alias(&$1 TSRMLS_CC); }
+;
+
+trait_precedence:
+       trait_method_reference_fully_qualified T_INSTEADOF trait_reference_list { zend_prepare_trait_precedence(&$$, &$1, &$3 TSRMLS_CC); }
+;
+
+trait_reference_list:
+               fully_qualified_class_name                                                                      { zend_init_list(&$$.u.op.ptr, Z_STRVAL($1.u.constant) TSRMLS_CC); }
+       |       trait_reference_list ',' fully_qualified_class_name                     { zend_add_to_list(&$1.u.op.ptr, Z_STRVAL($3.u.constant) TSRMLS_CC); $$ = $1; }
+;
+
+trait_method_reference:
+               T_STRING                                                                                                        { zend_prepare_reference(&$$, NULL, &$1 TSRMLS_CC); }
+       |       trait_method_reference_fully_qualified                                          { $$ = $1; }
+;
+
+trait_method_reference_fully_qualified:
+       fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING              { zend_prepare_reference(&$$, &$1, &$3 TSRMLS_CC); }
+;
+
+trait_alias:
+               trait_method_reference T_AS trait_modifiers T_STRING            { zend_prepare_trait_alias(&$$, &$1, &$3, &$4 TSRMLS_CC); }
+       |       trait_method_reference T_AS member_modifier                                     { zend_prepare_trait_alias(&$$, &$1, &$3, NULL TSRMLS_CC); }
+;
+
+trait_modifiers:
+               /* empty */                                     { Z_LVAL($$.u.constant) = 0x0; } /* No change of methods visibility */
+       |       member_modifier { $$ = $1; } /* REM: Keep in mind, there are not only visibility modifiers */
+;
 
 method_body:
                ';' /* abstract method */               { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
index 4d7a283ad2ce135e076fd500d02cf31a12e3f8d5..3f4ebc12d2d1e21655cf359242434ce1ab22b67d 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Tue Apr 20 15:11:14 2010 */
+/* Generated by re2c 0.13.5 on Thu Apr 22 23:49:41 2010 */
 #line 1 "Zend/zend_language_scanner.l"
 /*
    +----------------------------------------------------------------------+
@@ -939,7 +939,7 @@ yyc_INITIAL:
 yy3:
                YYDEBUG(3, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1568 "Zend/zend_language_scanner.l"
+#line 1576 "Zend/zend_language_scanner.l"
                {
        if (YYCURSOR > YYLIMIT) {
                return 0;
@@ -1022,7 +1022,7 @@ yy5:
 yy6:
                YYDEBUG(6, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1556 "Zend/zend_language_scanner.l"
+#line 1564 "Zend/zend_language_scanner.l"
                {
        if (CG(short_tags)) {
                zendlval->value.str.val = yytext; /* no copying - intentional */
@@ -1041,7 +1041,7 @@ yy7:
                if ((yych = *YYCURSOR) == '=') goto yy43;
                YYDEBUG(8, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1533 "Zend/zend_language_scanner.l"
+#line 1541 "Zend/zend_language_scanner.l"
                {
        if (CG(asp_tags)) {
                zendlval->value.str.val = yytext; /* no copying - intentional */
@@ -1239,7 +1239,7 @@ yy35:
                ++YYCURSOR;
                YYDEBUG(38, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1489 "Zend/zend_language_scanner.l"
+#line 1497 "Zend/zend_language_scanner.l"
                {
        YYCTYPE *bracket = zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
 
@@ -1283,7 +1283,7 @@ yy43:
                ++YYCURSOR;
                YYDEBUG(44, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1507 "Zend/zend_language_scanner.l"
+#line 1515 "Zend/zend_language_scanner.l"
                {
        if (CG(asp_tags)) {
                zendlval->value.str.val = yytext; /* no copying - intentional */
@@ -1301,7 +1301,7 @@ yy45:
                ++YYCURSOR;
                YYDEBUG(46, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1520 "Zend/zend_language_scanner.l"
+#line 1528 "Zend/zend_language_scanner.l"
                {
        if (CG(short_tags)) {
                zendlval->value.str.val = yytext; /* no copying - intentional */
@@ -1340,7 +1340,7 @@ yy50:
 yy51:
                YYDEBUG(51, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1546 "Zend/zend_language_scanner.l"
+#line 1554 "Zend/zend_language_scanner.l"
                {
        zendlval->value.str.val = yytext; /* no copying - intentional */
        zendlval->value.str.len = yyleng;
@@ -1420,7 +1420,7 @@ yyc_ST_BACKQUOTE:
 yy56:
                YYDEBUG(56, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 2026 "Zend/zend_language_scanner.l"
+#line 2034 "Zend/zend_language_scanner.l"
                {
        if (YYCURSOR > YYLIMIT) {
                return 0;
@@ -1472,7 +1472,7 @@ yy58:
                ++YYCURSOR;
                YYDEBUG(59, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1970 "Zend/zend_language_scanner.l"
+#line 1978 "Zend/zend_language_scanner.l"
                {
        BEGIN(ST_IN_SCRIPTING);
        return '`';
@@ -1487,7 +1487,7 @@ yy61:
                ++YYCURSOR;
                YYDEBUG(62, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1957 "Zend/zend_language_scanner.l"
+#line 1965 "Zend/zend_language_scanner.l"
                {
        zendlval->value.lval = (long) '{';
        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
@@ -1510,7 +1510,7 @@ yy63:
 yy65:
                YYDEBUG(65, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1655 "Zend/zend_language_scanner.l"
+#line 1663 "Zend/zend_language_scanner.l"
                {
        zend_copy_value(zendlval, (yytext+1), (yyleng-1));
        zendlval->type = IS_STRING;
@@ -1522,7 +1522,7 @@ yy66:
                ++YYCURSOR;
                YYDEBUG(67, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1282 "Zend/zend_language_scanner.l"
+#line 1290 "Zend/zend_language_scanner.l"
                {
        yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
        return T_DOLLAR_OPEN_CURLY_BRACES;
@@ -1541,7 +1541,7 @@ yy70:
                ++YYCURSOR;
                YYDEBUG(71, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1647 "Zend/zend_language_scanner.l"
+#line 1655 "Zend/zend_language_scanner.l"
                {
        yyless(yyleng - 1);
        yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
@@ -1567,7 +1567,7 @@ yy73:
                ++YYCURSOR;
                YYDEBUG(74, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1637 "Zend/zend_language_scanner.l"
+#line 1645 "Zend/zend_language_scanner.l"
                {
        yyless(yyleng - 3);
        yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
@@ -1643,7 +1643,7 @@ yy77:
 yy78:
                YYDEBUG(78, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1976 "Zend/zend_language_scanner.l"
+#line 1984 "Zend/zend_language_scanner.l"
                {
        if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
                YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
@@ -1703,7 +1703,7 @@ yy80:
                ++YYCURSOR;
                YYDEBUG(81, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1965 "Zend/zend_language_scanner.l"
+#line 1973 "Zend/zend_language_scanner.l"
                {
        BEGIN(ST_IN_SCRIPTING);
        return '"';
@@ -1718,7 +1718,7 @@ yy83:
                ++YYCURSOR;
                YYDEBUG(84, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1957 "Zend/zend_language_scanner.l"
+#line 1965 "Zend/zend_language_scanner.l"
                {
        zendlval->value.lval = (long) '{';
        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
@@ -1741,7 +1741,7 @@ yy85:
 yy87:
                YYDEBUG(87, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1655 "Zend/zend_language_scanner.l"
+#line 1663 "Zend/zend_language_scanner.l"
                {
        zend_copy_value(zendlval, (yytext+1), (yyleng-1));
        zendlval->type = IS_STRING;
@@ -1753,7 +1753,7 @@ yy88:
                ++YYCURSOR;
                YYDEBUG(89, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1282 "Zend/zend_language_scanner.l"
+#line 1290 "Zend/zend_language_scanner.l"
                {
        yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
        return T_DOLLAR_OPEN_CURLY_BRACES;
@@ -1772,7 +1772,7 @@ yy92:
                ++YYCURSOR;
                YYDEBUG(93, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1647 "Zend/zend_language_scanner.l"
+#line 1655 "Zend/zend_language_scanner.l"
                {
        yyless(yyleng - 1);
        yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
@@ -1798,7 +1798,7 @@ yy95:
                ++YYCURSOR;
                YYDEBUG(96, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1637 "Zend/zend_language_scanner.l"
+#line 1645 "Zend/zend_language_scanner.l"
                {
        yyless(yyleng - 3);
        yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
@@ -1817,7 +1817,7 @@ yyc_ST_END_HEREDOC:
        ++YYCURSOR;
        YYDEBUG(100, *YYCURSOR);
        yyleng = YYCURSOR - SCNG(yy_text);
-#line 1944 "Zend/zend_language_scanner.l"
+#line 1952 "Zend/zend_language_scanner.l"
        {
        YYCURSOR += CG(heredoc_len) - 1;
        yyleng = CG(heredoc_len);
@@ -1891,7 +1891,7 @@ yy103:
 yy104:
                YYDEBUG(104, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 2068 "Zend/zend_language_scanner.l"
+#line 2076 "Zend/zend_language_scanner.l"
                {
        int newline = 0;
 
@@ -1977,7 +1977,7 @@ yy107:
                ++YYCURSOR;
                YYDEBUG(108, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1957 "Zend/zend_language_scanner.l"
+#line 1965 "Zend/zend_language_scanner.l"
                {
        zendlval->value.lval = (long) '{';
        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
@@ -2000,7 +2000,7 @@ yy109:
 yy111:
                YYDEBUG(111, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1655 "Zend/zend_language_scanner.l"
+#line 1663 "Zend/zend_language_scanner.l"
                {
        zend_copy_value(zendlval, (yytext+1), (yyleng-1));
        zendlval->type = IS_STRING;
@@ -2012,7 +2012,7 @@ yy112:
                ++YYCURSOR;
                YYDEBUG(113, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1282 "Zend/zend_language_scanner.l"
+#line 1290 "Zend/zend_language_scanner.l"
                {
        yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
        return T_DOLLAR_OPEN_CURLY_BRACES;
@@ -2031,7 +2031,7 @@ yy116:
                ++YYCURSOR;
                YYDEBUG(117, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1647 "Zend/zend_language_scanner.l"
+#line 1655 "Zend/zend_language_scanner.l"
                {
        yyless(yyleng - 1);
        yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
@@ -2057,7 +2057,7 @@ yy119:
                ++YYCURSOR;
                YYDEBUG(120, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1637 "Zend/zend_language_scanner.l"
+#line 1645 "Zend/zend_language_scanner.l"
                {
        yyless(yyleng - 3);
        yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
@@ -2230,23 +2230,23 @@ yy123:
                YYDEBUG(-1, yych);
                switch ((yych = *YYCURSOR)) {
                case 'C':
-               case 'c':       goto yy701;
+               case 'c':       goto yy711;
                case 'L':
-               case 'l':       goto yy702;
+               case 'l':       goto yy712;
                case 'M':
-               case 'm':       goto yy703;
+               case 'm':       goto yy713;
                case 'N':
-               case 'n':       goto yy704;
+               case 'n':       goto yy714;
                case 'V':
-               case 'v':       goto yy705;
+               case 'v':       goto yy715;
                case 'X':
-               case 'x':       goto yy706;
+               case 'x':       goto yy716;
                default:        goto yy186;
                }
 yy124:
                YYDEBUG(124, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1678 "Zend/zend_language_scanner.l"
+#line 1686 "Zend/zend_language_scanner.l"
                {
        zend_copy_value(zendlval, yytext, yyleng);
        zendlval->type = IS_STRING;
@@ -2258,20 +2258,20 @@ yy125:
                yych = *++YYCURSOR;
                if (yych <= 'O') {
                        if (yych <= 'H') {
-                               if (yych == 'E') goto yy683;
+                               if (yych == 'E') goto yy693;
                                goto yy186;
                        } else {
-                               if (yych <= 'I') goto yy684;
+                               if (yych <= 'I') goto yy694;
                                if (yych <= 'N') goto yy186;
-                               goto yy685;
+                               goto yy695;
                        }
                } else {
                        if (yych <= 'h') {
-                               if (yych == 'e') goto yy683;
+                               if (yych == 'e') goto yy693;
                                goto yy186;
                        } else {
-                               if (yych <= 'i') goto yy684;
-                               if (yych == 'o') goto yy685;
+                               if (yych <= 'i') goto yy694;
+                               if (yych == 'o') goto yy695;
                                goto yy186;
                        }
                }
@@ -2280,20 +2280,20 @@ yy126:
                yych = *++YYCURSOR;
                if (yych <= 'U') {
                        if (yych <= 'N') {
-                               if (yych == 'I') goto yy662;
+                               if (yych == 'I') goto yy672;
                                goto yy186;
                        } else {
-                               if (yych <= 'O') goto yy663;
+                               if (yych <= 'O') goto yy673;
                                if (yych <= 'T') goto yy186;
-                               goto yy664;
+                               goto yy674;
                        }
                } else {
                        if (yych <= 'n') {
-                               if (yych == 'i') goto yy662;
+                               if (yych == 'i') goto yy672;
                                goto yy186;
                        } else {
-                               if (yych <= 'o') goto yy663;
-                               if (yych == 'u') goto yy664;
+                               if (yych <= 'o') goto yy673;
+                               if (yych == 'u') goto yy674;
                                goto yy186;
                        }
                }
@@ -2302,42 +2302,42 @@ yy127:
                yych = *++YYCURSOR;
                if (yych <= 'O') {
                        if (yych <= 'K') {
-                               if (yych == 'A') goto yy634;
+                               if (yych == 'A') goto yy644;
                                goto yy186;
                        } else {
-                               if (yych <= 'L') goto yy635;
+                               if (yych <= 'L') goto yy645;
                                if (yych <= 'N') goto yy186;
-                               goto yy636;
+                               goto yy646;
                        }
                } else {
                        if (yych <= 'k') {
-                               if (yych == 'a') goto yy634;
+                               if (yych == 'a') goto yy644;
                                goto yy186;
                        } else {
-                               if (yych <= 'l') goto yy635;
-                               if (yych == 'o') goto yy636;
+                               if (yych <= 'l') goto yy645;
+                               if (yych == 'o') goto yy646;
                                goto yy186;
                        }
                }
 yy128:
                YYDEBUG(128, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy616;
-               if (yych == 'e') goto yy616;
+               if (yych == 'E') goto yy626;
+               if (yych == 'e') goto yy626;
                goto yy186;
 yy129:
                YYDEBUG(129, *YYCURSOR);
                yych = *++YYCURSOR;
                if (yych <= 'R') {
-                       if (yych == 'H') goto yy608;
+                       if (yych == 'H') goto yy614;
                        if (yych <= 'Q') goto yy186;
-                       goto yy609;
+                       goto yy615;
                } else {
                        if (yych <= 'h') {
                                if (yych <= 'g') goto yy186;
-                               goto yy608;
+                               goto yy614;
                        } else {
-                               if (yych == 'r') goto yy609;
+                               if (yych == 'r') goto yy615;
                                goto yy186;
                        }
                }
@@ -2478,7 +2478,7 @@ yy137:
 yy138:
                YYDEBUG(138, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1271 "Zend/zend_language_scanner.l"
+#line 1279 "Zend/zend_language_scanner.l"
                {
        return yytext[0];
 }
@@ -2491,7 +2491,7 @@ yy139:
 yy140:
                YYDEBUG(140, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1006 "Zend/zend_language_scanner.l"
+#line 1010 "Zend/zend_language_scanner.l"
                {
        zendlval->value.str.val = yytext; /* no copying - intentional */
        zendlval->value.str.len = yyleng;
@@ -2510,7 +2510,7 @@ yy142:
                ++YYCURSOR;
                YYDEBUG(143, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1035 "Zend/zend_language_scanner.l"
+#line 1039 "Zend/zend_language_scanner.l"
                {
        return T_NS_SEPARATOR;
 }
@@ -2742,7 +2742,7 @@ yy167:
                ++YYCURSOR;
                YYDEBUG(168, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1276 "Zend/zend_language_scanner.l"
+#line 1284 "Zend/zend_language_scanner.l"
                {
        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
        return '{';
@@ -2753,7 +2753,7 @@ yy169:
                ++YYCURSOR;
                YYDEBUG(170, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1288 "Zend/zend_language_scanner.l"
+#line 1296 "Zend/zend_language_scanner.l"
                {
        RESET_DOC_COMMENT();
        if (!zend_stack_is_empty(&SCNG(state_stack))) {
@@ -2784,7 +2784,7 @@ yy171:
 yy172:
                YYDEBUG(172, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1314 "Zend/zend_language_scanner.l"
+#line 1322 "Zend/zend_language_scanner.l"
                {
        if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
                zendlval->value.lval = strtol(yytext, NULL, 0);
@@ -2833,7 +2833,7 @@ yy175:
 yy176:
                YYDEBUG(176, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1685 "Zend/zend_language_scanner.l"
+#line 1693 "Zend/zend_language_scanner.l"
                {
        while (YYCURSOR < YYLIMIT) {
                switch (*YYCURSOR++) {
@@ -2874,7 +2874,7 @@ yy177:
 yy178:
                YYDEBUG(178, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1776 "Zend/zend_language_scanner.l"
+#line 1784 "Zend/zend_language_scanner.l"
                {
        register char *s, *t;
        char *end;
@@ -2951,7 +2951,7 @@ yy179:
 yy180:
                YYDEBUG(180, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1847 "Zend/zend_language_scanner.l"
+#line 1855 "Zend/zend_language_scanner.l"
                {
        int bprefix = (yytext[0] != '"') ? 1 : 0;
 
@@ -2998,7 +2998,7 @@ yy181:
                ++YYCURSOR;
                YYDEBUG(182, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1938 "Zend/zend_language_scanner.l"
+#line 1946 "Zend/zend_language_scanner.l"
                {
        BEGIN(ST_BACKQUOTE);
        return '`';
@@ -3009,7 +3009,7 @@ yy183:
                ++YYCURSOR;
                YYDEBUG(184, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 2196 "Zend/zend_language_scanner.l"
+#line 2204 "Zend/zend_language_scanner.l"
                {
        if (YYCURSOR > YYLIMIT) {
                return 0;
@@ -3045,7 +3045,7 @@ yy187:
 yy189:
                YYDEBUG(189, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1375 "Zend/zend_language_scanner.l"
+#line 1383 "Zend/zend_language_scanner.l"
                {
        zendlval->value.dval = zend_strtod(yytext, NULL);
        zendlval->type = IS_DOUBLE;
@@ -3136,7 +3136,7 @@ yy198:
                }
                YYDEBUG(200, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1335 "Zend/zend_language_scanner.l"
+#line 1343 "Zend/zend_language_scanner.l"
                {
        char *hex = yytext + 2; /* Skip "0x" */
        int len = yyleng - 2;
@@ -3166,7 +3166,7 @@ yy201:
 yy202:
                YYDEBUG(202, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1753 "Zend/zend_language_scanner.l"
+#line 1761 "Zend/zend_language_scanner.l"
                {
        zendlval->value.str.val = yytext; /* no copying - intentional */
        zendlval->value.str.len = yyleng;
@@ -3208,7 +3208,7 @@ yy205:
 yy207:
                YYDEBUG(207, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1655 "Zend/zend_language_scanner.l"
+#line 1663 "Zend/zend_language_scanner.l"
                {
        zend_copy_value(zendlval, (yytext+1), (yyleng-1));
        zendlval->type = IS_STRING;
@@ -3228,7 +3228,7 @@ yy209:
                }
                YYDEBUG(210, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1259 "Zend/zend_language_scanner.l"
+#line 1267 "Zend/zend_language_scanner.l"
                {
        return T_LOGICAL_XOR;
 }
@@ -3241,7 +3241,7 @@ yy211:
                }
                YYDEBUG(212, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1251 "Zend/zend_language_scanner.l"
+#line 1259 "Zend/zend_language_scanner.l"
                {
        return T_LOGICAL_OR;
 }
@@ -3251,7 +3251,7 @@ yy213:
                ++YYCURSOR;
                YYDEBUG(214, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1239 "Zend/zend_language_scanner.l"
+#line 1247 "Zend/zend_language_scanner.l"
                {
        return T_XOR_EQUAL;
 }
@@ -3261,7 +3261,7 @@ yy215:
                ++YYCURSOR;
                YYDEBUG(216, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1243 "Zend/zend_language_scanner.l"
+#line 1251 "Zend/zend_language_scanner.l"
                {
        return T_BOOLEAN_OR;
 }
@@ -3271,7 +3271,7 @@ yy217:
                ++YYCURSOR;
                YYDEBUG(218, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1235 "Zend/zend_language_scanner.l"
+#line 1243 "Zend/zend_language_scanner.l"
                {
        return T_OR_EQUAL;
 }
@@ -3281,7 +3281,7 @@ yy219:
                ++YYCURSOR;
                YYDEBUG(220, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1247 "Zend/zend_language_scanner.l"
+#line 1255 "Zend/zend_language_scanner.l"
                {
        return T_BOOLEAN_AND;
 }
@@ -3291,7 +3291,7 @@ yy221:
                ++YYCURSOR;
                YYDEBUG(222, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1231 "Zend/zend_language_scanner.l"
+#line 1239 "Zend/zend_language_scanner.l"
                {
        return T_AND_EQUAL;
 }
@@ -3304,7 +3304,7 @@ yy223:
 yy224:
                YYDEBUG(224, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1762 "Zend/zend_language_scanner.l"
+#line 1770 "Zend/zend_language_scanner.l"
                {
        if (CG(asp_tags)) {
                BEGIN(INITIAL);
@@ -3323,7 +3323,7 @@ yy225:
                ++YYCURSOR;
                YYDEBUG(226, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1219 "Zend/zend_language_scanner.l"
+#line 1227 "Zend/zend_language_scanner.l"
                {
        return T_MOD_EQUAL;
 }
@@ -3358,7 +3358,7 @@ yy231:
                ++YYCURSOR;
                YYDEBUG(232, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1215 "Zend/zend_language_scanner.l"
+#line 1223 "Zend/zend_language_scanner.l"
                {
        return T_CONCAT_EQUAL;
 }
@@ -3371,7 +3371,7 @@ yy233:
 yy234:
                YYDEBUG(234, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1719 "Zend/zend_language_scanner.l"
+#line 1727 "Zend/zend_language_scanner.l"
                {
        int doc_com;
 
@@ -3415,7 +3415,7 @@ yy236:
                ++YYCURSOR;
                YYDEBUG(237, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1211 "Zend/zend_language_scanner.l"
+#line 1219 "Zend/zend_language_scanner.l"
                {
        return T_DIV_EQUAL;
 }
@@ -3442,7 +3442,7 @@ yy241:
                ++YYCURSOR;
                YYDEBUG(242, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1207 "Zend/zend_language_scanner.l"
+#line 1215 "Zend/zend_language_scanner.l"
                {
        return T_MUL_EQUAL;
 }
@@ -3453,7 +3453,7 @@ yy243:
                if ((yych = *YYCURSOR) == '=') goto yy247;
                YYDEBUG(244, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1267 "Zend/zend_language_scanner.l"
+#line 1275 "Zend/zend_language_scanner.l"
                {
        return T_SR;
 }
@@ -3463,7 +3463,7 @@ yy245:
                ++YYCURSOR;
                YYDEBUG(246, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1195 "Zend/zend_language_scanner.l"
+#line 1203 "Zend/zend_language_scanner.l"
                {
        return T_IS_GREATER_OR_EQUAL;
 }
@@ -3473,7 +3473,7 @@ yy247:
                ++YYCURSOR;
                YYDEBUG(248, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1227 "Zend/zend_language_scanner.l"
+#line 1235 "Zend/zend_language_scanner.l"
                {
        return T_SR_EQUAL;
 }
@@ -3488,7 +3488,7 @@ yy249:
 yy250:
                YYDEBUG(250, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1263 "Zend/zend_language_scanner.l"
+#line 1271 "Zend/zend_language_scanner.l"
                {
        return T_SL;
 }
@@ -3504,7 +3504,7 @@ yy252:
                ++YYCURSOR;
                YYDEBUG(253, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1191 "Zend/zend_language_scanner.l"
+#line 1199 "Zend/zend_language_scanner.l"
                {
        return T_IS_SMALLER_OR_EQUAL;
 }
@@ -3515,7 +3515,7 @@ yy254:
 yy255:
                YYDEBUG(255, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1187 "Zend/zend_language_scanner.l"
+#line 1195 "Zend/zend_language_scanner.l"
                {
        return T_IS_NOT_EQUAL;
 }
@@ -3570,7 +3570,7 @@ yy263:
                ++YYCURSOR;
                YYDEBUG(264, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1223 "Zend/zend_language_scanner.l"
+#line 1231 "Zend/zend_language_scanner.l"
                {
        return T_SL_EQUAL;
 }
@@ -3679,7 +3679,7 @@ yy274:
 yy275:
                YYDEBUG(275, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1889 "Zend/zend_language_scanner.l"
+#line 1897 "Zend/zend_language_scanner.l"
                {
        char *s;
        int bprefix = (yytext[0] != '<') ? 1 : 0;
@@ -3767,7 +3767,7 @@ yy279:
                ++YYCURSOR;
                YYDEBUG(281, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1179 "Zend/zend_language_scanner.l"
+#line 1187 "Zend/zend_language_scanner.l"
                {
        return T_IS_NOT_IDENTICAL;
 }
@@ -3777,7 +3777,7 @@ yy282:
                ++YYCURSOR;
                YYDEBUG(283, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1199 "Zend/zend_language_scanner.l"
+#line 1207 "Zend/zend_language_scanner.l"
                {
        return T_PLUS_EQUAL;
 }
@@ -3787,7 +3787,7 @@ yy284:
                ++YYCURSOR;
                YYDEBUG(285, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1167 "Zend/zend_language_scanner.l"
+#line 1175 "Zend/zend_language_scanner.l"
                {
        return T_INC;
 }
@@ -3810,7 +3810,7 @@ yy288:
                }
                YYDEBUG(289, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1159 "Zend/zend_language_scanner.l"
+#line 1167 "Zend/zend_language_scanner.l"
                {
        return T_LIST;
 }
@@ -3821,7 +3821,7 @@ yy290:
                if ((yych = *YYCURSOR) == '=') goto yy294;
                YYDEBUG(291, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1183 "Zend/zend_language_scanner.l"
+#line 1191 "Zend/zend_language_scanner.l"
                {
        return T_IS_EQUAL;
 }
@@ -3831,7 +3831,7 @@ yy292:
                ++YYCURSOR;
                YYDEBUG(293, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1155 "Zend/zend_language_scanner.l"
+#line 1163 "Zend/zend_language_scanner.l"
                {
        return T_DOUBLE_ARROW;
 }
@@ -3841,7 +3841,7 @@ yy294:
                ++YYCURSOR;
                YYDEBUG(295, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1175 "Zend/zend_language_scanner.l"
+#line 1183 "Zend/zend_language_scanner.l"
                {
        return T_IS_IDENTICAL;
 }
@@ -3967,7 +3967,7 @@ yy311:
                }
                YYDEBUG(314, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1479 "Zend/zend_language_scanner.l"
+#line 1487 "Zend/zend_language_scanner.l"
                {
        if (CG(current_namespace)) {
                *zendlval = *CG(current_namespace);
@@ -3997,7 +3997,7 @@ yy316:
                }
                YYDEBUG(319, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1452 "Zend/zend_language_scanner.l"
+#line 1460 "Zend/zend_language_scanner.l"
                {
        char *filename = zend_get_compiled_filename(TSRMLS_C);
        const size_t filename_len = strlen(filename);
@@ -4049,7 +4049,7 @@ yy322:
                }
                YYDEBUG(325, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1434 "Zend/zend_language_scanner.l"
+#line 1442 "Zend/zend_language_scanner.l"
                {
        zendlval->value.lval = CG(zend_lineno);
        zendlval->type = IS_LONG;
@@ -4090,7 +4090,7 @@ yy330:
                }
                YYDEBUG(333, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1413 "Zend/zend_language_scanner.l"
+#line 1421 "Zend/zend_language_scanner.l"
                {
        char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
        char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
@@ -4162,7 +4162,7 @@ yy341:
                }
                YYDEBUG(344, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1397 "Zend/zend_language_scanner.l"
+#line 1405 "Zend/zend_language_scanner.l"
                {
        char *func_name = NULL;
 
@@ -4198,7 +4198,7 @@ yy346:
                }
                YYDEBUG(349, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1440 "Zend/zend_language_scanner.l"
+#line 1448 "Zend/zend_language_scanner.l"
                {
        char *filename = zend_get_compiled_filename(TSRMLS_C);
 
@@ -4240,7 +4240,7 @@ yy353:
                }
                YYDEBUG(356, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1381 "Zend/zend_language_scanner.l"
+#line 1389 "Zend/zend_language_scanner.l"
                {
        char *class_name = NULL;
 
@@ -4318,7 +4318,7 @@ yy368:
                }
                YYDEBUG(369, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1123 "Zend/zend_language_scanner.l"
+#line 1131 "Zend/zend_language_scanner.l"
                {
        return T_HALT_COMPILER;
 }
@@ -4342,7 +4342,7 @@ yy372:
                }
                YYDEBUG(373, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1107 "Zend/zend_language_scanner.l"
+#line 1111 "Zend/zend_language_scanner.l"
                {
        return T_USE;
 }
@@ -4365,7 +4365,7 @@ yy376:
                }
                YYDEBUG(377, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1151 "Zend/zend_language_scanner.l"
+#line 1159 "Zend/zend_language_scanner.l"
                {
        return T_UNSET;
 }
@@ -4541,7 +4541,7 @@ yy393:
                ++YYCURSOR;
                YYDEBUG(395, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1051 "Zend/zend_language_scanner.l"
+#line 1055 "Zend/zend_language_scanner.l"
                {
        return T_INT_CAST;
 }
@@ -4589,7 +4589,7 @@ yy401:
                ++YYCURSOR;
                YYDEBUG(404, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1055 "Zend/zend_language_scanner.l"
+#line 1059 "Zend/zend_language_scanner.l"
                {
        return T_DOUBLE_CAST;
 }
@@ -4663,7 +4663,7 @@ yy415:
                ++YYCURSOR;
                YYDEBUG(418, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1059 "Zend/zend_language_scanner.l"
+#line 1063 "Zend/zend_language_scanner.l"
                {
        return T_STRING_CAST;
 }
@@ -4700,7 +4700,7 @@ yy422:
                ++YYCURSOR;
                YYDEBUG(425, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1067 "Zend/zend_language_scanner.l"
+#line 1071 "Zend/zend_language_scanner.l"
                {
        return T_ARRAY_CAST;
 }
@@ -4742,7 +4742,7 @@ yy430:
                ++YYCURSOR;
                YYDEBUG(433, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1071 "Zend/zend_language_scanner.l"
+#line 1075 "Zend/zend_language_scanner.l"
                {
        return T_OBJECT_CAST;
 }
@@ -4787,7 +4787,7 @@ yy439:
                ++YYCURSOR;
                YYDEBUG(441, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1075 "Zend/zend_language_scanner.l"
+#line 1079 "Zend/zend_language_scanner.l"
                {
        return T_BOOL_CAST;
 }
@@ -4835,7 +4835,7 @@ yy447:
                ++YYCURSOR;
                YYDEBUG(450, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1063 "Zend/zend_language_scanner.l"
+#line 1067 "Zend/zend_language_scanner.l"
                {
        return T_STRING_CAST;
 }
@@ -4872,7 +4872,7 @@ yy454:
                ++YYCURSOR;
                YYDEBUG(457, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1079 "Zend/zend_language_scanner.l"
+#line 1083 "Zend/zend_language_scanner.l"
                {
        return T_UNSET_CAST;
 }
@@ -4890,7 +4890,7 @@ yy459:
                }
                YYDEBUG(460, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1047 "Zend/zend_language_scanner.l"
+#line 1051 "Zend/zend_language_scanner.l"
                {
        return T_VAR;
 }
@@ -4914,7 +4914,7 @@ yy463:
                }
                YYDEBUG(464, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1039 "Zend/zend_language_scanner.l"
+#line 1043 "Zend/zend_language_scanner.l"
                {
        return T_NEW;
 }
@@ -4957,7 +4957,7 @@ yy471:
                }
                YYDEBUG(472, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1103 "Zend/zend_language_scanner.l"
+#line 1107 "Zend/zend_language_scanner.l"
                {
        return T_NAMESPACE;
 }
@@ -4967,7 +4967,7 @@ yy473:
                ++YYCURSOR;
                YYDEBUG(474, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1031 "Zend/zend_language_scanner.l"
+#line 1035 "Zend/zend_language_scanner.l"
                {
        return T_PAAMAYIM_NEKUDOTAYIM;
 }
@@ -4993,7 +4993,7 @@ yy477:
                ++YYCURSOR;
                YYDEBUG(478, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1203 "Zend/zend_language_scanner.l"
+#line 1211 "Zend/zend_language_scanner.l"
                {
        return T_MINUS_EQUAL;
 }
@@ -5003,7 +5003,7 @@ yy479:
                ++YYCURSOR;
                YYDEBUG(480, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1171 "Zend/zend_language_scanner.l"
+#line 1179 "Zend/zend_language_scanner.l"
                {
        return T_DEC;
 }
@@ -5013,7 +5013,7 @@ yy481:
                ++YYCURSOR;
                YYDEBUG(482, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1001 "Zend/zend_language_scanner.l"
+#line 1005 "Zend/zend_language_scanner.l"
                {
        yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
        return T_OBJECT_OPERATOR;
@@ -5063,7 +5063,7 @@ yy488:
                }
                YYDEBUG(489, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1147 "Zend/zend_language_scanner.l"
+#line 1155 "Zend/zend_language_scanner.l"
                {
        return T_PUBLIC;
 }
@@ -5122,7 +5122,7 @@ yy497:
                }
                YYDEBUG(498, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1143 "Zend/zend_language_scanner.l"
+#line 1151 "Zend/zend_language_scanner.l"
                {
        return T_PROTECTED;
 }
@@ -5156,7 +5156,7 @@ yy503:
                }
                YYDEBUG(504, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1139 "Zend/zend_language_scanner.l"
+#line 1147 "Zend/zend_language_scanner.l"
                {
        return T_PRIVATE;
 }
@@ -5226,7 +5226,7 @@ yy515:
                }
                YYDEBUG(516, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1111 "Zend/zend_language_scanner.l"
+#line 1119 "Zend/zend_language_scanner.l"
                {
        return T_GLOBAL;
 }
@@ -5339,7 +5339,7 @@ yy536:
                }
                YYDEBUG(537, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1127 "Zend/zend_language_scanner.l"
+#line 1135 "Zend/zend_language_scanner.l"
                {
        return T_STATIC;
 }
@@ -5393,7 +5393,7 @@ yy545:
                }
                YYDEBUG(546, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1163 "Zend/zend_language_scanner.l"
+#line 1171 "Zend/zend_language_scanner.l"
                {
        return T_ARRAY;
 }
@@ -5406,7 +5406,7 @@ yy547:
                }
                YYDEBUG(548, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1255 "Zend/zend_language_scanner.l"
+#line 1263 "Zend/zend_language_scanner.l"
                {
        return T_LOGICAL_AND;
 }
@@ -5444,7 +5444,7 @@ yy554:
                }
                YYDEBUG(555, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1131 "Zend/zend_language_scanner.l"
+#line 1139 "Zend/zend_language_scanner.l"
                {
        return T_ABSTRACT;
 }
@@ -5493,8 +5493,8 @@ yy561:
 yy563:
                YYDEBUG(563, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'P') goto yy599;
-               if (yych == 'p') goto yy599;
+               if (yych == 'P') goto yy605;
+               if (yych == 'p') goto yy605;
                goto yy186;
 yy564:
                YYDEBUG(564, *YYCURSOR);
@@ -5541,7 +5541,7 @@ yy568:
                }
                YYDEBUG(569, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1115 "Zend/zend_language_scanner.l"
+#line 1123 "Zend/zend_language_scanner.l"
                {
        return T_ISSET;
 }
@@ -5599,7 +5599,7 @@ yy576:
 yy577:
                YYDEBUG(577, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1087 "Zend/zend_language_scanner.l"
+#line 1091 "Zend/zend_language_scanner.l"
                {
        return T_INCLUDE;
 }
@@ -5632,7 +5632,7 @@ yy582:
                }
                YYDEBUG(583, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1091 "Zend/zend_language_scanner.l"
+#line 1095 "Zend/zend_language_scanner.l"
                {
        return T_INCLUDE_ONCE;
 }
@@ -5678,23 +5678,34 @@ yy589:
 yy591:
                YYDEBUG(591, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'A') goto yy592;
-               if (yych != 'a') goto yy186;
+               if (yych <= 'E') {
+                       if (yych == 'A') goto yy592;
+                       if (yych <= 'D') goto yy186;
+                       goto yy593;
+               } else {
+                       if (yych <= 'a') {
+                               if (yych <= '`') goto yy186;
+                       } else {
+                               if (yych == 'e') goto yy593;
+                               goto yy186;
+                       }
+               }
 yy592:
                YYDEBUG(592, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy593;
-               if (yych != 'n') goto yy186;
+               if (yych == 'N') goto yy599;
+               if (yych == 'n') goto yy599;
+               goto yy186;
 yy593:
                YYDEBUG(593, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'C') goto yy594;
-               if (yych != 'c') goto yy186;
+               if (yych == 'A') goto yy594;
+               if (yych != 'a') goto yy186;
 yy594:
                YYDEBUG(594, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy595;
-               if (yych != 'e') goto yy186;
+               if (yych == 'D') goto yy595;
+               if (yych != 'd') goto yy186;
 yy595:
                YYDEBUG(595, *YYCURSOR);
                yych = *++YYCURSOR;
@@ -5713,16 +5724,16 @@ yy597:
                }
                YYDEBUG(598, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 941 "Zend/zend_language_scanner.l"
+#line 1115 "Zend/zend_language_scanner.l"
                {
-       return T_INSTANCEOF;
+        return T_INSTEADOF;
 }
-#line 5721 "Zend/zend_language_scanner.c"
+#line 5732 "Zend/zend_language_scanner.c"
 yy599:
                YYDEBUG(599, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'L') goto yy600;
-               if (yych != 'l') goto yy186;
+               if (yych == 'C') goto yy600;
+               if (yych != 'c') goto yy186;
 yy600:
                YYDEBUG(600, *YYCURSOR);
                yych = *++YYCURSOR;
@@ -5731,1071 +5742,1135 @@ yy600:
 yy601:
                YYDEBUG(601, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'M') goto yy602;
-               if (yych != 'm') goto yy186;
+               if (yych == 'O') goto yy602;
+               if (yych != 'o') goto yy186;
 yy602:
                YYDEBUG(602, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy603;
-               if (yych != 'e') goto yy186;
+               if (yych == 'F') goto yy603;
+               if (yych != 'f') goto yy186;
 yy603:
                YYDEBUG(603, *YYCURSOR);
-               yych = *++YYCURSOR;
-               if (yych == 'N') goto yy604;
-               if (yych != 'n') goto yy186;
-yy604:
+               ++YYCURSOR;
+               if (yybm[0+(yych = *YYCURSOR)] & 8) {
+                       goto yy185;
+               }
                YYDEBUG(604, *YYCURSOR);
-               yych = *++YYCURSOR;
-               if (yych == 'T') goto yy605;
-               if (yych != 't') goto yy186;
+               yyleng = YYCURSOR - SCNG(yy_text);
+#line 941 "Zend/zend_language_scanner.l"
+               {
+       return T_INSTANCEOF;
+}
+#line 5765 "Zend/zend_language_scanner.c"
 yy605:
                YYDEBUG(605, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'S') goto yy606;
-               if (yych != 's') goto yy186;
+               if (yych == 'L') goto yy606;
+               if (yych != 'l') goto yy186;
 yy606:
                YYDEBUG(606, *YYCURSOR);
+               yych = *++YYCURSOR;
+               if (yych == 'E') goto yy607;
+               if (yych != 'e') goto yy186;
+yy607:
+               YYDEBUG(607, *YYCURSOR);
+               yych = *++YYCURSOR;
+               if (yych == 'M') goto yy608;
+               if (yych != 'm') goto yy186;
+yy608:
+               YYDEBUG(608, *YYCURSOR);
+               yych = *++YYCURSOR;
+               if (yych == 'E') goto yy609;
+               if (yych != 'e') goto yy186;
+yy609:
+               YYDEBUG(609, *YYCURSOR);
+               yych = *++YYCURSOR;
+               if (yych == 'N') goto yy610;
+               if (yych != 'n') goto yy186;
+yy610:
+               YYDEBUG(610, *YYCURSOR);
+               yych = *++YYCURSOR;
+               if (yych == 'T') goto yy611;
+               if (yych != 't') goto yy186;
+yy611:
+               YYDEBUG(611, *YYCURSOR);
+               yych = *++YYCURSOR;
+               if (yych == 'S') goto yy612;
+               if (yych != 's') goto yy186;
+yy612:
+               YYDEBUG(612, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(607, *YYCURSOR);
+               YYDEBUG(613, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 997 "Zend/zend_language_scanner.l"
+#line 1001 "Zend/zend_language_scanner.l"
                {
        return T_IMPLEMENTS;
 }
-#line 5769 "Zend/zend_language_scanner.c"
-yy608:
-               YYDEBUG(608, *YYCURSOR);
+#line 5813 "Zend/zend_language_scanner.c"
+yy614:
+               YYDEBUG(614, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'R') goto yy612;
-               if (yych == 'r') goto yy612;
+               if (yych == 'R') goto yy622;
+               if (yych == 'r') goto yy622;
                goto yy186;
-yy609:
-               YYDEBUG(609, *YYCURSOR);
+yy615:
+               YYDEBUG(615, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'Y') goto yy610;
-               if (yych != 'y') goto yy186;
-yy610:
-               YYDEBUG(610, *YYCURSOR);
+               if (yych <= 'Y') {
+                       if (yych == 'A') goto yy618;
+                       if (yych <= 'X') goto yy186;
+               } else {
+                       if (yych <= 'a') {
+                               if (yych <= '`') goto yy186;
+                               goto yy618;
+                       } else {
+                               if (yych != 'y') goto yy186;
+                       }
+               }
+               YYDEBUG(616, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(611, *YYCURSOR);
+               YYDEBUG(617, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 877 "Zend/zend_language_scanner.l"
                {
        return T_TRY;
 }
-#line 5793 "Zend/zend_language_scanner.c"
-yy612:
-               YYDEBUG(612, *YYCURSOR);
+#line 5845 "Zend/zend_language_scanner.c"
+yy618:
+               YYDEBUG(618, *YYCURSOR);
+               yych = *++YYCURSOR;
+               if (yych == 'I') goto yy619;
+               if (yych != 'i') goto yy186;
+yy619:
+               YYDEBUG(619, *YYCURSOR);
+               yych = *++YYCURSOR;
+               if (yych == 'T') goto yy620;
+               if (yych != 't') goto yy186;
+yy620:
+               YYDEBUG(620, *YYCURSOR);
+               ++YYCURSOR;
+               if (yybm[0+(yych = *YYCURSOR)] & 8) {
+                       goto yy185;
+               }
+               YYDEBUG(621, *YYCURSOR);
+               yyleng = YYCURSOR - SCNG(yy_text);
+#line 993 "Zend/zend_language_scanner.l"
+               {
+       return T_TRAIT;
+}
+#line 5868 "Zend/zend_language_scanner.c"
+yy622:
+               YYDEBUG(622, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'O') goto yy613;
+               if (yych == 'O') goto yy623;
                if (yych != 'o') goto yy186;
-yy613:
-               YYDEBUG(613, *YYCURSOR);
+yy623:
+               YYDEBUG(623, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'W') goto yy614;
+               if (yych == 'W') goto yy624;
                if (yych != 'w') goto yy186;
-yy614:
-               YYDEBUG(614, *YYCURSOR);
+yy624:
+               YYDEBUG(624, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(615, *YYCURSOR);
+               YYDEBUG(625, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 885 "Zend/zend_language_scanner.l"
                {
        return T_THROW;
 }
-#line 5816 "Zend/zend_language_scanner.c"
-yy616:
-               YYDEBUG(616, *YYCURSOR);
+#line 5891 "Zend/zend_language_scanner.c"
+yy626:
+               YYDEBUG(626, *YYCURSOR);
                yych = *++YYCURSOR;
                if (yych <= 'T') {
-                       if (yych == 'Q') goto yy618;
+                       if (yych == 'Q') goto yy628;
                        if (yych <= 'S') goto yy186;
                } else {
                        if (yych <= 'q') {
                                if (yych <= 'p') goto yy186;
-                               goto yy618;
+                               goto yy628;
                        } else {
                                if (yych != 't') goto yy186;
                        }
                }
-               YYDEBUG(617, *YYCURSOR);
+               YYDEBUG(627, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'U') goto yy630;
-               if (yych == 'u') goto yy630;
+               if (yych == 'U') goto yy640;
+               if (yych == 'u') goto yy640;
                goto yy186;
-yy618:
-               YYDEBUG(618, *YYCURSOR);
+yy628:
+               YYDEBUG(628, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'U') goto yy619;
+               if (yych == 'U') goto yy629;
                if (yych != 'u') goto yy186;
-yy619:
-               YYDEBUG(619, *YYCURSOR);
+yy629:
+               YYDEBUG(629, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'I') goto yy620;
+               if (yych == 'I') goto yy630;
                if (yych != 'i') goto yy186;
-yy620:
-               YYDEBUG(620, *YYCURSOR);
+yy630:
+               YYDEBUG(630, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'R') goto yy621;
+               if (yych == 'R') goto yy631;
                if (yych != 'r') goto yy186;
-yy621:
-               YYDEBUG(621, *YYCURSOR);
+yy631:
+               YYDEBUG(631, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy622;
+               if (yych == 'E') goto yy632;
                if (yych != 'e') goto yy186;
-yy622:
-               YYDEBUG(622, *YYCURSOR);
+yy632:
+               YYDEBUG(632, *YYCURSOR);
                ++YYCURSOR;
                if ((yych = *YYCURSOR) <= '^') {
                        if (yych <= '9') {
                                if (yych >= '0') goto yy185;
                        } else {
-                               if (yych <= '@') goto yy623;
+                               if (yych <= '@') goto yy633;
                                if (yych <= 'Z') goto yy185;
                        }
                } else {
                        if (yych <= '`') {
-                               if (yych <= '_') goto yy624;
+                               if (yych <= '_') goto yy634;
                        } else {
                                if (yych <= 'z') goto yy185;
                                if (yych >= 0x7F) goto yy185;
                        }
                }
-yy623:
-               YYDEBUG(623, *YYCURSOR);
+yy633:
+               YYDEBUG(633, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1095 "Zend/zend_language_scanner.l"
+#line 1099 "Zend/zend_language_scanner.l"
                {
        return T_REQUIRE;
 }
-#line 5881 "Zend/zend_language_scanner.c"
-yy624:
-               YYDEBUG(624, *YYCURSOR);
+#line 5956 "Zend/zend_language_scanner.c"
+yy634:
+               YYDEBUG(634, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'O') goto yy625;
+               if (yych == 'O') goto yy635;
                if (yych != 'o') goto yy186;
-yy625:
-               YYDEBUG(625, *YYCURSOR);
+yy635:
+               YYDEBUG(635, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy626;
+               if (yych == 'N') goto yy636;
                if (yych != 'n') goto yy186;
-yy626:
-               YYDEBUG(626, *YYCURSOR);
+yy636:
+               YYDEBUG(636, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'C') goto yy627;
+               if (yych == 'C') goto yy637;
                if (yych != 'c') goto yy186;
-yy627:
-               YYDEBUG(627, *YYCURSOR);
+yy637:
+               YYDEBUG(637, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy628;
+               if (yych == 'E') goto yy638;
                if (yych != 'e') goto yy186;
-yy628:
-               YYDEBUG(628, *YYCURSOR);
+yy638:
+               YYDEBUG(638, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(629, *YYCURSOR);
+               YYDEBUG(639, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1099 "Zend/zend_language_scanner.l"
+#line 1103 "Zend/zend_language_scanner.l"
                {
        return T_REQUIRE_ONCE;
 }
-#line 5914 "Zend/zend_language_scanner.c"
-yy630:
-               YYDEBUG(630, *YYCURSOR);
+#line 5989 "Zend/zend_language_scanner.c"
+yy640:
+               YYDEBUG(640, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'R') goto yy631;
+               if (yych == 'R') goto yy641;
                if (yych != 'r') goto yy186;
-yy631:
-               YYDEBUG(631, *YYCURSOR);
+yy641:
+               YYDEBUG(641, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy632;
+               if (yych == 'N') goto yy642;
                if (yych != 'n') goto yy186;
-yy632:
-               YYDEBUG(632, *YYCURSOR);
+yy642:
+               YYDEBUG(642, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(633, *YYCURSOR);
+               YYDEBUG(643, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 873 "Zend/zend_language_scanner.l"
                {
        return T_RETURN;
 }
-#line 5937 "Zend/zend_language_scanner.c"
-yy634:
-               YYDEBUG(634, *YYCURSOR);
+#line 6012 "Zend/zend_language_scanner.c"
+yy644:
+               YYDEBUG(644, *YYCURSOR);
                yych = *++YYCURSOR;
                if (yych <= 'T') {
                        if (yych <= 'R') goto yy186;
-                       if (yych <= 'S') goto yy656;
-                       goto yy655;
+                       if (yych <= 'S') goto yy666;
+                       goto yy665;
                } else {
                        if (yych <= 'r') goto yy186;
-                       if (yych <= 's') goto yy656;
-                       if (yych <= 't') goto yy655;
+                       if (yych <= 's') goto yy666;
+                       if (yych <= 't') goto yy665;
                        goto yy186;
                }
-yy635:
-               YYDEBUG(635, *YYCURSOR);
+yy645:
+               YYDEBUG(645, *YYCURSOR);
                yych = *++YYCURSOR;
                if (yych <= 'O') {
-                       if (yych == 'A') goto yy647;
+                       if (yych == 'A') goto yy657;
                        if (yych <= 'N') goto yy186;
-                       goto yy648;
+                       goto yy658;
                } else {
                        if (yych <= 'a') {
                                if (yych <= '`') goto yy186;
-                               goto yy647;
+                               goto yy657;
                        } else {
-                               if (yych == 'o') goto yy648;
+                               if (yych == 'o') goto yy658;
                                goto yy186;
                        }
                }
-yy636:
-               YYDEBUG(636, *YYCURSOR);
+yy646:
+               YYDEBUG(646, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy637;
+               if (yych == 'N') goto yy647;
                if (yych != 'n') goto yy186;
-yy637:
-               YYDEBUG(637, *YYCURSOR);
+yy647:
+               YYDEBUG(647, *YYCURSOR);
                yych = *++YYCURSOR;
                if (yych <= 'T') {
                        if (yych <= 'R') goto yy186;
-                       if (yych >= 'T') goto yy639;
+                       if (yych >= 'T') goto yy649;
                } else {
                        if (yych <= 'r') goto yy186;
-                       if (yych <= 's') goto yy638;
-                       if (yych <= 't') goto yy639;
+                       if (yych <= 's') goto yy648;
+                       if (yych <= 't') goto yy649;
                        goto yy186;
                }
-yy638:
-               YYDEBUG(638, *YYCURSOR);
+yy648:
+               YYDEBUG(648, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'T') goto yy645;
-               if (yych == 't') goto yy645;
+               if (yych == 'T') goto yy655;
+               if (yych == 't') goto yy655;
                goto yy186;
-yy639:
-               YYDEBUG(639, *YYCURSOR);
+yy649:
+               YYDEBUG(649, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'I') goto yy640;
+               if (yych == 'I') goto yy650;
                if (yych != 'i') goto yy186;
-yy640:
-               YYDEBUG(640, *YYCURSOR);
+yy650:
+               YYDEBUG(650, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy641;
+               if (yych == 'N') goto yy651;
                if (yych != 'n') goto yy186;
-yy641:
-               YYDEBUG(641, *YYCURSOR);
+yy651:
+               YYDEBUG(651, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'U') goto yy642;
+               if (yych == 'U') goto yy652;
                if (yych != 'u') goto yy186;
-yy642:
-               YYDEBUG(642, *YYCURSOR);
+yy652:
+               YYDEBUG(652, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy643;
+               if (yych == 'E') goto yy653;
                if (yych != 'e') goto yy186;
-yy643:
-               YYDEBUG(643, *YYCURSOR);
+yy653:
+               YYDEBUG(653, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(644, *YYCURSOR);
+               YYDEBUG(654, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 969 "Zend/zend_language_scanner.l"
                {
        return T_CONTINUE;
 }
-#line 6022 "Zend/zend_language_scanner.c"
-yy645:
-               YYDEBUG(645, *YYCURSOR);
+#line 6097 "Zend/zend_language_scanner.c"
+yy655:
+               YYDEBUG(655, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(646, *YYCURSOR);
+               YYDEBUG(656, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 869 "Zend/zend_language_scanner.l"
                {
        return T_CONST;
 }
-#line 6035 "Zend/zend_language_scanner.c"
-yy647:
-               YYDEBUG(647, *YYCURSOR);
+#line 6110 "Zend/zend_language_scanner.c"
+yy657:
+               YYDEBUG(657, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'S') goto yy652;
-               if (yych == 's') goto yy652;
+               if (yych == 'S') goto yy662;
+               if (yych == 's') goto yy662;
                goto yy186;
-yy648:
-               YYDEBUG(648, *YYCURSOR);
+yy658:
+               YYDEBUG(658, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy649;
+               if (yych == 'N') goto yy659;
                if (yych != 'n') goto yy186;
-yy649:
-               YYDEBUG(649, *YYCURSOR);
+yy659:
+               YYDEBUG(659, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy650;
+               if (yych == 'E') goto yy660;
                if (yych != 'e') goto yy186;
-yy650:
-               YYDEBUG(650, *YYCURSOR);
+yy660:
+               YYDEBUG(660, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(651, *YYCURSOR);
+               YYDEBUG(661, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1043 "Zend/zend_language_scanner.l"
+#line 1047 "Zend/zend_language_scanner.l"
                {
        return T_CLONE;
 }
-#line 6064 "Zend/zend_language_scanner.c"
-yy652:
-               YYDEBUG(652, *YYCURSOR);
+#line 6139 "Zend/zend_language_scanner.c"
+yy662:
+               YYDEBUG(662, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'S') goto yy653;
+               if (yych == 'S') goto yy663;
                if (yych != 's') goto yy186;
-yy653:
-               YYDEBUG(653, *YYCURSOR);
+yy663:
+               YYDEBUG(663, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(654, *YYCURSOR);
+               YYDEBUG(664, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 985 "Zend/zend_language_scanner.l"
                {
        return T_CLASS;
 }
-#line 6082 "Zend/zend_language_scanner.c"
-yy655:
-               YYDEBUG(655, *YYCURSOR);
+#line 6157 "Zend/zend_language_scanner.c"
+yy665:
+               YYDEBUG(665, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'C') goto yy659;
-               if (yych == 'c') goto yy659;
+               if (yych == 'C') goto yy669;
+               if (yych == 'c') goto yy669;
                goto yy186;
-yy656:
-               YYDEBUG(656, *YYCURSOR);
+yy666:
+               YYDEBUG(666, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy657;
+               if (yych == 'E') goto yy667;
                if (yych != 'e') goto yy186;
-yy657:
-               YYDEBUG(657, *YYCURSOR);
+yy667:
+               YYDEBUG(667, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(658, *YYCURSOR);
+               YYDEBUG(668, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 957 "Zend/zend_language_scanner.l"
                {
        return T_CASE;
 }
-#line 6106 "Zend/zend_language_scanner.c"
-yy659:
-               YYDEBUG(659, *YYCURSOR);
+#line 6181 "Zend/zend_language_scanner.c"
+yy669:
+               YYDEBUG(669, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'H') goto yy660;
+               if (yych == 'H') goto yy670;
                if (yych != 'h') goto yy186;
-yy660:
-               YYDEBUG(660, *YYCURSOR);
+yy670:
+               YYDEBUG(670, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(661, *YYCURSOR);
+               YYDEBUG(671, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 881 "Zend/zend_language_scanner.l"
                {
        return T_CATCH;
 }
-#line 6124 "Zend/zend_language_scanner.c"
-yy662:
-               YYDEBUG(662, *YYCURSOR);
+#line 6199 "Zend/zend_language_scanner.c"
+yy672:
+               YYDEBUG(672, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy679;
-               if (yych == 'n') goto yy679;
+               if (yych == 'N') goto yy689;
+               if (yych == 'n') goto yy689;
                goto yy186;
-yy663:
-               YYDEBUG(663, *YYCURSOR);
+yy673:
+               YYDEBUG(673, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'R') goto yy672;
-               if (yych == 'r') goto yy672;
+               if (yych == 'R') goto yy682;
+               if (yych == 'r') goto yy682;
                goto yy186;
-yy664:
-               YYDEBUG(664, *YYCURSOR);
+yy674:
+               YYDEBUG(674, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy665;
+               if (yych == 'N') goto yy675;
                if (yych != 'n') goto yy186;
-yy665:
-               YYDEBUG(665, *YYCURSOR);
+yy675:
+               YYDEBUG(675, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'C') goto yy666;
+               if (yych == 'C') goto yy676;
                if (yych != 'c') goto yy186;
-yy666:
-               YYDEBUG(666, *YYCURSOR);
+yy676:
+               YYDEBUG(676, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'T') goto yy667;
+               if (yych == 'T') goto yy677;
                if (yych != 't') goto yy186;
-yy667:
-               YYDEBUG(667, *YYCURSOR);
+yy677:
+               YYDEBUG(677, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'I') goto yy668;
+               if (yych == 'I') goto yy678;
                if (yych != 'i') goto yy186;
-yy668:
-               YYDEBUG(668, *YYCURSOR);
+yy678:
+               YYDEBUG(678, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'O') goto yy669;
+               if (yych == 'O') goto yy679;
                if (yych != 'o') goto yy186;
-yy669:
-               YYDEBUG(669, *YYCURSOR);
+yy679:
+               YYDEBUG(679, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy670;
+               if (yych == 'N') goto yy680;
                if (yych != 'n') goto yy186;
-yy670:
-               YYDEBUG(670, *YYCURSOR);
+yy680:
+               YYDEBUG(680, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(671, *YYCURSOR);
+               YYDEBUG(681, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 865 "Zend/zend_language_scanner.l"
                {
        return T_FUNCTION;
 }
-#line 6179 "Zend/zend_language_scanner.c"
-yy672:
-               YYDEBUG(672, *YYCURSOR);
+#line 6254 "Zend/zend_language_scanner.c"
+yy682:
+               YYDEBUG(682, *YYCURSOR);
                ++YYCURSOR;
                if ((yych = *YYCURSOR) <= '^') {
                        if (yych <= '@') {
-                               if (yych <= '/') goto yy673;
+                               if (yych <= '/') goto yy683;
                                if (yych <= '9') goto yy185;
                        } else {
-                               if (yych == 'E') goto yy674;
+                               if (yych == 'E') goto yy684;
                                if (yych <= 'Z') goto yy185;
                        }
                } else {
                        if (yych <= 'd') {
                                if (yych != '`') goto yy185;
                        } else {
-                               if (yych <= 'e') goto yy674;
+                               if (yych <= 'e') goto yy684;
                                if (yych <= 'z') goto yy185;
                                if (yych >= 0x7F) goto yy185;
                        }
                }
-yy673:
-               YYDEBUG(673, *YYCURSOR);
+yy683:
+               YYDEBUG(683, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 917 "Zend/zend_language_scanner.l"
                {
        return T_FOR;
 }
-#line 6207 "Zend/zend_language_scanner.c"
-yy674:
-               YYDEBUG(674, *YYCURSOR);
+#line 6282 "Zend/zend_language_scanner.c"
+yy684:
+               YYDEBUG(684, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'A') goto yy675;
+               if (yych == 'A') goto yy685;
                if (yych != 'a') goto yy186;
-yy675:
-               YYDEBUG(675, *YYCURSOR);
+yy685:
+               YYDEBUG(685, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'C') goto yy676;
+               if (yych == 'C') goto yy686;
                if (yych != 'c') goto yy186;
-yy676:
-               YYDEBUG(676, *YYCURSOR);
+yy686:
+               YYDEBUG(686, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'H') goto yy677;
+               if (yych == 'H') goto yy687;
                if (yych != 'h') goto yy186;
-yy677:
-               YYDEBUG(677, *YYCURSOR);
+yy687:
+               YYDEBUG(687, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(678, *YYCURSOR);
+               YYDEBUG(688, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 925 "Zend/zend_language_scanner.l"
                {
        return T_FOREACH;
 }
-#line 6235 "Zend/zend_language_scanner.c"
-yy679:
-               YYDEBUG(679, *YYCURSOR);
+#line 6310 "Zend/zend_language_scanner.c"
+yy689:
+               YYDEBUG(689, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'A') goto yy680;
+               if (yych == 'A') goto yy690;
                if (yych != 'a') goto yy186;
-yy680:
-               YYDEBUG(680, *YYCURSOR);
+yy690:
+               YYDEBUG(690, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'L') goto yy681;
+               if (yych == 'L') goto yy691;
                if (yych != 'l') goto yy186;
-yy681:
-               YYDEBUG(681, *YYCURSOR);
+yy691:
+               YYDEBUG(691, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(682, *YYCURSOR);
+               YYDEBUG(692, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1135 "Zend/zend_language_scanner.l"
+#line 1143 "Zend/zend_language_scanner.l"
                {
        return T_FINAL;
 }
-#line 6258 "Zend/zend_language_scanner.c"
-yy683:
-               YYDEBUG(683, *YYCURSOR);
+#line 6333 "Zend/zend_language_scanner.c"
+yy693:
+               YYDEBUG(693, *YYCURSOR);
                yych = *++YYCURSOR;
                if (yych <= 'F') {
-                       if (yych == 'C') goto yy689;
+                       if (yych == 'C') goto yy699;
                        if (yych <= 'E') goto yy186;
-                       goto yy690;
+                       goto yy700;
                } else {
                        if (yych <= 'c') {
                                if (yych <= 'b') goto yy186;
-                               goto yy689;
+                               goto yy699;
                        } else {
-                               if (yych == 'f') goto yy690;
+                               if (yych == 'f') goto yy700;
                                goto yy186;
                        }
                }
-yy684:
-               YYDEBUG(684, *YYCURSOR);
+yy694:
+               YYDEBUG(694, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy687;
-               if (yych == 'e') goto yy687;
+               if (yych == 'E') goto yy697;
+               if (yych == 'e') goto yy697;
                goto yy186;
-yy685:
-               YYDEBUG(685, *YYCURSOR);
+yy695:
+               YYDEBUG(695, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(686, *YYCURSOR);
+               YYDEBUG(696, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 913 "Zend/zend_language_scanner.l"
                {
        return T_DO;
 }
-#line 6293 "Zend/zend_language_scanner.c"
-yy687:
-               YYDEBUG(687, *YYCURSOR);
+#line 6368 "Zend/zend_language_scanner.c"
+yy697:
+               YYDEBUG(697, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(688, *YYCURSOR);
+               YYDEBUG(698, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 861 "Zend/zend_language_scanner.l"
                {
        return T_EXIT;
 }
-#line 6306 "Zend/zend_language_scanner.c"
-yy689:
-               YYDEBUG(689, *YYCURSOR);
+#line 6381 "Zend/zend_language_scanner.c"
+yy699:
+               YYDEBUG(699, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'L') goto yy696;
-               if (yych == 'l') goto yy696;
+               if (yych == 'L') goto yy706;
+               if (yych == 'l') goto yy706;
                goto yy186;
-yy690:
-               YYDEBUG(690, *YYCURSOR);
+yy700:
+               YYDEBUG(700, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'A') goto yy691;
+               if (yych == 'A') goto yy701;
                if (yych != 'a') goto yy186;
-yy691:
-               YYDEBUG(691, *YYCURSOR);
+yy701:
+               YYDEBUG(701, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'U') goto yy692;
+               if (yych == 'U') goto yy702;
                if (yych != 'u') goto yy186;
-yy692:
-               YYDEBUG(692, *YYCURSOR);
+yy702:
+               YYDEBUG(702, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'L') goto yy693;
+               if (yych == 'L') goto yy703;
                if (yych != 'l') goto yy186;
-yy693:
-               YYDEBUG(693, *YYCURSOR);
+yy703:
+               YYDEBUG(703, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'T') goto yy694;
+               if (yych == 'T') goto yy704;
                if (yych != 't') goto yy186;
-yy694:
-               YYDEBUG(694, *YYCURSOR);
+yy704:
+               YYDEBUG(704, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(695, *YYCURSOR);
+               YYDEBUG(705, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 961 "Zend/zend_language_scanner.l"
                {
        return T_DEFAULT;
 }
-#line 6345 "Zend/zend_language_scanner.c"
-yy696:
-               YYDEBUG(696, *YYCURSOR);
+#line 6420 "Zend/zend_language_scanner.c"
+yy706:
+               YYDEBUG(706, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'A') goto yy697;
+               if (yych == 'A') goto yy707;
                if (yych != 'a') goto yy186;
-yy697:
-               YYDEBUG(697, *YYCURSOR);
+yy707:
+               YYDEBUG(707, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'R') goto yy698;
+               if (yych == 'R') goto yy708;
                if (yych != 'r') goto yy186;
-yy698:
-               YYDEBUG(698, *YYCURSOR);
+yy708:
+               YYDEBUG(708, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy699;
+               if (yych == 'E') goto yy709;
                if (yych != 'e') goto yy186;
-yy699:
-               YYDEBUG(699, *YYCURSOR);
+yy709:
+               YYDEBUG(709, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(700, *YYCURSOR);
+               YYDEBUG(710, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 933 "Zend/zend_language_scanner.l"
                {
        return T_DECLARE;
 }
-#line 6373 "Zend/zend_language_scanner.c"
-yy701:
-               YYDEBUG(701, *YYCURSOR);
+#line 6448 "Zend/zend_language_scanner.c"
+yy711:
+               YYDEBUG(711, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'H') goto yy763;
-               if (yych == 'h') goto yy763;
+               if (yych == 'H') goto yy773;
+               if (yych == 'h') goto yy773;
                goto yy186;
-yy702:
-               YYDEBUG(702, *YYCURSOR);
+yy712:
+               YYDEBUG(712, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'S') goto yy757;
-               if (yych == 's') goto yy757;
+               if (yych == 'S') goto yy767;
+               if (yych == 's') goto yy767;
                goto yy186;
-yy703:
-               YYDEBUG(703, *YYCURSOR);
+yy713:
+               YYDEBUG(713, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'P') goto yy753;
-               if (yych == 'p') goto yy753;
+               if (yych == 'P') goto yy763;
+               if (yych == 'p') goto yy763;
                goto yy186;
-yy704:
-               YYDEBUG(704, *YYCURSOR);
+yy714:
+               YYDEBUG(714, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'D') goto yy719;
-               if (yych == 'd') goto yy719;
+               if (yych == 'D') goto yy729;
+               if (yych == 'd') goto yy729;
                goto yy186;
-yy705:
-               YYDEBUG(705, *YYCURSOR);
+yy715:
+               YYDEBUG(715, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'A') goto yy716;
-               if (yych == 'a') goto yy716;
+               if (yych == 'A') goto yy726;
+               if (yych == 'a') goto yy726;
                goto yy186;
-yy706:
-               YYDEBUG(706, *YYCURSOR);
+yy716:
+               YYDEBUG(716, *YYCURSOR);
                yych = *++YYCURSOR;
                if (yych <= 'T') {
-                       if (yych == 'I') goto yy707;
+                       if (yych == 'I') goto yy717;
                        if (yych <= 'S') goto yy186;
-                       goto yy708;
+                       goto yy718;
                } else {
                        if (yych <= 'i') {
                                if (yych <= 'h') goto yy186;
                        } else {
-                               if (yych == 't') goto yy708;
+                               if (yych == 't') goto yy718;
                                goto yy186;
                        }
                }
-yy707:
-               YYDEBUG(707, *YYCURSOR);
+yy717:
+               YYDEBUG(717, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'T') goto yy714;
-               if (yych == 't') goto yy714;
+               if (yych == 'T') goto yy724;
+               if (yych == 't') goto yy724;
                goto yy186;
-yy708:
-               YYDEBUG(708, *YYCURSOR);
+yy718:
+               YYDEBUG(718, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy709;
+               if (yych == 'E') goto yy719;
                if (yych != 'e') goto yy186;
-yy709:
-               YYDEBUG(709, *YYCURSOR);
+yy719:
+               YYDEBUG(719, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'N') goto yy710;
+               if (yych == 'N') goto yy720;
                if (yych != 'n') goto yy186;
-yy710:
-               YYDEBUG(710, *YYCURSOR);
+yy720:
+               YYDEBUG(720, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'D') goto yy711;
+               if (yych == 'D') goto yy721;
                if (yych != 'd') goto yy186;
-yy711:
-               YYDEBUG(711, *YYCURSOR);
+yy721:
+               YYDEBUG(721, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'S') goto yy712;
+               if (yych == 'S') goto yy722;
                if (yych != 's') goto yy186;
-yy712:
-               YYDEBUG(712, *YYCURSOR);
+yy722:
+               YYDEBUG(722, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(713, *YYCURSOR);
+               YYDEBUG(723, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 993 "Zend/zend_language_scanner.l"
+#line 997 "Zend/zend_language_scanner.l"
                {
        return T_EXTENDS;
 }
-#line 6457 "Zend/zend_language_scanner.c"
-yy714:
-               YYDEBUG(714, *YYCURSOR);
+#line 6532 "Zend/zend_language_scanner.c"
+yy724:
+               YYDEBUG(724, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(715, *YYCURSOR);
+               YYDEBUG(725, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 857 "Zend/zend_language_scanner.l"
                {
        return T_EXIT;
 }
-#line 6470 "Zend/zend_language_scanner.c"
-yy716:
-               YYDEBUG(716, *YYCURSOR);
+#line 6545 "Zend/zend_language_scanner.c"
+yy726:
+               YYDEBUG(726, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'L') goto yy717;
+               if (yych == 'L') goto yy727;
                if (yych != 'l') goto yy186;
-yy717:
-               YYDEBUG(717, *YYCURSOR);
+yy727:
+               YYDEBUG(727, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(718, *YYCURSOR);
+               YYDEBUG(728, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1083 "Zend/zend_language_scanner.l"
+#line 1087 "Zend/zend_language_scanner.l"
                {
        return T_EVAL;
 }
-#line 6488 "Zend/zend_language_scanner.c"
-yy719:
-               YYDEBUG(719, *YYCURSOR);
+#line 6563 "Zend/zend_language_scanner.c"
+yy729:
+               YYDEBUG(729, *YYCURSOR);
                yych = *++YYCURSOR;
                YYDEBUG(-1, yych);
                switch (yych) {
                case 'D':
-               case 'd':       goto yy720;
+               case 'd':       goto yy730;
                case 'F':
-               case 'f':       goto yy721;
+               case 'f':       goto yy731;
                case 'I':
-               case 'i':       goto yy722;
+               case 'i':       goto yy732;
                case 'S':
-               case 's':       goto yy723;
+               case 's':       goto yy733;
                case 'W':
-               case 'w':       goto yy724;
+               case 'w':       goto yy734;
                default:        goto yy186;
                }
-yy720:
-               YYDEBUG(720, *YYCURSOR);
+yy730:
+               YYDEBUG(730, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy746;
-               if (yych == 'e') goto yy746;
+               if (yych == 'E') goto yy756;
+               if (yych == 'e') goto yy756;
                goto yy186;
-yy721:
-               YYDEBUG(721, *YYCURSOR);
+yy731:
+               YYDEBUG(731, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'O') goto yy738;
-               if (yych == 'o') goto yy738;
+               if (yych == 'O') goto yy748;
+               if (yych == 'o') goto yy748;
                goto yy186;
-yy722:
-               YYDEBUG(722, *YYCURSOR);
+yy732:
+               YYDEBUG(732, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'F') goto yy736;
-               if (yych == 'f') goto yy736;
+               if (yych == 'F') goto yy746;
+               if (yych == 'f') goto yy746;
                goto yy186;
-yy723:
-               YYDEBUG(723, *YYCURSOR);
+yy733:
+               YYDEBUG(733, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'W') goto yy730;
-               if (yych == 'w') goto yy730;
+               if (yych == 'W') goto yy740;
+               if (yych == 'w') goto yy740;
                goto yy186;
-yy724:
-               YYDEBUG(724, *YYCURSOR);
+yy734:
+               YYDEBUG(734, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'H') goto yy725;
+               if (yych == 'H') goto yy735;
                if (yych != 'h') goto yy186;
-yy725:
-               YYDEBUG(725, *YYCURSOR);
+yy735:
+               YYDEBUG(735, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'I') goto yy726;
+               if (yych == 'I') goto yy736;
                if (yych != 'i') goto yy186;
-yy726:
-               YYDEBUG(726, *YYCURSOR);
+yy736:
+               YYDEBUG(736, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'L') goto yy727;
+               if (yych == 'L') goto yy737;
                if (yych != 'l') goto yy186;
-yy727:
-               YYDEBUG(727, *YYCURSOR);
+yy737:
+               YYDEBUG(737, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy728;
+               if (yych == 'E') goto yy738;
                if (yych != 'e') goto yy186;
-yy728:
-               YYDEBUG(728, *YYCURSOR);
+yy738:
+               YYDEBUG(738, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(729, *YYCURSOR);
+               YYDEBUG(739, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 909 "Zend/zend_language_scanner.l"
                {
        return T_ENDWHILE;
 }
-#line 6562 "Zend/zend_language_scanner.c"
-yy730:
-               YYDEBUG(730, *YYCURSOR);
+#line 6637 "Zend/zend_language_scanner.c"
+yy740:
+               YYDEBUG(740, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'I') goto yy731;
+               if (yych == 'I') goto yy741;
                if (yych != 'i') goto yy186;
-yy731:
-               YYDEBUG(731, *YYCURSOR);
+yy741:
+               YYDEBUG(741, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'T') goto yy732;
+               if (yych == 'T') goto yy742;
                if (yych != 't') goto yy186;
-yy732:
-               YYDEBUG(732, *YYCURSOR);
+yy742:
+               YYDEBUG(742, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'C') goto yy733;
+               if (yych == 'C') goto yy743;
                if (yych != 'c') goto yy186;
-yy733:
-               YYDEBUG(733, *YYCURSOR);
+yy743:
+               YYDEBUG(743, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'H') goto yy734;
+               if (yych == 'H') goto yy744;
                if (yych != 'h') goto yy186;
-yy734:
-               YYDEBUG(734, *YYCURSOR);
+yy744:
+               YYDEBUG(744, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(735, *YYCURSOR);
+               YYDEBUG(745, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 953 "Zend/zend_language_scanner.l"
                {
        return T_ENDSWITCH;
 }
-#line 6595 "Zend/zend_language_scanner.c"
-yy736:
-               YYDEBUG(736, *YYCURSOR);
+#line 6670 "Zend/zend_language_scanner.c"
+yy746:
+               YYDEBUG(746, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(737, *YYCURSOR);
+               YYDEBUG(747, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 897 "Zend/zend_language_scanner.l"
                {
        return T_ENDIF;
 }
-#line 6608 "Zend/zend_language_scanner.c"
-yy738:
-               YYDEBUG(738, *YYCURSOR);
+#line 6683 "Zend/zend_language_scanner.c"
+yy748:
+               YYDEBUG(748, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'R') goto yy739;
+               if (yych == 'R') goto yy749;
                if (yych != 'r') goto yy186;
-yy739:
-               YYDEBUG(739, *YYCURSOR);
+yy749:
+               YYDEBUG(749, *YYCURSOR);
                ++YYCURSOR;
                if ((yych = *YYCURSOR) <= '^') {
                        if (yych <= '@') {
-                               if (yych <= '/') goto yy740;
+                               if (yych <= '/') goto yy750;
                                if (yych <= '9') goto yy185;
                        } else {
-                               if (yych == 'E') goto yy741;
+                               if (yych == 'E') goto yy751;
                                if (yych <= 'Z') goto yy185;
                        }
                } else {
                        if (yych <= 'd') {
                                if (yych != '`') goto yy185;
                        } else {
-                               if (yych <= 'e') goto yy741;
+                               if (yych <= 'e') goto yy751;
                                if (yych <= 'z') goto yy185;
                                if (yych >= 0x7F) goto yy185;
                        }
                }
-yy740:
-               YYDEBUG(740, *YYCURSOR);
+yy750:
+               YYDEBUG(750, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 921 "Zend/zend_language_scanner.l"
                {
        return T_ENDFOR;
 }
-#line 6641 "Zend/zend_language_scanner.c"
-yy741:
-               YYDEBUG(741, *YYCURSOR);
+#line 6716 "Zend/zend_language_scanner.c"
+yy751:
+               YYDEBUG(751, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'A') goto yy742;
+               if (yych == 'A') goto yy752;
                if (yych != 'a') goto yy186;
-yy742:
-               YYDEBUG(742, *YYCURSOR);
+yy752:
+               YYDEBUG(752, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'C') goto yy743;
+               if (yych == 'C') goto yy753;
                if (yych != 'c') goto yy186;
-yy743:
-               YYDEBUG(743, *YYCURSOR);
+yy753:
+               YYDEBUG(753, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'H') goto yy744;
+               if (yych == 'H') goto yy754;
                if (yych != 'h') goto yy186;
-yy744:
-               YYDEBUG(744, *YYCURSOR);
+yy754:
+               YYDEBUG(754, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(745, *YYCURSOR);
+               YYDEBUG(755, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 929 "Zend/zend_language_scanner.l"
                {
        return T_ENDFOREACH;
 }
-#line 6669 "Zend/zend_language_scanner.c"
-yy746:
-               YYDEBUG(746, *YYCURSOR);
+#line 6744 "Zend/zend_language_scanner.c"
+yy756:
+               YYDEBUG(756, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'C') goto yy747;
+               if (yych == 'C') goto yy757;
                if (yych != 'c') goto yy186;
-yy747:
-               YYDEBUG(747, *YYCURSOR);
+yy757:
+               YYDEBUG(757, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'L') goto yy748;
+               if (yych == 'L') goto yy758;
                if (yych != 'l') goto yy186;
-yy748:
-               YYDEBUG(748, *YYCURSOR);
+yy758:
+               YYDEBUG(758, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'A') goto yy749;
+               if (yych == 'A') goto yy759;
                if (yych != 'a') goto yy186;
-yy749:
-               YYDEBUG(749, *YYCURSOR);
+yy759:
+               YYDEBUG(759, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'R') goto yy750;
+               if (yych == 'R') goto yy760;
                if (yych != 'r') goto yy186;
-yy750:
-               YYDEBUG(750, *YYCURSOR);
+yy760:
+               YYDEBUG(760, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy751;
+               if (yych == 'E') goto yy761;
                if (yych != 'e') goto yy186;
-yy751:
-               YYDEBUG(751, *YYCURSOR);
+yy761:
+               YYDEBUG(761, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(752, *YYCURSOR);
+               YYDEBUG(762, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 937 "Zend/zend_language_scanner.l"
                {
        return T_ENDDECLARE;
 }
-#line 6707 "Zend/zend_language_scanner.c"
-yy753:
-               YYDEBUG(753, *YYCURSOR);
+#line 6782 "Zend/zend_language_scanner.c"
+yy763:
+               YYDEBUG(763, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'T') goto yy754;
+               if (yych == 'T') goto yy764;
                if (yych != 't') goto yy186;
-yy754:
-               YYDEBUG(754, *YYCURSOR);
+yy764:
+               YYDEBUG(764, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'Y') goto yy755;
+               if (yych == 'Y') goto yy765;
                if (yych != 'y') goto yy186;
-yy755:
-               YYDEBUG(755, *YYCURSOR);
+yy765:
+               YYDEBUG(765, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(756, *YYCURSOR);
+               YYDEBUG(766, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1119 "Zend/zend_language_scanner.l"
+#line 1127 "Zend/zend_language_scanner.l"
                {
        return T_EMPTY;
 }
-#line 6730 "Zend/zend_language_scanner.c"
-yy757:
-               YYDEBUG(757, *YYCURSOR);
+#line 6805 "Zend/zend_language_scanner.c"
+yy767:
+               YYDEBUG(767, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'E') goto yy758;
+               if (yych == 'E') goto yy768;
                if (yych != 'e') goto yy186;
-yy758:
-               YYDEBUG(758, *YYCURSOR);
+yy768:
+               YYDEBUG(768, *YYCURSOR);
                ++YYCURSOR;
                if ((yych = *YYCURSOR) <= '^') {
                        if (yych <= '@') {
-                               if (yych <= '/') goto yy759;
+                               if (yych <= '/') goto yy769;
                                if (yych <= '9') goto yy185;
                        } else {
-                               if (yych == 'I') goto yy760;
+                               if (yych == 'I') goto yy770;
                                if (yych <= 'Z') goto yy185;
                        }
                } else {
                        if (yych <= 'h') {
                                if (yych != '`') goto yy185;
                        } else {
-                               if (yych <= 'i') goto yy760;
+                               if (yych <= 'i') goto yy770;
                                if (yych <= 'z') goto yy185;
                                if (yych >= 0x7F) goto yy185;
                        }
                }
-yy759:
-               YYDEBUG(759, *YYCURSOR);
+yy769:
+               YYDEBUG(769, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 901 "Zend/zend_language_scanner.l"
                {
        return T_ELSE;
 }
-#line 6763 "Zend/zend_language_scanner.c"
-yy760:
-               YYDEBUG(760, *YYCURSOR);
+#line 6838 "Zend/zend_language_scanner.c"
+yy770:
+               YYDEBUG(770, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'F') goto yy761;
+               if (yych == 'F') goto yy771;
                if (yych != 'f') goto yy186;
-yy761:
-               YYDEBUG(761, *YYCURSOR);
+yy771:
+               YYDEBUG(771, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(762, *YYCURSOR);
+               YYDEBUG(772, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 893 "Zend/zend_language_scanner.l"
                {
        return T_ELSEIF;
 }
-#line 6781 "Zend/zend_language_scanner.c"
-yy763:
-               YYDEBUG(763, *YYCURSOR);
+#line 6856 "Zend/zend_language_scanner.c"
+yy773:
+               YYDEBUG(773, *YYCURSOR);
                yych = *++YYCURSOR;
-               if (yych == 'O') goto yy764;
+               if (yych == 'O') goto yy774;
                if (yych != 'o') goto yy186;
-yy764:
-               YYDEBUG(764, *YYCURSOR);
+yy774:
+               YYDEBUG(774, *YYCURSOR);
                ++YYCURSOR;
                if (yybm[0+(yych = *YYCURSOR)] & 8) {
                        goto yy185;
                }
-               YYDEBUG(765, *YYCURSOR);
+               YYDEBUG(775, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
 #line 977 "Zend/zend_language_scanner.l"
                {
        return T_ECHO;
 }
-#line 6799 "Zend/zend_language_scanner.c"
+#line 6874 "Zend/zend_language_scanner.c"
        }
 /* *********************************** */
 yyc_ST_LOOKING_FOR_PROPERTY:
@@ -6834,41 +6909,41 @@ yyc_ST_LOOKING_FOR_PROPERTY:
                         64,  64,  64,  64,  64,  64,  64,  64, 
                         64,  64,  64,  64,  64,  64,  64,  64, 
                };
-               YYDEBUG(766, *YYCURSOR);
+               YYDEBUG(776, *YYCURSOR);
                YYFILL(2);
                yych = *YYCURSOR;
                if (yych <= '-') {
                        if (yych <= '\r') {
-                               if (yych <= 0x08) goto yy774;
-                               if (yych <= '\n') goto yy768;
-                               if (yych <= '\f') goto yy774;
+                               if (yych <= 0x08) goto yy784;
+                               if (yych <= '\n') goto yy778;
+                               if (yych <= '\f') goto yy784;
                        } else {
-                               if (yych == ' ') goto yy768;
-                               if (yych <= ',') goto yy774;
-                               goto yy770;
+                               if (yych == ' ') goto yy778;
+                               if (yych <= ',') goto yy784;
+                               goto yy780;
                        }
                } else {
                        if (yych <= '_') {
-                               if (yych <= '@') goto yy774;
-                               if (yych <= 'Z') goto yy772;
-                               if (yych <= '^') goto yy774;
-                               goto yy772;
+                               if (yych <= '@') goto yy784;
+                               if (yych <= 'Z') goto yy782;
+                               if (yych <= '^') goto yy784;
+                               goto yy782;
                        } else {
-                               if (yych <= '`') goto yy774;
-                               if (yych <= 'z') goto yy772;
-                               if (yych <= '~') goto yy774;
-                               goto yy772;
+                               if (yych <= '`') goto yy784;
+                               if (yych <= 'z') goto yy782;
+                               if (yych <= '~') goto yy784;
+                               goto yy782;
                        }
                }
-yy768:
-               YYDEBUG(768, *YYCURSOR);
+yy778:
+               YYDEBUG(778, *YYCURSOR);
                ++YYCURSOR;
                yych = *YYCURSOR;
-               goto yy780;
-yy769:
-               YYDEBUG(769, *YYCURSOR);
+               goto yy790;
+yy779:
+               YYDEBUG(779, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1006 "Zend/zend_language_scanner.l"
+#line 1010 "Zend/zend_language_scanner.l"
                {
        zendlval->value.str.val = yytext; /* no copying - intentional */
        zendlval->value.str.len = yyleng;
@@ -6876,73 +6951,73 @@ yy769:
        HANDLE_NEWLINES(yytext, yyleng);
        return T_WHITESPACE;
 }
-#line 6880 "Zend/zend_language_scanner.c"
-yy770:
-               YYDEBUG(770, *YYCURSOR);
+#line 6955 "Zend/zend_language_scanner.c"
+yy780:
+               YYDEBUG(780, *YYCURSOR);
                ++YYCURSOR;
-               if ((yych = *YYCURSOR) == '>') goto yy777;
-yy771:
-               YYDEBUG(771, *YYCURSOR);
+               if ((yych = *YYCURSOR) == '>') goto yy787;
+yy781:
+               YYDEBUG(781, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1025 "Zend/zend_language_scanner.l"
+#line 1029 "Zend/zend_language_scanner.l"
                {
        yyless(0);
        yy_pop_state(TSRMLS_C);
        goto restart;
 }
-#line 6894 "Zend/zend_language_scanner.c"
-yy772:
-               YYDEBUG(772, *YYCURSOR);
+#line 6969 "Zend/zend_language_scanner.c"
+yy782:
+               YYDEBUG(782, *YYCURSOR);
                ++YYCURSOR;
                yych = *YYCURSOR;
-               goto yy776;
-yy773:
-               YYDEBUG(773, *YYCURSOR);
+               goto yy786;
+yy783:
+               YYDEBUG(783, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1018 "Zend/zend_language_scanner.l"
+#line 1022 "Zend/zend_language_scanner.l"
                {
        yy_pop_state(TSRMLS_C);
        zend_copy_value(zendlval, yytext, yyleng);
        zendlval->type = IS_STRING;
        return T_STRING;
 }
-#line 6910 "Zend/zend_language_scanner.c"
-yy774:
-               YYDEBUG(774, *YYCURSOR);
+#line 6985 "Zend/zend_language_scanner.c"
+yy784:
+               YYDEBUG(784, *YYCURSOR);
                yych = *++YYCURSOR;
-               goto yy771;
-yy775:
-               YYDEBUG(775, *YYCURSOR);
+               goto yy781;
+yy785:
+               YYDEBUG(785, *YYCURSOR);
                ++YYCURSOR;
                YYFILL(1);
                yych = *YYCURSOR;
-yy776:
-               YYDEBUG(776, *YYCURSOR);
+yy786:
+               YYDEBUG(786, *YYCURSOR);
                if (yybm[0+yych] & 64) {
-                       goto yy775;
+                       goto yy785;
                }
-               goto yy773;
-yy777:
-               YYDEBUG(777, *YYCURSOR);
+               goto yy783;
+yy787:
+               YYDEBUG(787, *YYCURSOR);
                ++YYCURSOR;
-               YYDEBUG(778, *YYCURSOR);
+               YYDEBUG(788, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1014 "Zend/zend_language_scanner.l"
+#line 1018 "Zend/zend_language_scanner.l"
                {
        return T_OBJECT_OPERATOR;
 }
-#line 6935 "Zend/zend_language_scanner.c"
-yy779:
-               YYDEBUG(779, *YYCURSOR);
+#line 7010 "Zend/zend_language_scanner.c"
+yy789:
+               YYDEBUG(789, *YYCURSOR);
                ++YYCURSOR;
                YYFILL(1);
                yych = *YYCURSOR;
-yy780:
-               YYDEBUG(780, *YYCURSOR);
+yy790:
+               YYDEBUG(790, *YYCURSOR);
                if (yybm[0+yych] & 128) {
-                       goto yy779;
+                       goto yy789;
                }
-               goto yy769;
+               goto yy779;
        }
 /* *********************************** */
 yyc_ST_LOOKING_FOR_VARNAME:
@@ -6981,27 +7056,27 @@ yyc_ST_LOOKING_FOR_VARNAME:
                        128, 128, 128, 128, 128, 128, 128, 128, 
                        128, 128, 128, 128, 128, 128, 128, 128, 
                };
-               YYDEBUG(781, *YYCURSOR);
+               YYDEBUG(791, *YYCURSOR);
                YYFILL(2);
                yych = *YYCURSOR;
                if (yych <= '_') {
-                       if (yych <= '@') goto yy785;
-                       if (yych <= 'Z') goto yy783;
-                       if (yych <= '^') goto yy785;
+                       if (yych <= '@') goto yy795;
+                       if (yych <= 'Z') goto yy793;
+                       if (yych <= '^') goto yy795;
                } else {
-                       if (yych <= '`') goto yy785;
-                       if (yych <= 'z') goto yy783;
-                       if (yych <= '~') goto yy785;
+                       if (yych <= '`') goto yy795;
+                       if (yych <= 'z') goto yy793;
+                       if (yych <= '~') goto yy795;
                }
-yy783:
-               YYDEBUG(783, *YYCURSOR);
+yy793:
+               YYDEBUG(793, *YYCURSOR);
                ++YYCURSOR;
                yych = *YYCURSOR;
-               goto yy788;
-yy784:
-               YYDEBUG(784, *YYCURSOR);
+               goto yy798;
+yy794:
+               YYDEBUG(794, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1297 "Zend/zend_language_scanner.l"
+#line 1305 "Zend/zend_language_scanner.l"
                {
        zend_copy_value(zendlval, yytext, yyleng);
        zendlval->type = IS_STRING;
@@ -7009,42 +7084,42 @@ yy784:
        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
        return T_STRING_VARNAME;
 }
-#line 7013 "Zend/zend_language_scanner.c"
-yy785:
-               YYDEBUG(785, *YYCURSOR);
+#line 7088 "Zend/zend_language_scanner.c"
+yy795:
+               YYDEBUG(795, *YYCURSOR);
                ++YYCURSOR;
-               YYDEBUG(786, *YYCURSOR);
+               YYDEBUG(796, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1306 "Zend/zend_language_scanner.l"
+#line 1314 "Zend/zend_language_scanner.l"
                {
        yyless(0);
        yy_pop_state(TSRMLS_C);
        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
        goto restart;
 }
-#line 7026 "Zend/zend_language_scanner.c"
-yy787:
-               YYDEBUG(787, *YYCURSOR);
+#line 7101 "Zend/zend_language_scanner.c"
+yy797:
+               YYDEBUG(797, *YYCURSOR);
                ++YYCURSOR;
                YYFILL(1);
                yych = *YYCURSOR;
-yy788:
-               YYDEBUG(788, *YYCURSOR);
+yy798:
+               YYDEBUG(798, *YYCURSOR);
                if (yybm[0+yych] & 128) {
-                       goto yy787;
+                       goto yy797;
                }
-               goto yy784;
+               goto yy794;
        }
 /* *********************************** */
 yyc_ST_NOWDOC:
-       YYDEBUG(789, *YYCURSOR);
+       YYDEBUG(799, *YYCURSOR);
        YYFILL(1);
        yych = *YYCURSOR;
-       YYDEBUG(791, *YYCURSOR);
+       YYDEBUG(801, *YYCURSOR);
        ++YYCURSOR;
-       YYDEBUG(792, *YYCURSOR);
+       YYDEBUG(802, *YYCURSOR);
        yyleng = YYCURSOR - SCNG(yy_text);
-#line 2140 "Zend/zend_language_scanner.l"
+#line 2148 "Zend/zend_language_scanner.l"
        {
        int newline = 0;
 
@@ -7099,7 +7174,7 @@ nowdoc_scan_done:
        HANDLE_NEWLINES(yytext, yyleng - newline);
        return T_ENCAPSED_AND_WHITESPACE;
 }
-#line 7103 "Zend/zend_language_scanner.c"
+#line 7178 "Zend/zend_language_scanner.c"
 /* *********************************** */
 yyc_ST_VAR_OFFSET:
        {
@@ -7137,69 +7212,69 @@ yyc_ST_VAR_OFFSET:
                         32,  32,  32,  32,  32,  32,  32,  32, 
                         32,  32,  32,  32,  32,  32,  32,  32, 
                };
-               YYDEBUG(793, *YYCURSOR);
+               YYDEBUG(803, *YYCURSOR);
                YYFILL(3);
                yych = *YYCURSOR;
                if (yych <= '/') {
                        if (yych <= ' ') {
                                if (yych <= '\f') {
-                                       if (yych <= 0x08) goto yy807;
-                                       if (yych <= '\n') goto yy803;
-                                       goto yy807;
+                                       if (yych <= 0x08) goto yy817;
+                                       if (yych <= '\n') goto yy813;
+                                       goto yy817;
                                } else {
-                                       if (yych <= '\r') goto yy803;
-                                       if (yych <= 0x1F) goto yy807;
-                                       goto yy803;
+                                       if (yych <= '\r') goto yy813;
+                                       if (yych <= 0x1F) goto yy817;
+                                       goto yy813;
                                }
                        } else {
                                if (yych <= '$') {
-                                       if (yych <= '"') goto yy802;
-                                       if (yych <= '#') goto yy803;
-                                       goto yy798;
+                                       if (yych <= '"') goto yy812;
+                                       if (yych <= '#') goto yy813;
+                                       goto yy808;
                                } else {
-                                       if (yych == '\'') goto yy803;
-                                       goto yy802;
+                                       if (yych == '\'') goto yy813;
+                                       goto yy812;
                                }
                        }
                } else {
                        if (yych <= '\\') {
                                if (yych <= '@') {
-                                       if (yych <= '0') goto yy795;
-                                       if (yych <= '9') goto yy797;
-                                       goto yy802;
+                                       if (yych <= '0') goto yy805;
+                                       if (yych <= '9') goto yy807;
+                                       goto yy812;
                                } else {
-                                       if (yych <= 'Z') goto yy805;
-                                       if (yych <= '[') goto yy802;
-                                       goto yy803;
+                                       if (yych <= 'Z') goto yy815;
+                                       if (yych <= '[') goto yy812;
+                                       goto yy813;
                                }
                        } else {
                                if (yych <= '_') {
-                                       if (yych <= ']') goto yy800;
-                                       if (yych <= '^') goto yy802;
-                                       goto yy805;
+                                       if (yych <= ']') goto yy810;
+                                       if (yych <= '^') goto yy812;
+                                       goto yy815;
                                } else {
-                                       if (yych <= '`') goto yy802;
-                                       if (yych <= 'z') goto yy805;
-                                       if (yych <= '~') goto yy802;
-                                       goto yy805;
+                                       if (yych <= '`') goto yy812;
+                                       if (yych <= 'z') goto yy815;
+                                       if (yych <= '~') goto yy812;
+                                       goto yy815;
                                }
                        }
                }
-yy795:
-               YYDEBUG(795, *YYCURSOR);
+yy805:
+               YYDEBUG(805, *YYCURSOR);
                yyaccept = 0;
                yych = *(YYMARKER = ++YYCURSOR);
                if (yych <= 'W') {
-                       if (yych <= '/') goto yy796;
-                       if (yych <= '9') goto yy818;
+                       if (yych <= '/') goto yy806;
+                       if (yych <= '9') goto yy828;
                } else {
-                       if (yych <= 'X') goto yy816;
-                       if (yych == 'x') goto yy816;
+                       if (yych <= 'X') goto yy826;
+                       if (yych == 'x') goto yy826;
                }
-yy796:
-               YYDEBUG(796, *YYCURSOR);
+yy806:
+               YYDEBUG(806, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1356 "Zend/zend_language_scanner.l"
+#line 1364 "Zend/zend_language_scanner.l"
                { /* Offset could be treated as a long */
        if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
                zendlval->value.lval = strtol(yytext, NULL, 10);
@@ -7211,81 +7286,81 @@ yy796:
        }
        return T_NUM_STRING;
 }
-#line 7215 "Zend/zend_language_scanner.c"
-yy797:
-               YYDEBUG(797, *YYCURSOR);
+#line 7290 "Zend/zend_language_scanner.c"
+yy807:
+               YYDEBUG(807, *YYCURSOR);
                yych = *++YYCURSOR;
-               goto yy815;
-yy798:
-               YYDEBUG(798, *YYCURSOR);
+               goto yy825;
+yy808:
+               YYDEBUG(808, *YYCURSOR);
                ++YYCURSOR;
                if ((yych = *YYCURSOR) <= '_') {
-                       if (yych <= '@') goto yy799;
-                       if (yych <= 'Z') goto yy811;
-                       if (yych >= '_') goto yy811;
+                       if (yych <= '@') goto yy809;
+                       if (yych <= 'Z') goto yy821;
+                       if (yych >= '_') goto yy821;
                } else {
-                       if (yych <= '`') goto yy799;
-                       if (yych <= 'z') goto yy811;
-                       if (yych >= 0x7F) goto yy811;
+                       if (yych <= '`') goto yy809;
+                       if (yych <= 'z') goto yy821;
+                       if (yych >= 0x7F) goto yy821;
                }
-yy799:
-               YYDEBUG(799, *YYCURSOR);
+yy809:
+               YYDEBUG(809, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1666 "Zend/zend_language_scanner.l"
+#line 1674 "Zend/zend_language_scanner.l"
                {
        /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
        return yytext[0];
 }
-#line 7240 "Zend/zend_language_scanner.c"
-yy800:
-               YYDEBUG(800, *YYCURSOR);
+#line 7315 "Zend/zend_language_scanner.c"
+yy810:
+               YYDEBUG(810, *YYCURSOR);
                ++YYCURSOR;
-               YYDEBUG(801, *YYCURSOR);
+               YYDEBUG(811, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1661 "Zend/zend_language_scanner.l"
+#line 1669 "Zend/zend_language_scanner.l"
                {
        yy_pop_state(TSRMLS_C);
        return ']';
 }
-#line 7251 "Zend/zend_language_scanner.c"
-yy802:
-               YYDEBUG(802, *YYCURSOR);
+#line 7326 "Zend/zend_language_scanner.c"
+yy812:
+               YYDEBUG(812, *YYCURSOR);
                yych = *++YYCURSOR;
-               goto yy799;
-yy803:
-               YYDEBUG(803, *YYCURSOR);
+               goto yy809;
+yy813:
+               YYDEBUG(813, *YYCURSOR);
                ++YYCURSOR;
-               YYDEBUG(804, *YYCURSOR);
+               YYDEBUG(814, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1671 "Zend/zend_language_scanner.l"
+#line 1679 "Zend/zend_language_scanner.l"
                {
        /* Invalid rule to return a more explicit parse error with proper line number */
        yyless(0);
        yy_pop_state(TSRMLS_C);
        return T_ENCAPSED_AND_WHITESPACE;
 }
-#line 7268 "Zend/zend_language_scanner.c"
-yy805:
-               YYDEBUG(805, *YYCURSOR);
+#line 7343 "Zend/zend_language_scanner.c"
+yy815:
+               YYDEBUG(815, *YYCURSOR);
                ++YYCURSOR;
                yych = *YYCURSOR;
-               goto yy810;
-yy806:
-               YYDEBUG(806, *YYCURSOR);
+               goto yy820;
+yy816:
+               YYDEBUG(816, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1678 "Zend/zend_language_scanner.l"
+#line 1686 "Zend/zend_language_scanner.l"
                {
        zend_copy_value(zendlval, yytext, yyleng);
        zendlval->type = IS_STRING;
        return T_STRING;
 }
-#line 7283 "Zend/zend_language_scanner.c"
-yy807:
-               YYDEBUG(807, *YYCURSOR);
+#line 7358 "Zend/zend_language_scanner.c"
+yy817:
+               YYDEBUG(817, *YYCURSOR);
                ++YYCURSOR;
-               YYDEBUG(808, *YYCURSOR);
+               YYDEBUG(818, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 2196 "Zend/zend_language_scanner.l"
+#line 2204 "Zend/zend_language_scanner.l"
                {
        if (YYCURSOR > YYLIMIT) {
                return 0;
@@ -7294,100 +7369,100 @@ yy807:
        zend_error(E_COMPILE_WARNING,"Unexpected character in input:  '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
        goto restart;
 }
-#line 7298 "Zend/zend_language_scanner.c"
-yy809:
-               YYDEBUG(809, *YYCURSOR);
+#line 7373 "Zend/zend_language_scanner.c"
+yy819:
+               YYDEBUG(819, *YYCURSOR);
                ++YYCURSOR;
                YYFILL(1);
                yych = *YYCURSOR;
-yy810:
-               YYDEBUG(810, *YYCURSOR);
+yy820:
+               YYDEBUG(820, *YYCURSOR);
                if (yybm[0+yych] & 32) {
-                       goto yy809;
+                       goto yy819;
                }
-               goto yy806;
-yy811:
-               YYDEBUG(811, *YYCURSOR);
+               goto yy816;
+yy821:
+               YYDEBUG(821, *YYCURSOR);
                ++YYCURSOR;
                YYFILL(1);
                yych = *YYCURSOR;
-               YYDEBUG(812, *YYCURSOR);
+               YYDEBUG(822, *YYCURSOR);
                if (yych <= '^') {
                        if (yych <= '9') {
-                               if (yych >= '0') goto yy811;
+                               if (yych >= '0') goto yy821;
                        } else {
-                               if (yych <= '@') goto yy813;
-                               if (yych <= 'Z') goto yy811;
+                               if (yych <= '@') goto yy823;
+                               if (yych <= 'Z') goto yy821;
                        }
                } else {
                        if (yych <= '`') {
-                               if (yych <= '_') goto yy811;
+                               if (yych <= '_') goto yy821;
                        } else {
-                               if (yych <= 'z') goto yy811;
-                               if (yych >= 0x7F) goto yy811;
+                               if (yych <= 'z') goto yy821;
+                               if (yych >= 0x7F) goto yy821;
                        }
                }
-yy813:
-               YYDEBUG(813, *YYCURSOR);
+yy823:
+               YYDEBUG(823, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1655 "Zend/zend_language_scanner.l"
+#line 1663 "Zend/zend_language_scanner.l"
                {
        zend_copy_value(zendlval, (yytext+1), (yyleng-1));
        zendlval->type = IS_STRING;
        return T_VARIABLE;
 }
-#line 7340 "Zend/zend_language_scanner.c"
-yy814:
-               YYDEBUG(814, *YYCURSOR);
+#line 7415 "Zend/zend_language_scanner.c"
+yy824:
+               YYDEBUG(824, *YYCURSOR);
                ++YYCURSOR;
                YYFILL(1);
                yych = *YYCURSOR;
-yy815:
-               YYDEBUG(815, *YYCURSOR);
+yy825:
+               YYDEBUG(825, *YYCURSOR);
                if (yybm[0+yych] & 64) {
-                       goto yy814;
+                       goto yy824;
                }
-               goto yy796;
-yy816:
-               YYDEBUG(816, *YYCURSOR);
+               goto yy806;
+yy826:
+               YYDEBUG(826, *YYCURSOR);
                yych = *++YYCURSOR;
                if (yybm[0+yych] & 128) {
-                       goto yy821;
+                       goto yy831;
                }
-               YYDEBUG(817, *YYCURSOR);
+               YYDEBUG(827, *YYCURSOR);
                YYCURSOR = YYMARKER;
-               goto yy796;
-yy818:
-               YYDEBUG(818, *YYCURSOR);
+               goto yy806;
+yy828:
+               YYDEBUG(828, *YYCURSOR);
                ++YYCURSOR;
                YYFILL(1);
                yych = *YYCURSOR;
-               YYDEBUG(819, *YYCURSOR);
-               if (yych <= '/') goto yy820;
-               if (yych <= '9') goto yy818;
-yy820:
-               YYDEBUG(820, *YYCURSOR);
+               YYDEBUG(829, *YYCURSOR);
+               if (yych <= '/') goto yy830;
+               if (yych <= '9') goto yy828;
+yy830:
+               YYDEBUG(830, *YYCURSOR);
                yyleng = YYCURSOR - SCNG(yy_text);
-#line 1368 "Zend/zend_language_scanner.l"
+#line 1376 "Zend/zend_language_scanner.l"
                { /* Offset must be treated as a string */
        zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
        zendlval->value.str.len = yyleng;
        zendlval->type = IS_STRING;
        return T_NUM_STRING;
 }
-#line 7379 "Zend/zend_language_scanner.c"
-yy821:
-               YYDEBUG(821, *YYCURSOR);
+#line 7454 "Zend/zend_language_scanner.c"
+yy831:
+               YYDEBUG(831, *YYCURSOR);
                ++YYCURSOR;
                YYFILL(1);
                yych = *YYCURSOR;
-               YYDEBUG(822, *YYCURSOR);
+               YYDEBUG(832, *YYCURSOR);
                if (yybm[0+yych] & 128) {
-                       goto yy821;
+                       goto yy831;
                }
-               goto yy820;
+               goto yy830;
        }
 }
-#line 2205 "Zend/zend_language_scanner.l"
+#line 2213 "Zend/zend_language_scanner.l"
 
 }
index 2857c873683bf0ec322ace570d5cc47e16736899..5c52ebaecdce7cdbfa4121822be234a4fe2373b7 100644 (file)
@@ -990,6 +990,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
        return T_INTERFACE;
 }
 
+<ST_IN_SCRIPTING>"trait" {
+       return T_TRAIT;
+}
+
 <ST_IN_SCRIPTING>"extends" {
        return T_EXTENDS;
 }
@@ -1108,6 +1112,10 @@ NEWLINE ("\r"|"\n"|"\r\n")
        return T_USE;
 }
 
+<ST_IN_SCRIPTING>"insteadof" {
+        return T_INSTEADOF;
+}
+
 <ST_IN_SCRIPTING>"global" {
        return T_GLOBAL;
 }
index b262ffc33abdcc7ef1d6ba8dc3faa40179d3076a..d506d9f974bb9a690e9ef0ecd0924559dd6a9fc3 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Tue Apr 20 15:11:14 2010 */
+/* Generated by re2c 0.13.5 on Thu Apr 22 23:49:41 2010 */
 #line 3 "Zend/zend_language_scanner_defs.h"
 
 enum YYCONDTYPE {
index 9e9b2f57679fec01ef461ab6c118baf509bc00db..2734379bcef4797f3905c498d3aa29ad917fefd3 100644 (file)
@@ -194,9 +194,50 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                        if (ce->num_interfaces > 0 && ce->interfaces) {
                                efree(ce->interfaces);
                        }
+            if (ce->num_traits > 0 && ce->traits) {
+               efree(ce->traits);
+            }
                        if (ce->doc_comment) {
                                efree(ce->doc_comment);
                        }
+                       if (ce->trait_aliases) {
+                               size_t i = 0;
+                               while (ce->trait_aliases[i]) {
+                                       if (ce->trait_aliases[i]->trait_method) {
+                                               if (ce->trait_aliases[i]->trait_method->method_name) {
+                                                       efree(ce->trait_aliases[i]->trait_method->method_name);
+                                               }
+                                               if (ce->trait_aliases[i]->trait_method->class_name) {
+                                                       efree(ce->trait_aliases[i]->trait_method->class_name);
+                                               }
+                                               efree(ce->trait_aliases[i]->trait_method);
+                                       }
+                                       if (ce->trait_aliases[i]->alias) {
+                                               efree(ce->trait_aliases[i]->alias);
+                                       }
+                                       efree(ce->trait_aliases[i]);
+                                       i++;
+                               }
+                               efree(ce->trait_aliases);
+                       }
+                       
+                       if (ce->trait_precedences) {
+                               size_t i = 0;
+                               while (ce->trait_precedences[i]) {
+                                       efree(ce->trait_precedences[i]->trait_method->method_name);
+                                       efree(ce->trait_precedences[i]->trait_method->class_name);
+                                       efree(ce->trait_precedences[i]->trait_method);
+                                       
+                                       if (ce->trait_precedences[i]->exclude_from_classes) {
+                                               efree(ce->trait_precedences[i]->exclude_from_classes);
+                                       }
+                                       
+                                       efree(ce->trait_precedences[i]);
+                                       i++;
+                               }
+                               efree(ce->trait_precedences);
+                       }
+                       
                        efree(ce);
                        break;
                case ZEND_INTERNAL_CLASS:
index 953f58a74c57080d86a2f3932634ef4df6c62b81..e1ecc8e5a5e94e0372b7aabf3c344c7bcc0134eb 100644 (file)
@@ -4638,6 +4638,34 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST)
        ZEND_VM_NEXT_OPCODE();
 }
 
+ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY)
+{
+       zend_op *opline = EX(opline);
+       zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+       zend_class_entry *trait = zend_fetch_class(Z_STRVAL_P(opline->op2.zv),
+                                             Z_STRLEN_P(opline->op2.zv),
+                                             opline->extended_value TSRMLS_CC);
+       
+       if (trait) {
+               if (!(trait->ce_flags & ZEND_ACC_TRAIT)) {
+                       zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name, trait->name);
+               }
+               zend_do_implement_trait(ce, trait TSRMLS_CC);
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(155, ZEND_BIND_TRAITS, ANY, ANY)
+{
+       zend_op *opline = EX(opline);
+       zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+       
+       zend_do_bind_traits(ce TSRMLS_CC);
+       
+       ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
 {
        zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
index e48b807eea01b0ccfbe976f784a95fbd1c11afd7..5e8b812efa85c20dd8b446d1f89413a653f04294 100644 (file)
@@ -681,6 +681,34 @@ static int ZEND_FASTCALL  ZEND_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL  ZEND_ADD_TRAIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+       zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+       zend_class_entry *trait = zend_fetch_class(Z_STRVAL_P(opline->op2.zv),
+                                             Z_STRLEN_P(opline->op2.zv),
+                                             opline->extended_value TSRMLS_CC);
+
+       if (trait) {
+               if (!(trait->ce_flags & ZEND_ACC_TRAIT)) {
+                       zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name, trait->name);
+               }
+               zend_do_implement_trait(ce, trait TSRMLS_CC);
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_BIND_TRAITS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+       zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
+
+       zend_do_bind_traits(ce TSRMLS_CC);
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
@@ -36648,6 +36676,56 @@ void zend_init_opcodes_handlers(void)
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_ADD_TRAIT_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
+       ZEND_BIND_TRAITS_SPEC_HANDLER,
        ZEND_NULL_HANDLER
   };
   zend_opcode_handlers = (opcode_handler_t*)labels;
index 10225c427c88d79596c693877a6a5266325b9bbd..7cd8add0f844a25b166ca3100b373ec25d4371fe 100644 (file)
 #define ZEND_USER_OPCODE                     150
 #define ZEND_JMP_SET                         152
 #define ZEND_DECLARE_LAMBDA_FUNCTION         153
+#define ZEND_ADD_TRAIT                       154
+#define ZEND_BIND_TRAITS                     155