]> granicus.if.org Git - php/commitdiff
Improve parser handling of 'abstract'
authorZeev Suraski <zeev@php.net>
Tue, 11 Feb 2003 09:48:37 +0000 (09:48 +0000)
committerZeev Suraski <zeev@php.net>
Tue, 11 Feb 2003 09:48:37 +0000 (09:48 +0000)
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y

index d273ed9870f273a988710f741c5282ec055c75a2..c25b64bef6aad88c9749998f2f9607bb289ba39f 100644 (file)
@@ -367,13 +367,24 @@ void zend_do_echo(znode *arg TSRMLS_DC)
        SET_UNUSED(opline->op2);
 }
 
-void zend_do_abstract_method(TSRMLS_D)
+void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC)
 {
-       zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+       if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) {
+               if (body->u.constant.value.lval & ZEND_ACC_ABSTRACT) {
+                       zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
-       SET_UNUSED(opline->op1);
-       SET_UNUSED(opline->op2);
+                       opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
+                       SET_UNUSED(opline->op1);
+                       SET_UNUSED(opline->op2);
+               } else {
+                       /* we had code in the function body */
+                       zend_error(E_COMPILE_ERROR, "Abstract function %s() cannot contain body", function_name->u.constant.value.str.val);
+               }
+       } else {
+               if (body->u.constant.value.lval & ZEND_ACC_ABSTRACT) {
+                       zend_error(E_COMPILE_ERROR, "Non-abstract method %s() must contain body", function_name->u.constant.value.str.val);
+               }
+       }
 }
 
 
@@ -899,7 +910,8 @@ void zend_do_free(znode *op1 TSRMLS_DC)
 
 int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier)
 {
-       if ((new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK)
+       if ((current_access_type->u.constant.value.lval & ZEND_ACC_PPP_MASK)
+               && (new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK)
                && ((current_access_type->u.constant.value.lval & ZEND_ACC_PPP_MASK) != (new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK))) {
                zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
        }
@@ -2180,6 +2192,10 @@ void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_ty
        zend_property_info *existing_property_info;
        HashTable *target_symbol_table;
 
+       if (access_type & ZEND_ACC_ABSTRACT) {
+               zend_error(E_COMPILE_ERROR, "Properties cannot be declared abstract");
+       }
+
        if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) {
                if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
                        zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
index 5e16be77da0a854bb6a11ef3d69492693309638d..ec82fe727a834a43b34dcbe6f2aa360bf1269068 100644 (file)
@@ -421,7 +421,7 @@ void zend_do_begin_import(TSRMLS_D);
 void zend_do_import(int type, znode *what TSRMLS_DC);
 void zend_do_end_import(znode *import_from TSRMLS_DC);
 
-void zend_do_abstract_method(TSRMLS_D);
+void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC);
 
 ZEND_API void function_add_ref(zend_function *function);
 
index 2310a655af53d05c89525cfdb71f1d93dd87cbae..4dc5ba8b686b36287bba851a39229cb56033f3df 100644 (file)
@@ -445,32 +445,37 @@ class_statement:
                variable_modifiers { CG(access_type) = $1.u.constant.value.lval; } class_variable_declaration ';'
        |       class_constant_declaration ';'
        |       method_modifiers T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' 
-                       parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); }
-       |       T_ABSTRACT method_modifiers T_FUNCTION { $3.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$3, &$6, 1, $5.op_type, $2.u.constant.value.lval | ZEND_ACC_ABSTRACT TSRMLS_CC); } '(' 
-                       parameter_list ')' { zend_do_abstract_method(TSRMLS_C); zend_do_end_function_declaration(&$3 TSRMLS_CC); } ';'
+                       parameter_list ')' method_body { zend_do_abstract_method(&$5, &$1, &$10 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
        |       T_CLASS T_STRING extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
 ;
 
+
+method_body:
+               ';' /* abstract method */               { $$.u.constant.value.lval = ZEND_ACC_ABSTRACT; }
+       |       '{' inner_statement_list '}'    { $$.u.constant.value.lval = 0; }
+;
+
 variable_modifiers:
-               non_empty_access_modifiers              { $$ = $1; }
+               non_empty_member_modifiers              { $$ = $1; }
        |       T_VAR                                                   { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; }
 ;
 
 method_modifiers:
                /* empty */                                                     { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; }
-       |       non_empty_access_modifiers                      { $$ = $1;  if (!($$.u.constant.value.lval & ZEND_ACC_PPP_MASK)) { $$.u.constant.value.lval |= ZEND_ACC_PUBLIC; } }
+       |       non_empty_member_modifiers                      { $$ = $1;  if (!($$.u.constant.value.lval & ZEND_ACC_PPP_MASK)) { $$.u.constant.value.lval |= ZEND_ACC_PUBLIC; } }
 ;
 
-non_empty_access_modifiers:
-               access_modifier                                         { $$ = $1; }
-       |       non_empty_access_modifiers access_modifier      { $$.u.constant.value.lval = zend_do_verify_access_types(&$1, &$2); }
+non_empty_member_modifiers:
+               member_modifier                                         { $$ = $1; }
+       |       non_empty_member_modifiers member_modifier      { $$.u.constant.value.lval = zend_do_verify_access_types(&$1, &$2); }
 ;
 
-access_modifier:
+member_modifier:
                T_PUBLIC                                { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; }
        |       T_PROTECTED                             { $$.u.constant.value.lval = ZEND_ACC_PROTECTED; }
        |       T_PRIVATE                               { $$.u.constant.value.lval = ZEND_ACC_PRIVATE; }
        |       T_STATIC                                { $$.u.constant.value.lval = ZEND_ACC_STATIC; }
+       |       T_ABSTRACT                              { $$.u.constant.value.lval = ZEND_ACC_ABSTRACT; }
 ;
 
 class_variable_declaration: