Stanislav Malyshev wrote:
>> Hold off for a bit - I may have a simple solution that solves the
>> problem for class names, method names and functions, have to code the
>> patch tonight first to prove it works.
>
> OK, please send it as soon as you have it :)
Hi,

The attached patch is for PHP 5.3, if it is acceptable, I will port it
to PHP 6, which is not difficult, although it does involve a lot of
cut/pasting.

The patch does these things:

1) fixes an unrelated bug I found in implementation of LSB - "static" is
not checked for in zend_do_import()/zend_do_namespace() and other places
that we check for "self" and "parent"
2) fixes a rather serious error in the fix for Bug #42859 - missing
parens in zend_do_import()
3) adds "import" and "namespace" as valid function/class names
4) allows any string for method names, just as we allow any string for
variable names
5) fixes a bug in logic for $class->list where $class-> list (note the
whitespace between -> and list) returns a T_LIST instead of T_STRING
6) It allows "import ::Classname as Blah" which is currently a parse error
7) class constants are unchanged - reserved words still error out.

Note that the zend_compile.c fixes can all be committed directly as they
are all bugfixes and not related to the import/namespace/reserved words fix.

To implement this, I added several states to the lexer in order to
return T_STRING whenever possible, which is after T_NEW, T_INTERFACE,
T_CLASS, T_EXTENDS and in the T_IMPLEMENTS list.  In addition, after
T_FUNCTION outside of a class, it returns T_STRING for "import" and
"namespace" but no other reserved words.  After T_FUNCTION inside of a
class (method declaration), it returns T_STRING for all possible
strings.  After :: or -> T_STRING is always returned.  Also, rather than
take the approach LSB does with T_STATIC, I have the lexer initialize
the string value of T_IMPORT and T_NAMESPACE so we can preserve case for
autoloading needs.  The parser frees the unused char * when normal
import/namespace declarations are called.

In the parser, I use fully_qualified_class_name instead of
namespace_name for both import syntaxes.  This introduces a minor issue
in that this is no longer a parse error:

import static::oops as Classname;

However, if "Classname" is used, this will simply result in "Fatal
error: Class 'static::oops' not found in..." and shouldn't be too big of
a deal.  Also in the parser, I inserted T_IMPORT and T_NAMESPACE as
aliases to T_STRING in global situations to allow for static method
calls, class constants, and fully-qualified namespace calls.

Basically this script is now possible with the patch:

<?php
namespace import;
import ::Exception as Test;
function import() {echo 'import function';}
interface import {}
interface fooey {}
class Exception extends ::Exception implements fooey, import {}
class namespace {
    const HI = 3;
    function list() {echo __METHOD__;}
}
import();
var_dump(namespace::HI);
namespace::list();
?>

and results in this output:

[EMAIL PROTECTED]:~/workspace/php5$ sapi/cli/php -n testme.php
import functionint(3)
import::namespace::list

I have not performed profiling on the patch, instead focusing on
correctness for now.

The patch looks complicated because of the additional states, but is
really not that complicated, honest.

:)
Greg
? Zend/tests/zend_function_name.phpt
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.41.2.10
diff -u -r1.647.2.27.2.41.2.10 zend_compile.c
--- Zend/zend_compile.c 17 Oct 2007 10:01:21 -0000      1.647.2.27.2.41.2.10
+++ Zend/zend_compile.c 23 Oct 2007 03:15:41 -0000
@@ -2975,7 +2975,7 @@
 
        lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, 
class_name->u.constant.value.str.len);
 
-       if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
+       if (!(strcmp(lcname, "self") && strcmp(lcname, "parent") && 
strcmp(lcname, "static"))) {
                efree(lcname);
                zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as 
it is reserved", class_name->u.constant.value.str.val);
        }
@@ -4582,7 +4582,9 @@
        if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
              !memcmp(lcname, "self", sizeof("self")-1)) ||
            ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
