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