Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implemented Traits for PHP as proposed in the RFC [TRAITS]

# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
# 
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
# 
# Internals of the Traits Patch
# -----------------------------
# 
# Open TODOs
# """"""""""
# 
# - Reflection API
# - support for traits for internal classes
#   - currently destroy_zend_class does not handle that case 
# 
# Introduced Structures
# """""""""""""""""""""
# 
# Data structures to encode the composition information specified in the
# source:
#  - zend_trait_method_reference
#  - zend_trait_precedence
#  - zend_trait_alias
# 
# Changes
# """""""
# 
# zend_class_entry
#  - uses NULL terminated lists of pointers for
#    - trait_aliases
#    - trait_precedences
#    - do you prefer an explicit counter?
#    - the information is only necessary during class composition
#      but might be interesting for reflection
#    - did not want to blow up class further with not really necessary length counters
# 
# added keywords
#   - trait
#   - insteadof
# 
# Added opcodes
#  ZEND_ADD_TRAIT
#    - similar to ZEND_ADD_INTERFACE
#    - adds the trait to the list of traits of a class, no actual composition done
#  ZEND_BIND_TRAITS
#    - emitted in zend_do_end_class_declaration
#    - concludes the class definition and will initiate the trait composition
#      when the class definition is encountered during runtime
# 
# Added Flags
#   ZEND_ACC_TRAIT = 0x120
#   ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
#   ZEND_FETCH_CLASS_TRAIT = 14
# 
# zend_vm_execute.h
#  - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
#    ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
# 
# zend_compile.c
#  - refactored do_inherit_method_check
#    split into do_inherit_method_check and do_inheritance_check_on_method
#  - added helper functions use a '_' as prefix and are not mentioned in the
#    headers
#  - _copy_functions
#    prepare hash-maps of functions which should be merged into a class
#    here the aliases are handled
#  - _merge_functions
#    builds a hash-table of the methods which need to be added to a class
#    does the conflict detection
#  - reused php_runkit_function_copy_ctor
#    - it is not identical with the original code anymore, needed to update it
#      think I fixed some bugs, not sure whether all have been reported back to runkit
#    - has to be renamed, left the name for the moment, to make its origin obvious
#    - here might be optimization potential
#    - not sure whether everything needs to be copied
#      - copying the literals might be broken
#        - added it since the literals array is freed by efree and gave problems
#          with doubled frees
#      - all immutable parts of the zend_op array should not be copied
#        - am not sure which parts are immutable
#        - and not sure how to avoid doubled frees on the same arrays on shutdown
#  - _merge_functions_to_class
#    does the final merging with the target class to handle inherited
#    and overridden methods
#  - small helper for NULL terminated lists
#    zend_init_list, zend_add_to_list
# 
# zend_language_parser.y
#  - reused class definition for traits
#    - there should be something with regard to properties
#      - if they get explicitly defined, it might be worthwhile to
#        check that there are no collisions with other traits in a composition
#        (however, I would not introduce elaborate language features to control that
#         but a notice for such conflicts might be nice to the developers)
  • Loading branch information...
commit cd6415f1a93ae5169e9ab92dfa384af29c1a1d87 1 parent 05a9649
Stefan Marr authored
View
43 Zend/zend.h
@@ -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;
View
736 Zend/zend_compile.c
@@ -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;
View
27 Zend/zend_compile.h
@@ -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
View
4 Zend/zend_execute_API.c
@@ -1561,7 +1561,9 @@ zend_class_entry *zend_fetch_class(const char *class_name, uint class_name_len,
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);
}
}
View
60 Zend/zend_language_parser.y
@@ -113,6 +113,7 @@
%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
@@ -121,6 +122,7 @@
%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; }
View
1,765 Zend/zend_language_scanner.c
@@ -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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
++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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
}
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 @@ int lex_scan(zval *zendlval TSRMLS_DC)
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);