-          !memcmp(lcname, "parent", sizeof("parent")-1))) {
+          !memcmp(lcname, "parent", sizeof("parent")-1)) ||
+           ((Z_STRLEN(name->u.constant) == sizeof("static")-1) &&
+          !memcmp(lcname, "static", sizeof("static")-1))) {
                zend_error(E_COMPILE_ERROR, "Cannot use '%s' as namespace 
name", Z_STRVAL(name->u.constant));
        }
        efree(lcname);
@@ -4596,7 +4598,7 @@
 {
        char *lcname;
        zval *name, *ns, tmp;
-       zend_bool warn = 0;
+       zend_bool warn = 0, shorthand = 0;
 
        if (!CG(current_import)) {
                CG(current_import) = emalloc(sizeof(HashTable));
@@ -4611,11 +4613,12 @@
                char *p;
 
                /* The form "import A::B" is eqivalent to "import A::B as B".
-                  So we extract the last part of compound name ti use as a 
new_name */
+                  So we extract the last part of compound name to use as a 
new_name */
                name = &tmp;
                p = zend_memrchr(Z_STRVAL_P(ns), ':', Z_STRLEN_P(ns));
                if (p) {
                        ZVAL_STRING(name, p+1, 1);
+                       shorthand = 1;
                } else {
                        *name = *ns;
                        zval_copy_ctor(name);
@@ -4627,6 +4630,8 @@
 
        if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
           !memcmp(lcname, "self", sizeof("self")-1)) ||
+           ((Z_STRLEN_P(name) == sizeof("static")-1) &&
+          !memcmp(lcname, "static", sizeof("static")-1)) ||
            ((Z_STRLEN_P(name) == sizeof("parent")-1) &&
           !memcmp(lcname, "parent", sizeof("parent")-1))) {
                zend_error(E_COMPILE_ERROR, "Cannot use '%s' as import name", 
Z_STRVAL_P(name));
@@ -4640,7 +4645,8 @@
                ns_name[Z_STRLEN_P(CG(current_namespace))] = ':';
                ns_name[Z_STRLEN_P(CG(current_namespace))+1] = ':';
                memcpy(ns_name+Z_STRLEN_P(CG(current_namespace))+2, lcname, 
Z_STRLEN_P(name)+1);
-               if (zend_hash_exists(CG(class_table), ns_name, 
Z_STRLEN_P(CG(current_namespace)) + 2 + Z_STRLEN_P(name)+1)) {
+               /* if our new import name is simply the shorthand, skip this 
check */
+               if ((!shorthand || !memcmp(ns_name, Z_STRVAL_P(ns), 
Z_STRLEN_P(ns) + 1)) && zend_hash_exists(CG(class_table), ns_name, 
Z_STRLEN_P(CG(current_namespace)) + 2 + Z_STRLEN_P(name)+1)) {
                        zend_error(E_COMPILE_ERROR, "Import name '%s' conflicts 
with defined class", Z_STRVAL_P(name));
                }
                efree(ns_name);
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.4.2.8.2.4
diff -u -r1.160.2.4.2.8.2.4 zend_language_parser.y
--- Zend/zend_language_parser.y 1 Oct 2007 10:37:13 -0000       
1.160.2.4.2.8.2.4
+++ Zend/zend_language_parser.y 23 Oct 2007 03:15:41 -0000
@@ -47,7 +47,7 @@
 %}
 
 %pure_parser
-%expect 2
+%expect 3
 
 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
 %left ','
@@ -142,7 +142,7 @@
 %token T_END_HEREDOC
 %token T_DOLLAR_OPEN_CURLY_BRACES
 %token T_CURLY_OPEN
-%token T_PAAMAYIM_NEKUDOTAYIM
+%left T_PAAMAYIM_NEKUDOTAYIM
 %token T_NAMESPACE
 %token T_IMPORT
 %token T_NS_C
@@ -160,6 +160,8 @@
 
 namespace_name:
                T_STRING { $$ = $1; }
+       |       T_IMPORT { $$ = $1; }
+       |       T_NAMESPACE { $$ = $1; }
        |       namespace_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { 
zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
 ;
 
@@ -168,9 +170,9 @@
        |       function_declaration_statement  { 
zend_do_early_binding(TSRMLS_C); }
        |       class_declaration_statement             { 
zend_do_early_binding(TSRMLS_C); }
        |       T_HALT_COMPILER '(' ')' ';'             { 
zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
-       |       T_NAMESPACE namespace_name ';'  { zend_do_namespace(&$2 
TSRMLS_CC); }
-       |       T_IMPORT namespace_name ';'             { zend_do_import(&$2, 
NULL TSRMLS_CC); }
-       |       T_IMPORT namespace_name T_AS T_STRING ';'       { 
zend_do_import(&$2, &$4 TSRMLS_CC); }
+       |       T_NAMESPACE namespace_name ';'  { 
efree($1.u.constant.value.str.val);zend_do_namespace(&$2 TSRMLS_CC); }
+       |       T_IMPORT fully_qualified_class_name ';'         { 
efree($1.u.constant.value.str.val);zend_do_import(&$2, NULL TSRMLS_CC); }
+       |       T_IMPORT fully_qualified_class_name T_AS function_name_token 
';'        { efree($1.u.constant.value.str.val);zend_do_import(&$2, &$4 
TSRMLS_CC); }
        |       constant_declaration ';'
 ;
 
@@ -298,6 +300,12 @@
                        '(' parameter_list ')' '{' inner_statement_list '}' { 
zend_do_end_function_declaration(&$1 TSRMLS_CC); }
 ;
 
+function_name_token:
+               T_STRING { $$ = $1; }
+       |       T_NAMESPACE { $$ = $1; }
+       |       T_IMPORT { $$ = $1; }
+;
+
 unticked_class_declaration_statement:
                class_entry_type T_STRING extends_from
                        { zend_do_begin_class_declaration(&$1, &$2, &$3 
TSRMLS_CC); }
@@ -636,7 +644,7 @@
 ;
 
 function_call:
-               T_STRING        '(' { $2.u.opline_num = 
zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
+               function_name_token     '(' { $2.u.opline_num = 
zend_do_begin_function_call(&$1, 1 TSRMLS_CC); }
                                function_call_parameter_list
                                ')' { zend_do_end_function_call(&$1, &$$, &$4, 
0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
        |       T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $3.u.opline_num = 
zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
@@ -661,6 +669,8 @@
 
 fully_qualified_class_name:
                T_STRING { $$ = $1; }
+       |       T_IMPORT { $$ = $1; }
+       |       T_NAMESPACE { $$ = $1; }
        |       T_STATIC { $$.op_type = IS_CONST; ZVAL_STRINGL(&$$.u.constant, 
"static", sizeof("static")-1, 1);}
        |       T_PAAMAYIM_NEKUDOTAYIM T_STRING { 
zend_do_build_namespace_name(&$$, NULL, &$2 TSRMLS_CC); }
        |       fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { 
zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
Index: Zend/zend_language_scanner.l
===================================================================
RCS file: /repository/ZendEngine2/zend_language_scanner.l,v
retrieving revision 1.131.2.11.2.13.2.2
diff -u -r1.131.2.11.2.13.2.2 zend_language_scanner.l
--- Zend/zend_language_scanner.l        7 Oct 2007 05:22:03 -0000       
1.131.2.11.2.13.2.2
+++ Zend/zend_language_scanner.l        23 Oct 2007 03:15:42 -0000
@@ -45,6 +45,11 @@
 %x ST_COMMENT
 %x ST_DOC_COMMENT
 %x ST_ONE_LINE_COMMENT
+%x ST_LOOKING_FOR_CLASSNAME
+%x ST_LOOKING_FOR_EXTENDS
+%x ST_LOOKING_FOR_IMPLEMENTS
+%x ST_LOOKING_FOR_FUNCTION_NAME
+%x ST_LOOKING_FOR_METHOD_NAME
 %option stack
 
 %{
@@ -969,143 +974,172 @@
 %option noyywrap
 %%
 
-<ST_IN_SCRIPTING>"exit" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"exit"
 {
        return T_EXIT;
 }
 
-<ST_IN_SCRIPTING>"die" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"die"
 {
        return T_EXIT;
 }
 
 <ST_IN_SCRIPTING>"function" {
+       if (CG(active_class_entry)) {
+               yy_push_state(ST_LOOKING_FOR_METHOD_NAME TSRMLS_CC);
+       } else {
+               yy_push_state(ST_LOOKING_FOR_FUNCTION_NAME TSRMLS_CC);
+       }
+       return T_FUNCTION;
+}
+
+<ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"function"
 {
        return T_FUNCTION;
 }
 
-<ST_IN_SCRIPTING>"const" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"const"
 {
        return T_CONST;
 }
 
-<ST_IN_SCRIPTING>"return" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"return"
 {
        return T_RETURN;
 }
 
-<ST_IN_SCRIPTING>"try" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"try"
 {
        return T_TRY;
 }
 
-<ST_IN_SCRIPTING>"catch" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"catch"
 {
        return T_CATCH;
 }
 
-<ST_IN_SCRIPTING>"throw" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"throw"
 {
        return T_THROW;
 }
 
-<ST_IN_SCRIPTING>"if" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"if"
 {
        return T_IF;
 }
 
-<ST_IN_SCRIPTING>"elseif" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"elseif"
 {
        return T_ELSEIF;
 }
 
-<ST_IN_SCRIPTING>"endif" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"endif"
 {
        return T_ENDIF;
 }
 
-<ST_IN_SCRIPTING>"else" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"else"
 {
        return T_ELSE;
 }
 
-<ST_IN_SCRIPTING>"while" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"while"
 {
        return T_WHILE;
 }
 
-<ST_IN_SCRIPTING>"endwhile" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"endwhile"
 {
        return T_ENDWHILE;
 }
 
-<ST_IN_SCRIPTING>"do" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"do"
 {
        return T_DO;
 }
 
-<ST_IN_SCRIPTING>"for" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"for"
 {
        return T_FOR;
 }
 
-<ST_IN_SCRIPTING>"endfor" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"endfor"
 {
        return T_ENDFOR;
 }
 
-<ST_IN_SCRIPTING>"foreach" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"foreach"
 {
        return T_FOREACH;
 }
 
-<ST_IN_SCRIPTING>"endforeach" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"endforeach"
 {
        return T_ENDFOREACH;
 }
 
-<ST_IN_SCRIPTING>"declare" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"declare"
 {
        return T_DECLARE;
 }
 
-<ST_IN_SCRIPTING>"enddeclare" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"enddeclare"
 {
        return T_ENDDECLARE;
 }
 
-<ST_IN_SCRIPTING>"instanceof" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"instanceof"
 {
        return T_INSTANCEOF;
 }
 
-<ST_IN_SCRIPTING>"as" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"as"
 {
        return T_AS;
 }
 
-<ST_IN_SCRIPTING>"switch" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"switch"
 {
        return T_SWITCH;
 }
 
-<ST_IN_SCRIPTING>"endswitch" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"endswitch"
 {
        return T_ENDSWITCH;
 }
 
-<ST_IN_SCRIPTING>"case" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"case"
 {
        return T_CASE;
 }
 
-<ST_IN_SCRIPTING>"default" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"default"
 {
        return T_DEFAULT;
 }
 
-<ST_IN_SCRIPTING>"break" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"break"
 {
        return T_BREAK;
 }
 
-<ST_IN_SCRIPTING>"continue" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"continue"
 {
        return T_CONTINUE;
 }
 
-<ST_IN_SCRIPTING>"echo" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"echo"
 {
        return T_ECHO;
 }
 
-<ST_IN_SCRIPTING>"print" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"print"
 {
        return T_PRINT;
 }
 
 <ST_IN_SCRIPTING>"class" {
+       yy_push_state(ST_LOOKING_FOR_CLASSNAME TSRMLS_CC);
+       return T_CLASS;
+}
+
+<ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"class"
 {
        return T_CLASS;
 }
 
 <ST_IN_SCRIPTING>"interface" {
+       yy_push_state(ST_LOOKING_FOR_CLASSNAME TSRMLS_CC);
+       return T_INTERFACE;
+}
+
+<ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"interface"
 {
        return T_INTERFACE;
 }
 
 <ST_IN_SCRIPTING>"extends" {
+       yy_push_state(ST_LOOKING_FOR_EXTENDS TSRMLS_CC);
+       return T_EXTENDS;
+}
+
+<ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"extends"
 {
        return T_EXTENDS;
 }
 
 <ST_IN_SCRIPTING>"implements" {
+       yy_push_state(ST_LOOKING_FOR_IMPLEMENTS TSRMLS_CC);
+       return T_IMPLEMENTS;
+}
+
+<ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"implements"
 {
        return T_IMPLEMENTS;
 }
 
@@ -1118,31 +1152,47 @@
        return T_OBJECT_OPERATOR;
 }
 
-<ST_LOOKING_FOR_PROPERTY>{LABEL} {
+<ST_LOOKING_FOR_METHOD_NAME>'&' {
+       return '&';
+}
+
+<ST_LOOKING_FOR_PROPERTY,ST_LOOKING_FOR_METHOD_NAME>{WHITESPACE} {
+       zendlval->value.str.val = yytext; /* no copying - intentional */
+       zendlval->value.str.len = yyleng;
+       zendlval->type = IS_STRING;
+       HANDLE_NEWLINES(yytext, yyleng);
+       return T_WHITESPACE;
+}
+
+<ST_LOOKING_FOR_PROPERTY,ST_LOOKING_FOR_METHOD_NAME>{LABEL} {
        yy_pop_state(TSRMLS_C);
        zend_copy_value(zendlval, yytext, yyleng);
        zendlval->type = IS_STRING;
        return T_STRING;
 }
 
-<ST_LOOKING_FOR_PROPERTY>{ANY_CHAR} {
+<ST_LOOKING_FOR_PROPERTY,ST_LOOKING_FOR_METHOD_NAME>{ANY_CHAR} {
        yyless(0);
        yy_pop_state(TSRMLS_C);
 }
 
 <ST_IN_SCRIPTING>"::" {
+       yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
        return T_PAAMAYIM_NEKUDOTAYIM;
 }
 
 <ST_IN_SCRIPTING>"new" {
+       yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
        return T_NEW;
 }
 
-<ST_IN_SCRIPTING>"clone" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"clone"
 {
+       zend_copy_value(zendlval, yytext, yyleng);
+       zendlval->type = IS_STRING;
        return T_CLONE;
 }
 
-<ST_IN_SCRIPTING>"var" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"var"
 {
        return T_VAR;
 }
 
@@ -1178,79 +1228,83 @@
        return T_UNSET_CAST;
 }
 
-<ST_IN_SCRIPTING>"eval" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"eval"
 {
        return T_EVAL;
 }
 
-<ST_IN_SCRIPTING>"include" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"include"
 {
        return T_INCLUDE;
 }
 
-<ST_IN_SCRIPTING>"include_once" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"include_once"
 {
        return T_INCLUDE_ONCE;
 }
 
-<ST_IN_SCRIPTING>"require" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"require"
 {
        return T_REQUIRE;
 }
 
-<ST_IN_SCRIPTING>"require_once" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"require_once"
 {
        return T_REQUIRE_ONCE;
 }
 
 <ST_IN_SCRIPTING>"namespace" {
+       zend_copy_value(zendlval, yytext, yyleng);
+       zendlval->type = IS_STRING;
        return T_NAMESPACE;
 }
 
 <ST_IN_SCRIPTING>"import" {
+       zend_copy_value(zendlval, yytext, yyleng);
+       zendlval->type = IS_STRING;
        return T_IMPORT;
 }
 
-<ST_IN_SCRIPTING>"use" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"use"
 {
        return T_USE;
 }
 
-<ST_IN_SCRIPTING>"global" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"global"
 {
        return T_GLOBAL;
 }
 
-<ST_IN_SCRIPTING>"isset" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"isset"
 {
        return T_ISSET;
 }
 
-<ST_IN_SCRIPTING>"empty" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"empty"
 {
        return T_EMPTY;
 }
 
-<ST_IN_SCRIPTING>"__halt_compiler" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"__halt_compiler"
 {
        return T_HALT_COMPILER;
 }
 
-<ST_IN_SCRIPTING>"static" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"static"
 {
        return T_STATIC;
 }
 
-<ST_IN_SCRIPTING>"abstract" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"abstract"
 {
        return T_ABSTRACT;
 }
 
-<ST_IN_SCRIPTING>"final" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"final"
 {
        return T_FINAL;
 }
 
-<ST_IN_SCRIPTING>"private" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"private"
 {
        return T_PRIVATE;
 }
 
-<ST_IN_SCRIPTING>"protected" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"protected"
 {
        return T_PROTECTED;
 }
 
-<ST_IN_SCRIPTING>"public" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"public"
 {
        return T_PUBLIC;
 }
 
-<ST_IN_SCRIPTING>"unset" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"unset"
 {
        return T_UNSET;
 }
 
@@ -1258,11 +1312,11 @@
        return T_DOUBLE_ARROW;
 }
 
-<ST_IN_SCRIPTING>"list" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"list"
 {
        return T_LIST;
 }
 
-<ST_IN_SCRIPTING>"array" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"array"
 {
        return T_ARRAY;
 }
 
@@ -1480,7 +1534,7 @@
        return T_DNUMBER;
 }
 
-<ST_IN_SCRIPTING>"__CLASS__" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"__CLASS__"
 {
        char *class_name = NULL;
 
        if (CG(active_class_entry)) {
@@ -1496,7 +1550,7 @@
        return T_CLASS_C;
 }
 
-<ST_IN_SCRIPTING>"__FUNCTION__" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"__FUNCTION__"
 {
        char *func_name = NULL;
 
        if (CG(active_op_array)) {
@@ -1512,7 +1566,7 @@
        return T_FUNC_C;
 }
 
-<ST_IN_SCRIPTING>"__METHOD__" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"__METHOD__"
 {
        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;
        size_t len = 0;
@@ -1533,13 +1587,13 @@
        return T_METHOD_C;
 }
 
-<ST_IN_SCRIPTING>"__LINE__" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"__LINE__"
 {
        zendlval->value.lval = CG(zend_lineno);
        zendlval->type = IS_LONG;
        return T_LINE;
 }
 
-<ST_IN_SCRIPTING>"__FILE__" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"__FILE__"
 {
        char *filename = zend_get_compiled_filename(TSRMLS_C);
 
        if (!filename) {
@@ -1551,7 +1605,7 @@
        return T_FILE;
 }
 
-<ST_IN_SCRIPTING>"__NAMESPACE__" {
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>"__NAMESPACE__"
 {
        if (CG(current_namespace)) {
                *zendlval = *CG(current_namespace);
                zval_copy_ctor(zendlval);
@@ -1561,6 +1615,38 @@
        return T_NS_C;
 }
 
+<ST_LOOKING_FOR_IMPLEMENTS>"," {
+       return ',';
+}
+
+<ST_LOOKING_FOR_FUNCTION_NAME>"&" {
+       return '&';
+}
+
+<ST_LOOKING_FOR_IMPLEMENTS>"::" {
+       return T_PAAMAYIM_NEKUDOTAYIM;
+}
+
+<ST_LOOKING_FOR_IMPLEMENTS,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME>{WHITESPACE}
 {
+       zendlval->value.str.val = yytext; /* no copying - intentional */
+       zendlval->value.str.len = yyleng;
+       zendlval->type = IS_STRING;
+       HANDLE_NEWLINES(yytext, yyleng);
+       return T_WHITESPACE;
+}
+
+<ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_FUNCTION_NAME,ST_LOOKING_FOR_IMPLEMENTS>{LABEL}
 {
+       yy_pop_state(TSRMLS_C);
+       zend_copy_value(zendlval, yytext, yyleng);
+       zendlval->type = IS_STRING;
+       return T_STRING;
+}
+
+<ST_LOOKING_FOR_FUNCTION_NAME,ST_LOOKING_FOR_CLASSNAME,ST_LOOKING_FOR_EXTENDS,ST_LOOKING_FOR_IMPLEMENTS>{ANY_CHAR}
 {
+       yyless(0);
+       yy_pop_state(TSRMLS_C);
+}
+
 <INITIAL>(([^<]|"<"[^?%s<]){1,400})|"<s"|"<" {
 #ifdef ZEND_MULTIBYTE
        if (SCNG(output_filter)) {
@@ -1693,7 +1779,6 @@
        return T_STRING;
 }
 
-
 <ST_IN_SCRIPTING>{WHITESPACE} {
        zendlval->value.str.val = yytext; /* no copying - intentional */
        zendlval->value.str.len = yyleng;

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to