summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2012-08-01 08:29:21 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2012-08-01 08:29:21 +0000
commite73d3ed6011892b053b75419a43317c6a07bc763 (patch)
tree68f07771560b856e10bd464163c46cbe566df2a1
parentcfdc1bc2f770341db269279b160d9210cd4b923c (diff)
download2012-php-weave-e73d3ed6011892b053b75419a43317c6a07bc763.tar.gz
2012-php-weave-e73d3ed6011892b053b75419a43317c6a07bc763.tar.bz2
2012-php-weave-e73d3ed6011892b053b75419a43317c6a07bc763.zip
Premier commit.
nikic-PHP-Parser est un outil très prometteur. Le test test01-parsing inclu dans l'AST principal tous les include(<String>) ou string est un chemin relatif facile à résoudre. git-svn-id: file:///var/svn/2012-php-weave/trunk@2 d972a294-176a-4cf9-8ea1-fcd5b0c30f5c
-rwxr-xr-xcomposer.pharbin0 -> 544342 bytes
-rw-r--r--recherches/grammaire/url.txt10
-rw-r--r--recherches/grammaire/zend_language_parser.y1245
-rw-r--r--recherches/grammaire/zend_language_scanner.l2414
-rw-r--r--recherches/parsers/lime.tar.gzbin0 -> 55579 bytes
-rw-r--r--recherches/parsers/nikic-PHP-Parser-v0.9.2.txt1
-rw-r--r--tests/test01-parsing/src/composer.json6
-rwxr-xr-xtests/test01-parsing/src/get_deps.sh2
-rw-r--r--tests/test01-parsing/src/php-weave/main.php64
-rw-r--r--tests/test01-parsing/src/php-weave/to_parse.php5
-rw-r--r--tests/test01-parsing/src/php-weave/visitors.inc.php91
11 files changed, 3838 insertions, 0 deletions
diff --git a/composer.phar b/composer.phar
new file mode 100755
index 0000000..f9592cc
--- /dev/null
+++ b/composer.phar
Binary files differ
diff --git a/recherches/grammaire/url.txt b/recherches/grammaire/url.txt
new file mode 100644
index 0000000..361f7a8
--- /dev/null
+++ b/recherches/grammaire/url.txt
@@ -0,0 +1,10 @@
+https://svn.php.net/repository/php/php-src/trunk/Zend/zend_language_parser.y
+(utilise re2c)
+
+http://stackoverflow.com/questions/8795845/flex-bison-php-ast-generation
+
+
+PHP parser in PHP :
+http://stackoverflow.com/questions/5586358/any-decent-php-parser-written-in-php
+
+
diff --git a/recherches/grammaire/zend_language_parser.y b/recherches/grammaire/zend_language_parser.y
new file mode 100644
index 0000000..d0730b7
--- /dev/null
+++ b/recherches/grammaire/zend_language_parser.y
@@ -0,0 +1,1245 @@
+%{
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andi Gutmans <andi@zend.com> |
+ | Zeev Suraski <zeev@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+/*
+ * LALR shift/reduce conflicts and how they are resolved:
+ *
+ * - 2 shift/reduce conflicts due to the dangling elseif/else ambiguity. Solved by shift.
+ *
+ */
+
+
+#include "zend_compile.h"
+#include "zend.h"
+#include "zend_list.h"
+#include "zend_globals.h"
+#include "zend_API.h"
+#include "zend_constants.h"
+
+#define YYSIZE_T size_t
+#define yytnamerr zend_yytnamerr
+static YYSIZE_T zend_yytnamerr(char*, const char*);
+
+#define YYERROR_VERBOSE
+#define YYSTYPE znode
+#ifdef ZTS
+# define YYPARSE_PARAM tsrm_ls
+# define YYLEX_PARAM tsrm_ls
+#endif
+
+
+%}
+
+%pure_parser
+%expect 3
+
+%token END 0 "end of file"
+%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
+%token T_INCLUDE "include (T_INCLUDE)"
+%token T_INCLUDE_ONCE "include_once (T_INCLUDE_ONCE)"
+%token T_EVAL "eval (T_EVAL)"
+%token T_REQUIRE "require (T_REQUIRE)"
+%token T_REQUIRE_ONCE "require_once (T_REQUIRE_ONCE)"
+%left ','
+%left T_LOGICAL_OR
+%token T_LOGICAL_OR "or (T_LOGICAL_OR)"
+%left T_LOGICAL_XOR
+%token T_LOGICAL_XOR "xor (T_LOGICAL_XOR)"
+%left T_LOGICAL_AND
+%token T_LOGICAL_AND "and (T_LOGICAL_AND)"
+%right T_PRINT
+%token T_PRINT "print (T_PRINT)"
+%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL
+%token T_PLUS_EQUAL "+= (T_PLUS_EQUAL)"
+%token T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
+%token T_MUL_EQUAL "*= (T_MUL_EQUAL)"
+%token T_DIV_EQUAL "/= (T_DIV_EQUAL)"
+%token T_CONCAT_EQUAL ".= (T_CONCAT_EQUAL)"
+%token T_MOD_EQUAL "%= (T_MOD_EQUAL)"
+%token T_AND_EQUAL "&= (T_AND_EQUAL)"
+%token T_OR_EQUAL "|= (T_OR_EQUAL)"
+%token T_XOR_EQUAL "^= (T_XOR_EQUAL)"
+%token T_SL_EQUAL "<<= (T_SL_EQUAL)"
+%token T_SR_EQUAL ">>= (T_SR_EQUAL)"
+%left '?' ':'
+%left T_BOOLEAN_OR
+%token T_BOOLEAN_OR "|| (T_BOOLEAN_OR)"
+%left T_BOOLEAN_AND
+%token T_BOOLEAN_AND "&& (T_BOOLEAN_AND)"
+%left '|'
+%left '^'
+%left '&'
+%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL
+%token T_IS_EQUAL "== (T_IS_EQUAL)"
+%token T_IS_NOT_EQUAL "!= (T_IS_NOT_EQUAL)"
+%token T_IS_IDENTICAL "=== (T_IS_IDENTICAL)"
+%token T_IS_NOT_IDENTICAL "!== (T_IS_NOT_IDENTICAL)"
+%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
+%token T_IS_SMALLER_OR_EQUAL "<= (T_IS_SMALLER_OR_EQUAL)"
+%token T_IS_GREATER_OR_EQUAL ">= (T_IS_GREATER_OR_EQUAL)"
+%left T_SL T_SR
+%token T_SL "<< (T_SL)"
+%token T_SR ">> (T_SR)"
+%left '+' '-' '.'
+%left '*' '/' '%'
+%right '!'
+%nonassoc T_INSTANCEOF
+%token T_INSTANCEOF "instanceof (T_INSTANCEOF)"
+%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
+%token T_INC "++ (T_INC)"
+%token T_DEC "-- (T_DEC)"
+%token T_INT_CAST "(int) (T_INT_CAST)"
+%token T_DOUBLE_CAST "(double) (T_DOUBLE_CAST)"
+%token T_STRING_CAST "(string) (T_STRING_CAST)"
+%token T_ARRAY_CAST "(array) (T_ARRAY_CAST)"
+%token T_OBJECT_CAST "(object) (T_OBJECT_CAST)"
+%token T_BOOL_CAST "(bool) (T_BOOL_CAST)"
+%token T_UNSET_CAST "(unset) (T_UNSET_CAST)"
+%right '['
+%nonassoc T_NEW T_CLONE
+%token T_NEW "new (T_NEW)"
+%token T_CLONE "clone (T_CLONE)"
+%token T_EXIT "exit (T_EXIT)"
+%token T_IF "if (T_IF)"
+%left T_ELSEIF
+%token T_ELSEIF "elseif (T_ELSEIF)"
+%left T_ELSE
+%token T_ELSE "else (T_ELSE)"
+%left T_ENDIF
+%token T_ENDIF "endif (T_ENDIF)"
+%token T_LNUMBER "integer number (T_LNUMBER)"
+%token T_DNUMBER "floating-point number (T_DNUMBER)"
+%token T_STRING "identifier (T_STRING)"
+%token T_STRING_VARNAME "variable name (T_STRING_VARNAME)"
+%token T_VARIABLE "variable (T_VARIABLE)"
+%token T_NUM_STRING "number (T_NUM_STRING)"
+%token T_INLINE_HTML
+%token T_CHARACTER
+%token T_BAD_CHARACTER
+%token T_ENCAPSED_AND_WHITESPACE "quoted-string and whitespace (T_ENCAPSED_AND_WHITESPACE)"
+%token T_CONSTANT_ENCAPSED_STRING "quoted-string (T_CONSTANT_ENCAPSED_STRING)"
+%token T_ECHO "echo (T_ECHO)"
+%token T_DO "do (T_DO)"
+%token T_WHILE "while (T_WHILE)"
+%token T_ENDWHILE "endwhile (T_ENDWHILE)"
+%token T_FOR "for (T_FOR)"
+%token T_ENDFOR "endfor (T_ENDFOR)"
+%token T_FOREACH "foreach (T_FOREACH)"
+%token T_ENDFOREACH "endforeach (T_ENDFOREACH)"
+%token T_DECLARE "declare (T_DECLARE)"
+%token T_ENDDECLARE "enddeclare (T_ENDDECLARE)"
+%token T_AS "as (T_AS)"
+%token T_SWITCH "switch (T_SWITCH)"
+%token T_ENDSWITCH "endswitch (T_ENDSWITCH)"
+%token T_CASE "case (T_CASE)"
+%token T_DEFAULT "default (T_DEFAULT)"
+%token T_BREAK "break (T_BREAK)"
+%token T_CONTINUE "continue (T_CONTINUE)"
+%token T_GOTO "goto (T_GOTO)"
+%token T_FUNCTION "function (T_FUNCTION)"
+%token T_CONST "const (T_CONST)"
+%token T_RETURN "return (T_RETURN)"
+%token T_TRY "try (T_TRY)"
+%token T_CATCH "catch (T_CATCH)"
+%token T_THROW "throw (T_THROW)"
+%token T_USE "use (T_USE)"
+%token T_INSTEADOF "insteadof (T_INSTEADOF)"
+%token T_GLOBAL "global (T_GLOBAL)"
+%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
+%token T_STATIC "static (T_STATIC)"
+%token T_ABSTRACT "abstract (T_ABSTRACT)"
+%token T_FINAL "final (T_FINAL)"
+%token T_PRIVATE "private (T_PRIVATE)"
+%token T_PROTECTED "protected (T_PROTECTED)"
+%token T_PUBLIC "public (T_PUBLIC)"
+%token T_VAR "var (T_VAR)"
+%token T_UNSET "unset (T_UNSET)"
+%token T_ISSET "isset (T_ISSET)"
+%token T_EMPTY "empty (T_EMPTY)"
+%token T_HALT_COMPILER "__halt_compiler (T_HALT_COMPILER)"
+%token T_CLASS "class (T_CLASS)"
+%token T_TRAIT "trait (T_TRAIT)"
+%token T_INTERFACE "interface (T_INTERFACE)"
+%token T_EXTENDS "extends (T_EXTENDS)"
+%token T_IMPLEMENTS "implements (T_IMPLEMENTS)"
+%token T_OBJECT_OPERATOR "-> (T_OBJECT_OPERATOR)"
+%token T_DOUBLE_ARROW "=> (T_DOUBLE_ARROW)"
+%token T_LIST "list (T_LIST)"
+%token T_ARRAY "array (T_ARRAY)"
+%token T_CALLABLE "callable (T_CALLABLE)"
+%token T_CLASS_C "__CLASS__ (T_CLASS_C)"
+%token T_TRAIT_C "__TRAIT__ (T_TRAIT_C)"
+%token T_METHOD_C "__METHOD__ (T_METHOD_C)"
+%token T_FUNC_C "__FUNCTION__ (T_FUNC_C)"
+%token T_LINE "__LINE__ (T_LINE)"
+%token T_FILE "__FILE__ (T_FILE)"
+%token T_COMMENT "comment (T_COMMENT)"
+%token T_DOC_COMMENT "doc comment (T_DOC_COMMENT)"
+%token T_OPEN_TAG "open tag (T_OPEN_TAG)"
+%token T_OPEN_TAG_WITH_ECHO "open tag with echo (T_OPEN_TAG_WITH_ECHO)"
+%token T_CLOSE_TAG "close tag (T_CLOSE_TAG)"
+%token T_WHITESPACE "whitespace (T_WHITESPACE)"
+%token T_START_HEREDOC "heredoc start (T_START_HEREDOC)"
+%token T_END_HEREDOC "heredoc end (T_END_HEREDOC)"
+%token T_DOLLAR_OPEN_CURLY_BRACES "${ (T_DOLLAR_OPEN_CURLY_BRACES)"
+%token T_CURLY_OPEN "{$ (T_CURLY_OPEN)"
+%token T_PAAMAYIM_NEKUDOTAYIM ":: (T_PAAMAYIM_NEKUDOTAYIM)"
+%token T_NAMESPACE "namespace (T_NAMESPACE)"
+%token T_NS_C "__NAMESPACE__ (T_NS_C)"
+%token T_DIR "__DIR__ (T_DIR)"
+%token T_NS_SEPARATOR "\\ (T_NS_SEPARATOR)"
+
+%% /* Rules */
+
+start:
+ top_statement_list { zend_do_end_compilation(TSRMLS_C); }
+;
+
+top_statement_list:
+ top_statement_list { zend_do_extended_info(TSRMLS_C); } top_statement { HANDLE_INTERACTIVE(); }
+ | /* empty */
+;
+
+namespace_name:
+ T_STRING { $$ = $1; }
+ | namespace_name T_NS_SEPARATOR T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
+;
+
+top_statement:
+ statement { zend_verify_namespace(TSRMLS_C); }
+ | function_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); }
+ | class_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); }
+ | T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
+ | T_NAMESPACE namespace_name ';' { zend_do_begin_namespace(&$2, 0 TSRMLS_CC); }
+ | T_NAMESPACE namespace_name '{' { zend_do_begin_namespace(&$2, 1 TSRMLS_CC); }
+ top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); }
+ | T_NAMESPACE '{' { zend_do_begin_namespace(NULL, 1 TSRMLS_CC); }
+ top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); }
+ | T_USE use_declarations ';' { zend_verify_namespace(TSRMLS_C); }
+ | constant_declaration ';' { zend_verify_namespace(TSRMLS_C); }
+;
+
+use_declarations:
+ use_declarations ',' use_declaration
+ | use_declaration
+;
+
+use_declaration:
+ namespace_name { zend_do_use(&$1, NULL, 0 TSRMLS_CC); }
+ | namespace_name T_AS T_STRING { zend_do_use(&$1, &$3, 0 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name { zend_do_use(&$2, NULL, 1 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use(&$2, &$4, 1 TSRMLS_CC); }
+;
+
+constant_declaration:
+ constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); }
+ | T_CONST T_STRING '=' static_scalar { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); }
+;
+
+inner_statement_list:
+ inner_statement_list { zend_do_extended_info(TSRMLS_C); } inner_statement { HANDLE_INTERACTIVE(); }
+ | /* empty */
+;
+
+
+inner_statement:
+ statement
+ | function_declaration_statement
+ | class_declaration_statement
+ | T_HALT_COMPILER '(' ')' ';' { zend_error(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope"); }
+;
+
+
+statement:
+ unticked_statement { DO_TICKS(); }
+ | T_STRING ':' { zend_do_label(&$1 TSRMLS_CC); }
+;
+
+unticked_statement:
+ '{' inner_statement_list '}'
+ | T_IF '(' expr ')' { zend_do_if_cond(&$3, &$4 TSRMLS_CC); } statement { zend_do_if_after_statement(&$4, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); }
+ | T_IF '(' expr ')' ':' { zend_do_if_cond(&$3, &$4 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$4, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); }
+ | T_WHILE '(' { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' { zend_do_while_cond(&$4, &$5 TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$5 TSRMLS_CC); }
+ | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE '(' { $5.u.op.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' ';' { zend_do_do_while_end(&$1, &$5, &$7 TSRMLS_CC); }
+ | T_FOR
+ '('
+ for_expr
+ ';' { zend_do_free(&$3 TSRMLS_CC); $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); }
+ for_expr
+ ';' { zend_do_extended_info(TSRMLS_C); zend_do_for_cond(&$6, &$7 TSRMLS_CC); }
+ for_expr
+ ')' { zend_do_free(&$9 TSRMLS_CC); zend_do_for_before_statement(&$4, &$7 TSRMLS_CC); }
+ for_statement { zend_do_for_end(&$7 TSRMLS_CC); }
+ | T_SWITCH '(' expr ')' { zend_do_switch_cond(&$3 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$6 TSRMLS_CC); }
+ | T_BREAK ';' { zend_do_brk_cont(ZEND_BRK, NULL TSRMLS_CC); }
+ | T_BREAK expr ';' { zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); }
+ | T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); }
+ | T_CONTINUE expr ';' { zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); }
+ | T_RETURN ';' { zend_do_return(NULL, 0 TSRMLS_CC); }
+ | T_RETURN expr_without_variable ';' { zend_do_return(&$2, 0 TSRMLS_CC); }
+ | T_RETURN variable ';' { zend_do_return(&$2, 1 TSRMLS_CC); }
+ | T_GLOBAL global_var_list ';'
+ | T_STATIC static_var_list ';'
+ | T_ECHO echo_expr_list ';'
+ | T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); }
+ | expr ';' { zend_do_free(&$1 TSRMLS_CC); }
+ | T_UNSET '(' unset_variables ')' ';'
+ | T_FOREACH '(' variable T_AS
+ { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
+ foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
+ foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
+ | T_FOREACH '(' expr_without_variable T_AS
+ { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
+ variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
+ foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
+ | T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
+ | ';' /* empty statement */
+ | T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
+ T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); }
+ fully_qualified_class_name { zend_do_first_catch(&$7 TSRMLS_CC); }
+ T_VARIABLE ')' { zend_do_begin_catch(&$1, &$9, &$11, &$7 TSRMLS_CC); }
+ '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+ additional_catches { zend_do_mark_last_catch(&$7, &$18 TSRMLS_CC); }
+ | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
+ | T_GOTO T_STRING ';' { zend_do_goto(&$2 TSRMLS_CC); }
+;
+
+
+additional_catches:
+ non_empty_additional_catches { $$ = $1; }
+ | /* empty */ { $$.u.op.opline_num = -1; }
+;
+
+non_empty_additional_catches:
+ additional_catch { $$ = $1; }
+ | non_empty_additional_catches additional_catch { $$ = $2; }
+;
+
+
+additional_catch:
+ T_CATCH '(' fully_qualified_class_name { $$.u.op.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+;
+
+
+unset_variables:
+ unset_variable
+ | unset_variables ',' unset_variable
+;
+
+unset_variable:
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
+;
+
+function_declaration_statement:
+ unticked_function_declaration_statement { DO_TICKS(); }
+;
+
+class_declaration_statement:
+ unticked_class_declaration_statement { DO_TICKS(); }
+;
+
+
+is_reference:
+ /* empty */ { $$.op_type = ZEND_RETURN_VAL; }
+ | '&' { $$.op_type = ZEND_RETURN_REF; }
+;
+
+
+unticked_function_declaration_statement:
+ function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); }
+ '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); }
+;
+
+unticked_class_declaration_statement:
+ class_entry_type T_STRING extends_from
+ { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); }
+ implements_list
+ '{'
+ class_statement_list
+ '}' { zend_do_end_class_declaration(&$1, &$2 TSRMLS_CC); }
+ | interface_entry T_STRING
+ { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); }
+ interface_extends_list
+ '{'
+ class_statement_list
+ '}' { zend_do_end_class_declaration(&$1, &$2 TSRMLS_CC); }
+;
+
+
+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; }
+;
+
+extends_from:
+ /* empty */ { $$.op_type = IS_UNUSED; }
+ | T_EXTENDS fully_qualified_class_name { zend_do_fetch_class(&$$, &$2 TSRMLS_CC); }
+;
+
+interface_entry:
+ T_INTERFACE { $$.u.op.opline_num = CG(zend_lineno); $$.EA = ZEND_ACC_INTERFACE; }
+;
+
+interface_extends_list:
+ /* empty */
+ | T_EXTENDS interface_list
+;
+
+implements_list:
+ /* empty */
+ | T_IMPLEMENTS interface_list
+;
+
+interface_list:
+ fully_qualified_class_name { zend_do_implements_interface(&$1 TSRMLS_CC); }
+ | interface_list ',' fully_qualified_class_name { zend_do_implements_interface(&$3 TSRMLS_CC); }
+;
+
+foreach_optional_arg:
+ /* empty */ { $$.op_type = IS_UNUSED; }
+ | T_DOUBLE_ARROW foreach_variable { $$ = $2; }
+;
+
+
+foreach_variable:
+ variable { zend_check_writable_variable(&$1); $$ = $1; }
+ | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; }
+;
+
+for_statement:
+ statement
+ | ':' inner_statement_list T_ENDFOR ';'
+;
+
+
+foreach_statement:
+ statement
+ | ':' inner_statement_list T_ENDFOREACH ';'
+;
+
+
+declare_statement:
+ statement
+ | ':' inner_statement_list T_ENDDECLARE ';'
+;
+
+
+declare_list:
+ T_STRING '=' static_scalar { zend_do_declare_stmt(&$1, &$3 TSRMLS_CC); }
+ | declare_list ',' T_STRING '=' static_scalar { zend_do_declare_stmt(&$3, &$5 TSRMLS_CC); }
+;
+
+
+switch_case_list:
+ '{' case_list '}' { $$ = $2; }
+ | '{' ';' case_list '}' { $$ = $3; }
+ | ':' case_list T_ENDSWITCH ';' { $$ = $2; }
+ | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; }
+;
+
+
+case_list:
+ /* empty */ { $$.op_type = IS_UNUSED; }
+ | case_list T_CASE expr case_separator { zend_do_extended_info(TSRMLS_C); zend_do_case_before_statement(&$1, &$2, &$3 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
+ | case_list T_DEFAULT case_separator { zend_do_extended_info(TSRMLS_C); zend_do_default_before_statement(&$1, &$2 TSRMLS_CC); } inner_statement_list { zend_do_case_after_statement(&$$, &$2 TSRMLS_CC); $$.op_type = IS_CONST; }
+;
+
+
+case_separator:
+ ':'
+ | ';'
+;
+
+
+while_statement:
+ statement
+ | ':' inner_statement_list T_ENDWHILE ';'
+;
+
+
+
+elseif_list:
+ /* empty */
+ | elseif_list T_ELSEIF '(' expr ')' { zend_do_if_cond(&$4, &$5 TSRMLS_CC); } statement { zend_do_if_after_statement(&$5, 0 TSRMLS_CC); }
+;
+
+
+new_elseif_list:
+ /* empty */
+ | new_elseif_list T_ELSEIF '(' expr ')' ':' { zend_do_if_cond(&$4, &$5 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$5, 0 TSRMLS_CC); }
+;
+
+
+else_single:
+ /* empty */
+ | T_ELSE statement
+;
+
+
+new_else_single:
+ /* empty */
+ | T_ELSE ':' inner_statement_list
+;
+
+
+parameter_list:
+ non_empty_parameter_list
+ | /* empty */
+;
+
+
+non_empty_parameter_list:
+ optional_class_type T_VARIABLE { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$2, &$$, NULL, &$1, 0 TSRMLS_CC); }
+ | optional_class_type '&' T_VARIABLE { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$3, &$$, NULL, &$1, 1 TSRMLS_CC); }
+ | optional_class_type '&' T_VARIABLE '=' static_scalar { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV_INIT, &$3, &$$, &$5, &$1, 1 TSRMLS_CC); }
+ | optional_class_type T_VARIABLE '=' static_scalar { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV_INIT, &$2, &$$, &$4, &$1, 0 TSRMLS_CC); }
+ | non_empty_parameter_list ',' optional_class_type T_VARIABLE { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV, &$4, &$$, NULL, &$3, 0 TSRMLS_CC); }
+ | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV, &$5, &$$, NULL, &$3, 1 TSRMLS_CC); }
+ | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '=' static_scalar { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV_INIT, &$5, &$$, &$7, &$3, 1 TSRMLS_CC); }
+ | non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV_INIT, &$4, &$$, &$6, &$3, 0 TSRMLS_CC); }
+;
+
+
+optional_class_type:
+ /* empty */ { $$.op_type = IS_UNUSED; }
+ | T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; }
+ | T_CALLABLE { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CALLABLE; }
+ | fully_qualified_class_name { $$ = $1; }
+;
+
+
+function_call_parameter_list:
+ non_empty_function_call_parameter_list { $$ = $1; }
+ | /* empty */ { Z_LVAL($$.u.constant) = 0; }
+;
+
+
+non_empty_function_call_parameter_list:
+ expr_without_variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$1, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
+ | variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$1, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
+ | '&' w_variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$2, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
+ | non_empty_function_call_parameter_list ',' expr_without_variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$3, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
+ | non_empty_function_call_parameter_list ',' variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$3, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
+ | non_empty_function_call_parameter_list ',' '&' w_variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$4, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
+;
+
+global_var_list:
+ global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
+ | global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); }
+;
+
+
+global_var:
+ T_VARIABLE { $$ = $1; }
+ | '$' r_variable { $$ = $2; }
+ | '$' '{' expr '}' { $$ = $3; }
+;
+
+
+static_var_list:
+ static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
+ | static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
+ | T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
+ | T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); }
+
+;
+
+
+class_statement_list:
+ class_statement_list class_statement
+ | /* empty */
+;
+
+
+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_resolve_class_name(&$1, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC); zend_init_list(&$$.u.op.ptr, Z_STRVAL($1.u.constant) TSRMLS_CC); }
+ | trait_reference_list ',' fully_qualified_class_name { zend_resolve_class_name(&$3, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC); 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; }
+ | '{' inner_statement_list '}' { Z_LVAL($$.u.constant) = 0; }
+;
+
+variable_modifiers:
+ non_empty_member_modifiers { $$ = $1; }
+ | T_VAR { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
+;
+
+method_modifiers:
+ /* empty */ { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
+ | non_empty_member_modifiers { $$ = $1; if (!(Z_LVAL($$.u.constant) & ZEND_ACC_PPP_MASK)) { Z_LVAL($$.u.constant) |= ZEND_ACC_PUBLIC; } }
+;
+
+non_empty_member_modifiers:
+ member_modifier { $$ = $1; }
+ | non_empty_member_modifiers member_modifier { Z_LVAL($$.u.constant) = zend_do_verify_access_types(&$1, &$2); }
+;
+
+member_modifier:
+ T_PUBLIC { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
+ | T_PROTECTED { Z_LVAL($$.u.constant) = ZEND_ACC_PROTECTED; }
+ | T_PRIVATE { Z_LVAL($$.u.constant) = ZEND_ACC_PRIVATE; }
+ | T_STATIC { Z_LVAL($$.u.constant) = ZEND_ACC_STATIC; }
+ | T_ABSTRACT { Z_LVAL($$.u.constant) = ZEND_ACC_ABSTRACT; }
+ | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; }
+;
+
+class_variable_declaration:
+ class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); }
+ | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); }
+ | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); }
+ | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); }
+;
+
+class_constant_declaration:
+ class_constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_class_constant(&$3, &$5 TSRMLS_CC); }
+ | T_CONST T_STRING '=' static_scalar { zend_do_declare_class_constant(&$2, &$4 TSRMLS_CC); }
+;
+
+echo_expr_list:
+ echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }
+ | expr { zend_do_echo(&$1 TSRMLS_CC); }
+;
+
+
+for_expr:
+ /* empty */ { $$.op_type = IS_CONST; Z_TYPE($$.u.constant) = IS_BOOL; Z_LVAL($$.u.constant) = 1; }
+ | non_empty_for_expr { $$ = $1; }
+;
+
+non_empty_for_expr:
+ non_empty_for_expr ',' { zend_do_free(&$1 TSRMLS_CC); } expr { $$ = $4; }
+ | expr { $$ = $1; }
+;
+
+chaining_method_or_property:
+ chaining_method_or_property variable_property { $$.EA = $2.EA; }
+ | variable_property { $$.EA = $1.EA; }
+;
+
+chaining_dereference:
+ chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+ | '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); }
+;
+
+chaining_instance_call:
+ chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; }
+ | chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; }
+ | chaining_method_or_property { $$ = $1; }
+;
+
+instance_call:
+ /* empty */ { $$ = $0; }
+ | { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); }
+ chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); }
+;
+
+new_expr:
+ T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+;
+
+expr_without_variable:
+ T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
+ | variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
+ | variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
+ | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.EA = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
+ | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
+ | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_MUL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_DIV_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_CONCAT_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_MOD_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_AND_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_OR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_XOR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_SL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_SR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); }
+ | rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); }
+ | T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); }
+ | rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); }
+ | T_DEC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_DEC TSRMLS_CC); }
+ | expr T_BOOLEAN_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
+ | expr T_BOOLEAN_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
+ | expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
+ | expr T_LOGICAL_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
+ | expr T_LOGICAL_XOR expr { zend_do_binary_op(ZEND_BOOL_XOR, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '|' expr { zend_do_binary_op(ZEND_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '&' expr { zend_do_binary_op(ZEND_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '^' expr { zend_do_binary_op(ZEND_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '.' expr { zend_do_binary_op(ZEND_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '+' expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '-' expr { zend_do_binary_op(ZEND_SUB, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '*' expr { zend_do_binary_op(ZEND_MUL, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '/' expr { zend_do_binary_op(ZEND_DIV, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '%' expr { zend_do_binary_op(ZEND_MOD, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr T_SL expr { zend_do_binary_op(ZEND_SL, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr T_SR expr { zend_do_binary_op(ZEND_SR, &$$, &$1, &$3 TSRMLS_CC); }
+ | '+' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); zend_do_binary_op(ZEND_ADD, &$$, &$1, &$2 TSRMLS_CC); } }
+ | '-' expr %prec T_INC { ZVAL_LONG(&$1.u.constant, 0); if ($2.op_type == IS_CONST) { sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; } else { $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); zend_do_binary_op(ZEND_SUB, &$$, &$1, &$2 TSRMLS_CC); } }
+ | '!' expr { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$2 TSRMLS_CC); }
+ | '~' expr { zend_do_unary_op(ZEND_BW_NOT, &$$, &$2 TSRMLS_CC); }
+ | expr T_IS_IDENTICAL expr { zend_do_binary_op(ZEND_IS_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr T_IS_NOT_IDENTICAL expr { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr T_IS_EQUAL expr { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr T_IS_NOT_EQUAL expr { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '<' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
+ | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }
+ | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
+ | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
+ | '(' expr ')' { $$ = $2; }
+ | new_expr { $$ = $1; }
+ | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; }
+ | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
+ expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
+ expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
+ | expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); }
+ expr { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }
+ | internal_functions_in_yacc { $$ = $1; }
+ | T_INT_CAST expr { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); }
+ | T_DOUBLE_CAST expr { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); }
+ | T_STRING_CAST expr { zend_do_cast(&$$, &$2, IS_STRING TSRMLS_CC); }
+ | T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); }
+ | T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
+ | T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); }
+ | T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); }
+ | T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); }
+ | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
+ | scalar { $$ = $1; }
+ | T_ARRAY '(' array_pair_list ')' { $$ = $3; }
+ | '[' array_pair_list ']' { $$ = $2; }
+ | '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
+ | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
+ | function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); }
+ parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
+ | T_STATIC function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); }
+ parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $5; }
+;
+
+function:
+ T_FUNCTION { $$.u.op.opline_num = CG(zend_lineno); }
+;
+
+lexical_vars:
+ /* empty */
+ | T_USE '(' lexical_var_list ')'
+;
+
+lexical_var_list:
+ lexical_var_list ',' T_VARIABLE { zend_do_fetch_lexical_variable(&$3, 0 TSRMLS_CC); }
+ | lexical_var_list ',' '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$4, 1 TSRMLS_CC); }
+ | T_VARIABLE { zend_do_fetch_lexical_variable(&$1, 0 TSRMLS_CC); }
+ | '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$2, 1 TSRMLS_CC); }
+;
+
+function_call:
+ namespace_name '(' { $2.u.op.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.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name '(' { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant); zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $4.u.op.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); }
+ function_call_parameter_list
+ ')' { zend_do_end_function_call(&$1, &$$, &$6, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+ | T_NS_SEPARATOR namespace_name '(' { $3.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); }
+ function_call_parameter_list
+ ')' { zend_do_end_function_call(&$2, &$$, &$5, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+ | class_name T_PAAMAYIM_NEKUDOTAYIM variable_name '(' { $4.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+ function_call_parameter_list
+ ')' { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, &$6, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+ | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+ function_call_parameter_list
+ ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+ function_call_parameter_list
+ ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+ function_call_parameter_list
+ ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+ | variable_without_objects '(' { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
+ function_call_parameter_list ')'
+ { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+;
+
+class_name:
+ T_STATIC { $$.op_type = IS_CONST; ZVAL_STRINGL(&$$.u.constant, "static", sizeof("static")-1, 1);}
+ | namespace_name { $$ = $1; }
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); $$ = $2; }
+;
+
+fully_qualified_class_name:
+ namespace_name { $$ = $1; }
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); $$ = $2; }
+;
+
+
+
+class_name_reference:
+ class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+ | dynamic_class_name_reference { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+;
+
+
+dynamic_class_name_reference:
+ base_variable T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
+ object_property { zend_do_push_object(&$4 TSRMLS_CC); } dynamic_class_name_variable_properties
+ { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = ZEND_PARSED_MEMBER; }
+ | base_variable { $$ = $1; }
+;
+
+
+dynamic_class_name_variable_properties:
+ dynamic_class_name_variable_properties dynamic_class_name_variable_property
+ | /* empty */
+;
+
+
+dynamic_class_name_variable_property:
+ T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); }
+;
+
+exit_expr:
+ /* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
+ | '(' ')' { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; }
+ | '(' expr ')' { $$ = $2; }
+;
+
+backticks_expr:
+ /* empty */ { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
+ | T_ENCAPSED_AND_WHITESPACE { $$ = $1; }
+ | encaps_list { $$ = $1; }
+;
+
+
+ctor_arguments:
+ /* empty */ { Z_LVAL($$.u.constant)=0; }
+ | '(' function_call_parameter_list ')' { $$ = $2; }
+;
+
+
+common_scalar:
+ T_LNUMBER { $$ = $1; }
+ | T_DNUMBER { $$ = $1; }
+ | T_CONSTANT_ENCAPSED_STRING { $$ = $1; }
+ | T_LINE { $$ = $1; }
+ | T_FILE { $$ = $1; }
+ | T_DIR { $$ = $1; }
+ | T_TRAIT_C { $$ = $1; }
+ | T_METHOD_C { $$ = $1; }
+ | T_FUNC_C { $$ = $1; }
+ | T_NS_C { $$ = $1; }
+ | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; CG(heredoc) = Z_STRVAL($1.u.constant); CG(heredoc_len) = Z_STRLEN($1.u.constant); }
+ | T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; CG(heredoc) = Z_STRVAL($1.u.constant); CG(heredoc_len) = Z_STRLEN($1.u.constant); }
+;
+
+
+static_scalar: /* compile-time evaluated scalars */
+ common_scalar { $$ = $1; }
+ | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); }
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); }
+ | '+' static_scalar { ZVAL_LONG(&$1.u.constant, 0); add_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
+ | '-' static_scalar { ZVAL_LONG(&$1.u.constant, 0); sub_function(&$2.u.constant, &$1.u.constant, &$2.u.constant TSRMLS_CC); $$ = $2; }
+ | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
+ | '[' static_array_pair_list ']' { $$ = $2; Z_TYPE($$.u.constant) = IS_CONSTANT_ARRAY; }
+ | static_class_constant { $$ = $1; }
+ | T_CLASS_C { $$ = $1; }
+;
+
+static_class_constant:
+ class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_CT, 0 TSRMLS_CC); }
+;
+
+scalar:
+ T_STRING_VARNAME { $$ = $1; }
+ | class_constant { $$ = $1; }
+ | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC); }
+ | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_RT, 0 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); }
+ | common_scalar { $$ = $1; }
+ | '"' encaps_list '"' { $$ = $2; }
+ | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; CG(heredoc) = Z_STRVAL($1.u.constant); CG(heredoc_len) = Z_STRLEN($1.u.constant); }
+ | T_CLASS_C { if (Z_TYPE($1.u.constant) == IS_CONSTANT) {zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC);} else {$$ = $1;} }
+;
+
+
+static_array_pair_list:
+ /* empty */ { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); }
+ | non_empty_static_array_pair_list possible_comma { $$ = $1; }
+;
+
+possible_comma:
+ /* empty */
+ | ','
+;
+
+non_empty_static_array_pair_list:
+ non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW static_scalar { zend_do_add_static_array_element(&$$, &$3, &$5); }
+ | non_empty_static_array_pair_list ',' static_scalar { zend_do_add_static_array_element(&$$, NULL, &$3); }
+ | static_scalar T_DOUBLE_ARROW static_scalar { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); zend_do_add_static_array_element(&$$, &$1, &$3); }
+ | static_scalar { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); zend_do_add_static_array_element(&$$, NULL, &$1); }
+;
+
+expr:
+ r_variable { $$ = $1; }
+ | expr_without_variable { $$ = $1; }
+;
+
+
+r_variable:
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
+;
+
+
+w_variable:
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $$ = $1;
+ zend_check_writable_variable(&$1); }
+;
+
+rw_variable:
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); $$ = $1;
+ zend_check_writable_variable(&$1); }
+;
+
+variable:
+ base_variable_with_function_calls T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
+ object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties
+ { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = $1.EA | ($7.EA ? $7.EA : $6.EA); }
+ | base_variable_with_function_calls { $$ = $1; }
+;
+
+variable_properties:
+ variable_properties variable_property { $$.EA = $2.EA; }
+ | /* empty */ { $$.EA = 0; }
+;
+
+
+variable_property:
+ T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } method_or_not { $$.EA = $4.EA; }
+;
+
+array_method_dereference:
+ array_method_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+ | method '[' dim_offset ']' { $1.EA = ZEND_PARSED_METHOD_CALL; fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+;
+
+method:
+ '(' { zend_do_pop_object(&$1 TSRMLS_CC); zend_do_begin_method_call(&$1 TSRMLS_CC); }
+ function_call_parameter_list ')'
+ { zend_do_end_function_call(&$1, &$$, &$3, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
+;
+
+method_or_not:
+ method { $$ = $1; $$.EA = ZEND_PARSED_METHOD_CALL; zend_do_push_object(&$$ TSRMLS_CC); }
+ | array_method_dereference { $$ = $1; zend_do_push_object(&$$ TSRMLS_CC); }
+ | /* empty */ { $$.EA = ZEND_PARSED_MEMBER; }
+;
+
+variable_without_objects:
+ reference_variable { $$ = $1; }
+ | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); }
+;
+
+static_member:
+ class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
+
+;
+
+variable_class_name:
+ reference_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$=$1;; }
+;
+
+array_function_dereference:
+ array_function_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+ | function_call { zend_do_begin_variable_parse(TSRMLS_C); $1.EA = ZEND_PARSED_FUNCTION_CALL; }
+ '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$4 TSRMLS_CC); }
+;
+
+base_variable_with_function_calls:
+ base_variable { $$ = $1; }
+ | array_function_dereference { $$ = $1; }
+ | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.EA = ZEND_PARSED_FUNCTION_CALL; }
+;
+
+
+base_variable:
+ reference_variable { $$ = $1; $$.EA = ZEND_PARSED_VARIABLE; }
+ | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); $$.EA = ZEND_PARSED_VARIABLE; }
+ | static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; }
+;
+
+reference_variable:
+ reference_variable '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+ | reference_variable '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); }
+ | compound_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
+;
+
+
+compound_variable:
+ T_VARIABLE { $$ = $1; }
+ | '$' '{' expr '}' { $$ = $3; }
+;
+
+dim_offset:
+ /* empty */ { $$.op_type = IS_UNUSED; }
+ | expr { $$ = $1; }
+;
+
+
+object_property:
+ object_dim_list { $$ = $1; }
+ | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
+;
+
+object_dim_list:
+ object_dim_list '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
+ | object_dim_list '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); }
+ | variable_name { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
+;
+
+variable_name:
+ T_STRING { $$ = $1; }
+ | '{' expr '}' { $$ = $2; }
+;
+
+simple_indirect_reference:
+ '$' { Z_LVAL($$.u.constant) = 1; }
+ | simple_indirect_reference '$' { Z_LVAL($$.u.constant)++; }
+;
+
+assignment_list:
+ assignment_list ',' assignment_list_element
+ | assignment_list_element
+;
+
+
+assignment_list_element:
+ variable { zend_do_add_list_element(&$1 TSRMLS_CC); }
+ | T_LIST '(' { zend_do_new_list_begin(TSRMLS_C); } assignment_list ')' { zend_do_new_list_end(TSRMLS_C); }
+ | /* empty */ { zend_do_add_list_element(NULL TSRMLS_CC); }
+;
+
+
+array_pair_list:
+ /* empty */ { zend_do_init_array(&$$, NULL, NULL, 0 TSRMLS_CC); }
+ | non_empty_array_pair_list possible_comma { $$ = $1; }
+;
+
+non_empty_array_pair_list:
+ non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { zend_do_add_array_element(&$$, &$5, &$3, 0 TSRMLS_CC); }
+ | non_empty_array_pair_list ',' expr { zend_do_add_array_element(&$$, &$3, NULL, 0 TSRMLS_CC); }
+ | expr T_DOUBLE_ARROW expr { zend_do_init_array(&$$, &$3, &$1, 0 TSRMLS_CC); }
+ | expr { zend_do_init_array(&$$, &$1, NULL, 0 TSRMLS_CC); }
+ | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable { zend_do_add_array_element(&$$, &$6, &$3, 1 TSRMLS_CC); }
+ | non_empty_array_pair_list ',' '&' w_variable { zend_do_add_array_element(&$$, &$4, NULL, 1 TSRMLS_CC); }
+ | expr T_DOUBLE_ARROW '&' w_variable { zend_do_init_array(&$$, &$4, &$1, 1 TSRMLS_CC); }
+ | '&' w_variable { zend_do_init_array(&$$, &$2, NULL, 1 TSRMLS_CC); }
+;
+
+encaps_list:
+ encaps_list encaps_var { zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
+ | encaps_list T_ENCAPSED_AND_WHITESPACE { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
+ | encaps_var { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, NULL, &$1 TSRMLS_CC); }
+ | T_ENCAPSED_AND_WHITESPACE encaps_var { zend_do_add_string(&$$, NULL, &$1 TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$$, &$2 TSRMLS_CC); }
+;
+
+
+
+encaps_var:
+ T_VARIABLE { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
+ | T_VARIABLE '[' { zend_do_begin_variable_parse(TSRMLS_C); } encaps_var_offset ']' { fetch_array_begin(&$$, &$1, &$4 TSRMLS_CC); }
+ | T_VARIABLE T_OBJECT_OPERATOR T_STRING { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$2, &$1, 1 TSRMLS_CC); zend_do_fetch_property(&$$, &$2, &$3 TSRMLS_CC); }
+ | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$2, 1 TSRMLS_CC); }
+ | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_begin(&$$, &$2, &$4 TSRMLS_CC); }
+ | T_CURLY_OPEN variable '}' { $$ = $2; }
+;
+
+
+encaps_var_offset:
+ T_STRING { $$ = $1; }
+ | T_NUM_STRING { $$ = $1; }
+ | T_VARIABLE { fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
+;
+
+
+internal_functions_in_yacc:
+ T_ISSET '(' isset_variables ')' { $$ = $3; }
+ | T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); }
+ | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
+ | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
+ | T_EVAL '(' expr ')' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
+ | T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
+ | T_REQUIRE_ONCE expr { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }
+;
+
+isset_variables:
+ variable { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); }
+ | isset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } variable { znode tmp; zend_do_isset_or_isempty(ZEND_ISSET, &tmp, &$4 TSRMLS_CC); zend_do_boolean_and_end(&$$, &$1, &tmp, &$2 TSRMLS_CC); }
+;
+
+class_constant:
+ class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_fetch_constant(&$$, &$1, &$3, ZEND_RT, 0 TSRMLS_CC); }
+;
+
+%%
+
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T zend_yytnamerr(char *yyres, const char *yystr)
+{
+ if (!yyres) {
+ return yystrlen(yystr);
+ }
+ {
+ TSRMLS_FETCH();
+ if (CG(parse_error) == 0) {
+ char buffer[120];
+ const unsigned char *end, *str, *tok1 = NULL, *tok2 = NULL;
+ unsigned int len = 0, toklen = 0, yystr_len;
+
+ CG(parse_error) = 1;
+
+ if (LANG_SCNG(yy_text)[0] == 0 &&
+ LANG_SCNG(yy_leng) == 1 &&
+ memcmp(yystr, ZEND_STRL("\"end of file\"")) == 0) {
+ yystpcpy(yyres, "end of file");
+ return sizeof("end of file")-1;
+ }
+
+ str = LANG_SCNG(yy_text);
+ end = memchr(str, '\n', LANG_SCNG(yy_leng));
+ yystr_len = yystrlen(yystr);
+
+ if ((tok1 = memchr(yystr, '(', yystr_len)) != NULL
+ && (tok2 = zend_memrchr(yystr, ')', yystr_len)) != NULL) {
+ toklen = (tok2 - tok1) + 1;
+ } else {
+ tok1 = tok2 = NULL;
+ toklen = 0;
+ }
+
+ if (end == NULL) {
+ len = LANG_SCNG(yy_leng) > 30 ? 30 : LANG_SCNG(yy_leng);
+ } else {
+ len = (end - str) > 30 ? 30 : (end - str);
+ }
+ if (toklen) {
+ snprintf(buffer, sizeof(buffer), "'%.*s' %.*s", len, str, toklen, tok1);
+ } else {
+ snprintf(buffer, sizeof(buffer), "'%.*s'", len, str);
+ }
+ yystpcpy(yyres, buffer);
+ return len + (toklen ? toklen + 1 : 0) + 2;
+ }
+ }
+ if (*yystr == '"') {
+ YYSIZE_T yyn = 0;
+ const char *yyp = yystr;
+
+ for (; *++yyp != '"'; ++yyn) {
+ yyres[yyn] = *yyp;
+ }
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ yystpcpy(yyres, yystr);
+ return strlen(yystr);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/recherches/grammaire/zend_language_scanner.l b/recherches/grammaire/zend_language_scanner.l
new file mode 100644
index 0000000..d530b53
--- /dev/null
+++ b/recherches/grammaire/zend_language_scanner.l
@@ -0,0 +1,2414 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Marcus Boerger <helly@php.net> |
+ | Nuno Lopes <nlopess@php.net> |
+ | Scott MacVicar <scottmac@php.net> |
+ | Flex version authors: |
+ | Andi Gutmans <andi@zend.com> |
+ | Zeev Suraski <zeev@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#if 0
+# define YYDEBUG(s, c) printf("state: %d char: %c\n", s, c)
+#else
+# define YYDEBUG(s, c)
+#endif
+
+#include "zend_language_scanner_defs.h"
+
+#include <errno.h>
+#include "zend.h"
+#include "zend_alloc.h"
+#include <zend_language_parser.h>
+#include "zend_compile.h"
+#include "zend_language_scanner.h"
+#include "zend_highlight.h"
+#include "zend_constants.h"
+#include "zend_variables.h"
+#include "zend_operators.h"
+#include "zend_API.h"
+#include "zend_strtod.h"
+#include "zend_exceptions.h"
+#include "tsrm_virtual_cwd.h"
+#include "tsrm_config_common.h"
+
+#define YYCTYPE unsigned char
+#define YYFILL(n) { if ((YYCURSOR + n) >= (YYLIMIT + ZEND_MMAP_AHEAD)) { return 0; } }
+#define YYCURSOR SCNG(yy_cursor)
+#define YYLIMIT SCNG(yy_limit)
+#define YYMARKER SCNG(yy_marker)
+
+#define YYGETCONDITION() SCNG(yy_state)
+#define YYSETCONDITION(s) SCNG(yy_state) = s
+
+#define STATE(name) yyc##name
+
+/* emulate flex constructs */
+#define BEGIN(state) YYSETCONDITION(STATE(state))
+#define YYSTATE YYGETCONDITION()
+#define yytext ((char*)SCNG(yy_text))
+#define yyleng SCNG(yy_leng)
+#define yyless(x) do { YYCURSOR = (unsigned char*)yytext + x; \
+ yyleng = (unsigned int)x; } while(0)
+#define yymore() goto yymore_restart
+
+/* perform sanity check. If this message is triggered you should
+ increase the ZEND_MMAP_AHEAD value in the zend_streams.h file */
+/*!max:re2c */
+#if ZEND_MMAP_AHEAD < YYMAXFILL
+# error ZEND_MMAP_AHEAD should be greater than or equal to YYMAXFILL
+#endif
+
+#ifdef HAVE_STDARG_H
+# include <stdarg.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+/* Globals Macros */
+#define SCNG LANG_SCNG
+#ifdef ZTS
+ZEND_API ts_rsrc_id language_scanner_globals_id;
+#else
+ZEND_API zend_php_scanner_globals language_scanner_globals;
+#endif
+
+#define HANDLE_NEWLINES(s, l) \
+do { \
+ char *p = (s), *boundary = p+(l); \
+ \
+ while (p<boundary) { \
+ if (*p == '\n' || (*p == '\r' && (*(p+1) != '\n'))) { \
+ CG(zend_lineno)++; \
+ } \
+ p++; \
+ } \
+} while (0)
+
+#define HANDLE_NEWLINE(c) \
+{ \
+ if (c == '\n' || c == '\r') { \
+ CG(zend_lineno)++; \
+ } \
+}
+
+/* To save initial string length after scanning to first variable, CG(doc_comment_len) can be reused */
+#define SET_DOUBLE_QUOTES_SCANNED_LENGTH(len) CG(doc_comment_len) = (len)
+#define GET_DOUBLE_QUOTES_SCANNED_LENGTH() CG(doc_comment_len)
+
+#define IS_LABEL_START(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || (c) == '_' || (c) >= 0x7F)
+
+#define ZEND_IS_OCT(c) ((c)>='0' && (c)<='7')
+#define ZEND_IS_HEX(c) (((c)>='0' && (c)<='9') || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F'))
+
+BEGIN_EXTERN_C()
+
+static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding) TSRMLS_CC);
+}
+
+static size_t encoding_filter_script_to_intermediate(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length, zend_multibyte_encoding_utf8, LANG_SCNG(script_encoding) TSRMLS_CC);
+}
+
+static size_t encoding_filter_intermediate_to_script(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length,
+LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8 TSRMLS_CC);
+}
+
+static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
+ return zend_multibyte_encoding_converter(to, to_length, from, from_length,
+internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC);
+}
+
+
+static void _yy_push_state(int new_state TSRMLS_DC)
+{
+ zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int));
+ YYSETCONDITION(new_state);
+}
+
+#define yy_push_state(state_and_tsrm) _yy_push_state(yyc##state_and_tsrm)
+
+static void yy_pop_state(TSRMLS_D)
+{
+ int *stack_state;
+ zend_stack_top(&SCNG(state_stack), (void **) &stack_state);
+ YYSETCONDITION(*stack_state);
+ zend_stack_del_top(&SCNG(state_stack));
+}
+
+static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC)
+{
+ YYCURSOR = (YYCTYPE*)str;
+ YYLIMIT = YYCURSOR + len;
+ if (!SCNG(yy_start)) {
+ SCNG(yy_start) = YYCURSOR;
+ }
+}
+
+void startup_scanner(TSRMLS_D)
+{
+ CG(parse_error) = 0;
+ CG(heredoc) = NULL;
+ CG(heredoc_len) = 0;
+ CG(doc_comment) = NULL;
+ CG(doc_comment_len) = 0;
+ zend_stack_init(&SCNG(state_stack));
+}
+
+void shutdown_scanner(TSRMLS_D)
+{
+ if (CG(heredoc)) {
+ efree(CG(heredoc));
+ CG(heredoc_len)=0;
+ }
+ CG(parse_error) = 0;
+ zend_stack_destroy(&SCNG(state_stack));
+ RESET_DOC_COMMENT();
+}
+
+ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
+{
+ lex_state->yy_leng = SCNG(yy_leng);
+ lex_state->yy_start = SCNG(yy_start);
+ lex_state->yy_text = SCNG(yy_text);
+ lex_state->yy_cursor = SCNG(yy_cursor);
+ lex_state->yy_marker = SCNG(yy_marker);
+ lex_state->yy_limit = SCNG(yy_limit);
+
+ lex_state->state_stack = SCNG(state_stack);
+ zend_stack_init(&SCNG(state_stack));
+
+ lex_state->in = SCNG(yy_in);
+ lex_state->yy_state = YYSTATE;
+ lex_state->filename = zend_get_compiled_filename(TSRMLS_C);
+ lex_state->lineno = CG(zend_lineno);
+
+ lex_state->script_org = SCNG(script_org);
+ lex_state->script_org_size = SCNG(script_org_size);
+ lex_state->script_filtered = SCNG(script_filtered);
+ lex_state->script_filtered_size = SCNG(script_filtered_size);
+ lex_state->input_filter = SCNG(input_filter);
+ lex_state->output_filter = SCNG(output_filter);
+ lex_state->script_encoding = SCNG(script_encoding);
+}
+
+ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
+{
+ SCNG(yy_leng) = lex_state->yy_leng;
+ SCNG(yy_start) = lex_state->yy_start;
+ SCNG(yy_text) = lex_state->yy_text;
+ SCNG(yy_cursor) = lex_state->yy_cursor;
+ SCNG(yy_marker) = lex_state->yy_marker;
+ SCNG(yy_limit) = lex_state->yy_limit;
+
+ zend_stack_destroy(&SCNG(state_stack));
+ SCNG(state_stack) = lex_state->state_stack;
+
+ SCNG(yy_in) = lex_state->in;
+ YYSETCONDITION(lex_state->yy_state);
+ CG(zend_lineno) = lex_state->lineno;
+ zend_restore_compiled_filename(lex_state->filename TSRMLS_CC);
+
+ if (SCNG(script_filtered)) {
+ efree(SCNG(script_filtered));
+ SCNG(script_filtered) = NULL;
+ }
+ SCNG(script_org) = lex_state->script_org;
+ SCNG(script_org_size) = lex_state->script_org_size;
+ SCNG(script_filtered) = lex_state->script_filtered;
+ SCNG(script_filtered_size) = lex_state->script_filtered_size;
+ SCNG(input_filter) = lex_state->input_filter;
+ SCNG(output_filter) = lex_state->output_filter;
+ SCNG(script_encoding) = lex_state->script_encoding;
+
+ if (CG(heredoc)) {
+ efree(CG(heredoc));
+ CG(heredoc) = NULL;
+ CG(heredoc_len) = 0;
+ }
+}
+
+ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC)
+{
+ zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles);
+ /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */
+ file_handle->opened_path = NULL;
+ if (file_handle->free_filename) {
+ file_handle->filename = NULL;
+ }
+}
+
+#define BOM_UTF32_BE "\x00\x00\xfe\xff"
+#define BOM_UTF32_LE "\xff\xfe\x00\x00"
+#define BOM_UTF16_BE "\xfe\xff"
+#define BOM_UTF16_LE "\xff\xfe"
+#define BOM_UTF8 "\xef\xbb\xbf"
+
+static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC)
+{
+ const unsigned char *p;
+ int wchar_size = 2;
+ int le = 0;
+
+ /* utf-16 or utf-32? */
+ p = script;
+ while ((p-script) < script_size) {
+ p = memchr(p, 0, script_size-(p-script)-2);
+ if (!p) {
+ break;
+ }
+ if (*(p+1) == '\0' && *(p+2) == '\0') {
+ wchar_size = 4;
+ break;
+ }
+
+ /* searching for UTF-32 specific byte orders, so this will do */
+ p += 4;
+ }
+
+ /* BE or LE? */
+ p = script;
+ while ((p-script) < script_size) {
+ if (*p == '\0' && *(p+wchar_size-1) != '\0') {
+ /* BE */
+ le = 0;
+ break;
+ } else if (*p != '\0' && *(p+wchar_size-1) == '\0') {
+ /* LE* */
+ le = 1;
+ break;
+ }
+ p += wchar_size;
+ }
+
+ if (wchar_size == 2) {
+ return le ? zend_multibyte_encoding_utf16le : zend_multibyte_encoding_utf16be;
+ } else {
+ return le ? zend_multibyte_encoding_utf32le : zend_multibyte_encoding_utf32be;
+ }
+
+ return NULL;
+}
+
+static const zend_encoding* zend_multibyte_detect_unicode(TSRMLS_D)
+{
+ const zend_encoding *script_encoding = NULL;
+ int bom_size;
+ unsigned char *pos1, *pos2;
+
+ if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) {
+ return NULL;
+ }
+
+ /* check out BOM */
+ if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf32be;
+ bom_size = sizeof(BOM_UTF32_BE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf32le;
+ bom_size = sizeof(BOM_UTF32_LE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf16be;
+ bom_size = sizeof(BOM_UTF16_BE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) {
+ script_encoding = zend_multibyte_encoding_utf16le;
+ bom_size = sizeof(BOM_UTF16_LE)-1;
+ } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) {
+ script_encoding = zend_multibyte_encoding_utf8;
+ bom_size = sizeof(BOM_UTF8)-1;
+ }
+
+ if (script_encoding) {
+ /* remove BOM */
+ LANG_SCNG(script_org) += bom_size;
+ LANG_SCNG(script_org_size) -= bom_size;
+
+ return script_encoding;
+ }
+
+ /* script contains NULL bytes -> auto-detection */
+ if ((pos1 = memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size)))) {
+ /* check if the NULL byte is after the __HALT_COMPILER(); */
+ pos2 = LANG_SCNG(script_org);
+
+ while (pos1 - pos2 >= sizeof("__HALT_COMPILER();")-1) {
+ pos2 = memchr(pos2, '_', pos1 - pos2);
+ if (!pos2) break;
+ pos2++;
+ if (strncasecmp((char*)pos2, "_HALT_COMPILER", sizeof("_HALT_COMPILER")-1) == 0) {
+ pos2 += sizeof("_HALT_COMPILER")-1;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == '(') {
+ pos2++;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == ')') {
+ pos2++;
+ while (*pos2 == ' ' ||
+ *pos2 == '\t' ||
+ *pos2 == '\r' ||
+ *pos2 == '\n') {
+ pos2++;
+ }
+ if (*pos2 == ';') {
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+ /* make best effort if BOM is missing */
+ return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size) TSRMLS_CC);
+ }
+
+ return NULL;
+}
+
+static const zend_encoding* zend_multibyte_find_script_encoding(TSRMLS_D)
+{
+ const zend_encoding *script_encoding;
+
+ if (CG(detect_unicode)) {
+ /* check out bom(byte order mark) and see if containing wchars */
+ script_encoding = zend_multibyte_detect_unicode(TSRMLS_C);
+ if (script_encoding != NULL) {
+ /* bom or wchar detection is prior to 'script_encoding' option */
+ return script_encoding;
+ }
+ }
+
+ /* if no script_encoding specified, just leave alone */
+ if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) {
+ return NULL;
+ }
+
+ /* if multiple encodings specified, detect automagically */
+ if (CG(script_encoding_list_size) > 1) {
+ return zend_multibyte_encoding_detector(LANG_SCNG(script_org), LANG_SCNG(script_org_size), CG(script_encoding_list), CG(script_encoding_list_size) TSRMLS_CC);
+ }
+
+ return CG(script_encoding_list)[0];
+}
+
+ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding TSRMLS_DC)
+{
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ const zend_encoding *script_encoding = onetime_encoding ? onetime_encoding: zend_multibyte_find_script_encoding(TSRMLS_C);
+
+ if (!script_encoding) {
+ return FAILURE;
+ }
+
+ /* judge input/output filter */
+ LANG_SCNG(script_encoding) = script_encoding;
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = NULL;
+
+ if (!internal_encoding || LANG_SCNG(script_encoding) == internal_encoding) {
+ if (!zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
+ /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
+ LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
+ LANG_SCNG(output_filter) = encoding_filter_intermediate_to_script;
+ } else {
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = NULL;
+ }
+ return SUCCESS;
+ }
+
+ if (zend_multibyte_check_lexer_compatibility(internal_encoding)) {
+ LANG_SCNG(input_filter) = encoding_filter_script_to_internal;
+ LANG_SCNG(output_filter) = NULL;
+ } else if (zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
+ LANG_SCNG(input_filter) = NULL;
+ LANG_SCNG(output_filter) = encoding_filter_script_to_internal;
+ } else {
+ /* both script and internal encodings are incompatible w/ flex */
+ LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
+ LANG_SCNG(output_filter) = encoding_filter_intermediate_to_internal;
+ }
+
+ return 0;
+}
+
+ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
+{
+ const char *file_path = NULL;
+ char *buf;
+ size_t size, offset = 0;
+
+ /* The shebang line was read, get the current position to obtain the buffer start */
+ if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) {
+ if ((offset = ftell(file_handle->handle.fp)) == -1) {
+ offset = 0;
+ }
+ }
+
+ if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) {
+ return FAILURE;
+ }
+
+ zend_llist_add_element(&CG(open_files), file_handle);
+ if (file_handle->handle.stream.handle >= (void*)file_handle && file_handle->handle.stream.handle <= (void*)(file_handle+1)) {
+ zend_file_handle *fh = (zend_file_handle*)zend_llist_get_last(&CG(open_files));
+ size_t diff = (char*)file_handle->handle.stream.handle - (char*)file_handle;
+ fh->handle.stream.handle = (void*)(((char*)fh) + diff);
+ file_handle->handle.stream.handle = fh->handle.stream.handle;
+ }
+
+ /* Reset the scanner for scanning the new file */
+ SCNG(yy_in) = file_handle;
+ SCNG(yy_start) = NULL;
+
+ if (size != -1) {
+ if (CG(multibyte)) {
+ SCNG(script_org) = (unsigned char*)buf;
+ SCNG(script_org_size) = size;
+ SCNG(script_filtered) = NULL;
+
+ zend_multibyte_set_filter(NULL TSRMLS_CC);
+
+ if (SCNG(input_filter)) {
+ if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
+ }
+ buf = (char*)SCNG(script_filtered);
+ size = SCNG(script_filtered_size);
+ }
+ }
+ SCNG(yy_start) = (unsigned char *)buf - offset;
+ yy_scan_buffer(buf, size TSRMLS_CC);
+ } else {
+ zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed");
+ }
+
+ BEGIN(INITIAL);
+
+ if (file_handle->opened_path) {
+ file_path = file_handle->opened_path;
+ } else {
+ file_path = file_handle->filename;
+ }
+
+ zend_set_compiled_filename(file_path TSRMLS_CC);
+
+ if (CG(start_lineno)) {
+ CG(zend_lineno) = CG(start_lineno);
+ CG(start_lineno) = 0;
+ } else {
+ CG(zend_lineno) = 1;
+ }
+
+ CG(increment_lineno) = 0;
+ return SUCCESS;
+}
+END_EXTERN_C()
+
+
+ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
+{
+ zend_lex_state original_lex_state;
+ zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
+ zend_op_array *original_active_op_array = CG(active_op_array);
+ zend_op_array *retval=NULL;
+ int compiler_result;
+ zend_bool compilation_successful=0;
+ znode retval_znode;
+ zend_bool original_in_compilation = CG(in_compilation);
+
+ retval_znode.op_type = IS_CONST;
+ retval_znode.u.constant.type = IS_LONG;
+ retval_znode.u.constant.value.lval = 1;
+ Z_UNSET_ISREF(retval_znode.u.constant);
+ Z_SET_REFCOUNT(retval_znode.u.constant, 1);
+
+ zend_save_lexical_state(&original_lex_state TSRMLS_CC);
+
+ retval = op_array; /* success oriented */
+
+ if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
+ if (type==ZEND_REQUIRE) {
+ zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
+ zend_bailout();
+ } else {
+ zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
+ }
+ compilation_successful=0;
+ } else {
+ init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
+ CG(in_compilation) = 1;
+ CG(active_op_array) = op_array;
+ zend_init_compiler_context(TSRMLS_C);
+ compiler_result = zendparse(TSRMLS_C);
+ zend_do_return(&retval_znode, 0 TSRMLS_CC);
+ CG(in_compilation) = original_in_compilation;
+ if (compiler_result==1) { /* parser error */
+ zend_bailout();
+ }
+ compilation_successful=1;
+ }
+
+ if (retval) {
+ CG(active_op_array) = original_active_op_array;
+ if (compilation_successful) {
+ pass_two(op_array TSRMLS_CC);
+ zend_release_labels(TSRMLS_C);
+ } else {
+ efree(op_array);
+ retval = NULL;
+ }
+ }
+ zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
+ return retval;
+}
+
+
+zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
+{
+ zend_file_handle file_handle;
+ zval tmp;
+ zend_op_array *retval;
+ char *opened_path = NULL;
+
+ if (filename->type != IS_STRING) {
+ tmp = *filename;
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ filename = &tmp;
+ }
+ file_handle.filename = filename->value.str.val;
+ file_handle.free_filename = 0;
+ file_handle.type = ZEND_HANDLE_FILENAME;
+ file_handle.opened_path = NULL;
+ file_handle.handle.fp = NULL;
+
+ retval = zend_compile_file(&file_handle, type TSRMLS_CC);
+ if (retval && file_handle.handle.stream.handle) {
+ int dummy = 1;
+
+ if (!file_handle.opened_path) {
+ file_handle.opened_path = opened_path = estrndup(filename->value.str.val, filename->value.str.len);
+ }
+
+ zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL);
+
+ if (opened_path) {
+ efree(opened_path);
+ }
+ }
+ zend_destroy_file_handle(&file_handle TSRMLS_CC);
+
+ if (filename==&tmp) {
+ zval_dtor(&tmp);
+ }
+ return retval;
+}
+
+ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
+{
+ char *buf;
+ size_t size;
+
+ /* enforce two trailing NULLs for flex... */
+ if (IS_INTERNED(str->value.str.val)) {
+ char *tmp = safe_emalloc(1, str->value.str.len, ZEND_MMAP_AHEAD);
+ memcpy(tmp, str->value.str.val, str->value.str.len + ZEND_MMAP_AHEAD);
+ str->value.str.val = tmp;
+ } else {
+ str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
+ }
+
+ memset(str->value.str.val + str->value.str.len, 0, ZEND_MMAP_AHEAD);
+
+ SCNG(yy_in) = NULL;
+ SCNG(yy_start) = NULL;
+
+ buf = str->value.str.val;
+ size = str->value.str.len;
+
+ if (CG(multibyte)) {
+ SCNG(script_org) = (unsigned char*)buf;
+ SCNG(script_org_size) = size;
+ SCNG(script_filtered) = NULL;
+
+ zend_multibyte_set_filter(zend_multibyte_get_internal_encoding(TSRMLS_C) TSRMLS_CC);
+
+ if (SCNG(input_filter)) {
+ if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
+ }
+ buf = (char*)SCNG(script_filtered);
+ size = SCNG(script_filtered_size);
+ }
+ }
+
+ yy_scan_buffer(buf, size TSRMLS_CC);
+
+ zend_set_compiled_filename(filename TSRMLS_CC);
+ CG(zend_lineno) = 1;
+ CG(increment_lineno) = 0;
+ return SUCCESS;
+}
+
+
+ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
+{
+ size_t offset = SCNG(yy_cursor) - SCNG(yy_start);
+ if (SCNG(input_filter)) {
+ size_t original_offset = offset, length = 0;
+ do {
+ unsigned char *p = NULL;
+ if ((size_t)-1 == SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC)) {
+ return (size_t)-1;
+ }
+ efree(p);
+ if (length > original_offset) {
+ offset--;
+ } else if (length < original_offset) {
+ offset++;
+ }
+ } while (original_offset != length);
+ }
+ return offset;
+}
+
+
+zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
+{
+ zend_lex_state original_lex_state;
+ zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
+ zend_op_array *original_active_op_array = CG(active_op_array);
+ zend_op_array *retval;
+ zval tmp;
+ int compiler_result;
+ zend_bool original_in_compilation = CG(in_compilation);
+
+ if (source_string->value.str.len==0) {
+ efree(op_array);
+ return NULL;
+ }
+
+ CG(in_compilation) = 1;
+
+ tmp = *source_string;
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ source_string = &tmp;
+
+ zend_save_lexical_state(&original_lex_state TSRMLS_CC);
+ if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) {
+ efree(op_array);
+ retval = NULL;
+ } else {
+ zend_bool orig_interactive = CG(interactive);
+
+ CG(interactive) = 0;
+ init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
+ CG(interactive) = orig_interactive;
+ CG(active_op_array) = op_array;
+ zend_init_compiler_context(TSRMLS_C);
+ BEGIN(ST_IN_SCRIPTING);
+ compiler_result = zendparse(TSRMLS_C);
+
+ if (SCNG(script_filtered)) {
+ efree(SCNG(script_filtered));
+ SCNG(script_filtered) = NULL;
+ }
+
+ if (compiler_result==1) {
+ CG(active_op_array) = original_active_op_array;
+ CG(unclean_shutdown)=1;
+ destroy_op_array(op_array TSRMLS_CC);
+ efree(op_array);
+ retval = NULL;
+ } else {
+ zend_do_return(NULL, 0 TSRMLS_CC);
+ CG(active_op_array) = original_active_op_array;
+ pass_two(op_array TSRMLS_CC);
+ zend_release_labels(TSRMLS_C);
+ retval = op_array;
+ }
+ }
+ zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
+ zval_dtor(&tmp);
+ CG(in_compilation) = original_in_compilation;
+ return retval;
+}
+
+
+BEGIN_EXTERN_C()
+int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC)
+{
+ zend_lex_state original_lex_state;
+ zend_file_handle file_handle;
+
+ file_handle.type = ZEND_HANDLE_FILENAME;
+ file_handle.filename = filename;
+ file_handle.free_filename = 0;
+ file_handle.opened_path = NULL;
+ zend_save_lexical_state(&original_lex_state TSRMLS_CC);
+ if (open_file_for_scanning(&file_handle TSRMLS_CC)==FAILURE) {
+ zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename TSRMLS_CC);
+ zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
+ return FAILURE;
+ }
+ zend_highlight(syntax_highlighter_ini TSRMLS_CC);
+ if (SCNG(script_filtered)) {
+ efree(SCNG(script_filtered));
+ SCNG(script_filtered) = NULL;
+ }
+ zend_destroy_file_handle(&file_handle TSRMLS_CC);
+ zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
+ return SUCCESS;
+}
+
+int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC)
+{
+ zend_lex_state original_lex_state;
+ zval tmp = *str;
+
+ str = &tmp;
+ zval_copy_ctor(str);
+ zend_save_lexical_state(&original_lex_state TSRMLS_CC);
+ if (zend_prepare_string_for_scanning(str, str_name TSRMLS_CC)==FAILURE) {
+ zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
+ return FAILURE;
+ }
+ BEGIN(INITIAL);
+ zend_highlight(syntax_highlighter_ini TSRMLS_CC);
+ if (SCNG(script_filtered)) {
+ efree(SCNG(script_filtered));
+ SCNG(script_filtered) = NULL;
+ }
+ zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
+ zval_dtor(str);
+ return SUCCESS;
+}
+
+ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding TSRMLS_DC)
+{
+ size_t length;
+ unsigned char *new_yy_start;
+
+ /* convert and set */
+ if (!SCNG(input_filter)) {
+ if (SCNG(script_filtered)) {
+ efree(SCNG(script_filtered));
+ SCNG(script_filtered) = NULL;
+ }
+ SCNG(script_filtered_size) = 0;
+ length = SCNG(script_org_size);
+ new_yy_start = SCNG(script_org);
+ } else {
+ if ((size_t)-1 == SCNG(input_filter)(&new_yy_start, &length, SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
+ "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
+ }
+ SCNG(script_filtered) = new_yy_start;
+ SCNG(script_filtered_size) = length;
+ }
+
+ SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
+ SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
+ SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
+ SCNG(yy_limit) = new_yy_start + (SCNG(yy_limit) - SCNG(yy_start));
+
+ SCNG(yy_start) = new_yy_start;
+}
+
+
+# define zend_copy_value(zendlval, yytext, yyleng) \
+ if (SCNG(output_filter)) { \
+ size_t sz = 0; \
+ SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC); \
+ zendlval->value.str.len = sz; \
+ } else { \
+ zendlval->value.str.val = (char *) estrndup(yytext, yyleng); \
+ zendlval->value.str.len = yyleng; \
+ }
+
+static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
+{
+ register char *s, *t;
+ char *end;
+
+ ZVAL_STRINGL(zendlval, str, len, 1);
+
+ /* convert escape sequences */
+ s = t = zendlval->value.str.val;
+ end = s+zendlval->value.str.len;
+ while (s<end) {
+ if (*s=='\\') {
+ s++;
+ if (s >= end) {
+ *t++ = '\\';
+ break;
+ }
+
+ switch(*s) {
+ case 'n':
+ *t++ = '\n';
+ zendlval->value.str.len--;
+ break;
+ case 'r':
+ *t++ = '\r';
+ zendlval->value.str.len--;
+ break;
+ case 't':
+ *t++ = '\t';
+ zendlval->value.str.len--;
+ break;
+ case 'f':
+ *t++ = '\f';
+ zendlval->value.str.len--;
+ break;
+ case 'v':
+ *t++ = '\v';
+ zendlval->value.str.len--;
+ break;
+ case 'e':
+ *t++ = '\e';
+ zendlval->value.str.len--;
+ break;
+ case '"':
+ case '`':
+ if (*s != quote_type) {
+ *t++ = '\\';
+ *t++ = *s;
+ break;
+ }
+ case '\\':
+ case '$':
+ *t++ = *s;
+ zendlval->value.str.len--;
+ break;
+ case 'x':
+ case 'X':
+ if (ZEND_IS_HEX(*(s+1))) {
+ char hex_buf[3] = { 0, 0, 0 };
+
+ zendlval->value.str.len--; /* for the 'x' */
+
+ hex_buf[0] = *(++s);
+ zendlval->value.str.len--;
+ if (ZEND_IS_HEX(*(s+1))) {
+ hex_buf[1] = *(++s);
+ zendlval->value.str.len--;
+ }
+ *t++ = (char) strtol(hex_buf, NULL, 16);
+ } else {
+ *t++ = '\\';
+ *t++ = *s;
+ }
+ break;
+ default:
+ /* check for an octal */
+ if (ZEND_IS_OCT(*s)) {
+ char octal_buf[4] = { 0, 0, 0, 0 };
+
+ octal_buf[0] = *s;
+ zendlval->value.str.len--;
+ if (ZEND_IS_OCT(*(s+1))) {
+ octal_buf[1] = *(++s);
+ zendlval->value.str.len--;
+ if (ZEND_IS_OCT(*(s+1))) {
+ octal_buf[2] = *(++s);
+ zendlval->value.str.len--;
+ }
+ }
+ *t++ = (char) strtol(octal_buf, NULL, 8);
+ } else {
+ *t++ = '\\';
+ *t++ = *s;
+ }
+ break;
+ }
+ } else {
+ *t++ = *s;
+ }
+
+ if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
+ CG(zend_lineno)++;
+ }
+ s++;
+ }
+ *t = 0;
+ if (SCNG(output_filter)) {
+ size_t sz = 0;
+ s = zendlval->value.str.val;
+ SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)s, (size_t)zendlval->value.str.len TSRMLS_CC);
+ zendlval->value.str.len = sz;
+ efree(s);
+ }
+}
+
+
+int lex_scan(zval *zendlval TSRMLS_DC)
+{
+restart:
+ SCNG(yy_text) = YYCURSOR;
+
+yymore_restart:
+
+/*!re2c
+re2c:yyfill:check = 0;
+LNUM [0-9]+
+DNUM ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)
+EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM})
+HNUM "0x"[0-9a-fA-F]+
+BNUM "0b"[01]+
+LABEL [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
+WHITESPACE [ \n\r\t]+
+TABS_AND_SPACES [ \t]*
+TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@]
+ANY_CHAR [^]
+NEWLINE ("\r"|"\n"|"\r\n")
+
+/* compute yyleng before each rule */
+<!*> := yyleng = YYCURSOR - SCNG(yy_text);
+
+
+<ST_IN_SCRIPTING>"exit" {
+ return T_EXIT;
+}
+
+<ST_IN_SCRIPTING>"die" {
+ return T_EXIT;
+}
+
+<ST_IN_SCRIPTING>"function" {
+ return T_FUNCTION;
+}
+
+<ST_IN_SCRIPTING>"const" {
+ return T_CONST;
+}
+
+<ST_IN_SCRIPTING>"return" {
+ return T_RETURN;
+}
+
+<ST_IN_SCRIPTING>"try" {
+ return T_TRY;
+}
+
+<ST_IN_SCRIPTING>"catch" {
+ return T_CATCH;
+}
+
+<ST_IN_SCRIPTING>"throw" {
+ return T_THROW;
+}
+
+<ST_IN_SCRIPTING>"if" {
+ return T_IF;
+}
+
+<ST_IN_SCRIPTING>"elseif" {
+ return T_ELSEIF;
+}
+
+<ST_IN_SCRIPTING>"endif" {
+ return T_ENDIF;
+}
+
+<ST_IN_SCRIPTING>"else" {
+ return T_ELSE;
+}
+
+<ST_IN_SCRIPTING>"while" {
+ return T_WHILE;
+}
+
+<ST_IN_SCRIPTING>"endwhile" {
+ return T_ENDWHILE;
+}
+
+<ST_IN_SCRIPTING>"do" {
+ return T_DO;
+}
+
+<ST_IN_SCRIPTING>"for" {
+ return T_FOR;
+}
+
+<ST_IN_SCRIPTING>"endfor" {
+ return T_ENDFOR;
+}
+
+<ST_IN_SCRIPTING>"foreach" {
+ return T_FOREACH;
+}
+
+<ST_IN_SCRIPTING>"endforeach" {
+ return T_ENDFOREACH;
+}
+
+<ST_IN_SCRIPTING>"declare" {
+ return T_DECLARE;
+}
+
+<ST_IN_SCRIPTING>"enddeclare" {
+ return T_ENDDECLARE;
+}
+
+<ST_IN_SCRIPTING>"instanceof" {
+ return T_INSTANCEOF;
+}
+
+<ST_IN_SCRIPTING>"as" {
+ return T_AS;
+}
+
+<ST_IN_SCRIPTING>"switch" {
+ return T_SWITCH;
+}
+
+<ST_IN_SCRIPTING>"endswitch" {
+ return T_ENDSWITCH;
+}
+
+<ST_IN_SCRIPTING>"case" {
+ return T_CASE;
+}
+
+<ST_IN_SCRIPTING>"default" {
+ return T_DEFAULT;
+}
+
+<ST_IN_SCRIPTING>"break" {
+ return T_BREAK;
+}
+
+<ST_IN_SCRIPTING>"continue" {
+ return T_CONTINUE;
+}
+
+<ST_IN_SCRIPTING>"goto" {
+ return T_GOTO;
+}
+
+<ST_IN_SCRIPTING>"echo" {
+ return T_ECHO;
+}
+
+<ST_IN_SCRIPTING>"print" {
+ return T_PRINT;
+}
+
+<ST_IN_SCRIPTING>"class" {
+ return T_CLASS;
+}
+
+<ST_IN_SCRIPTING>"interface" {
+ return T_INTERFACE;
+}
+
+<ST_IN_SCRIPTING>"trait" {
+ return T_TRAIT;
+}
+
+<ST_IN_SCRIPTING>"extends" {
+ return T_EXTENDS;
+}
+
+<ST_IN_SCRIPTING>"implements" {
+ return T_IMPLEMENTS;
+}
+
+<ST_IN_SCRIPTING>"->" {
+ yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
+ return T_OBJECT_OPERATOR;
+}
+
+<ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY>{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>"->" {
+ return T_OBJECT_OPERATOR;
+}
+
+<ST_LOOKING_FOR_PROPERTY>{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} {
+ yyless(0);
+ yy_pop_state(TSRMLS_C);
+ goto restart;
+}
+
+<ST_IN_SCRIPTING>"::" {
+ return T_PAAMAYIM_NEKUDOTAYIM;
+}
+
+<ST_IN_SCRIPTING>"\\" {
+ return T_NS_SEPARATOR;
+}
+
+<ST_IN_SCRIPTING>"new" {
+ return T_NEW;
+}
+
+<ST_IN_SCRIPTING>"clone" {
+ return T_CLONE;
+}
+
+<ST_IN_SCRIPTING>"var" {
+ return T_VAR;
+}
+
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" {
+ return T_INT_CAST;
+}
+
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" {
+ return T_DOUBLE_CAST;
+}
+
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("string"|"binary"){TABS_AND_SPACES}")" {
+ return T_STRING_CAST;
+}
+
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" {
+ return T_ARRAY_CAST;
+}
+
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" {
+ return T_OBJECT_CAST;
+}
+
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" {
+ return T_BOOL_CAST;
+}
+
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" {
+ return T_UNSET_CAST;
+}
+
+<ST_IN_SCRIPTING>"eval" {
+ return T_EVAL;
+}
+
+<ST_IN_SCRIPTING>"include" {
+ return T_INCLUDE;
+}
+
+<ST_IN_SCRIPTING>"include_once" {
+ return T_INCLUDE_ONCE;
+}
+
+<ST_IN_SCRIPTING>"require" {
+ return T_REQUIRE;
+}
+
+<ST_IN_SCRIPTING>"require_once" {
+ return T_REQUIRE_ONCE;
+}
+
+<ST_IN_SCRIPTING>"namespace" {
+ return T_NAMESPACE;
+}
+
+<ST_IN_SCRIPTING>"use" {
+ return T_USE;
+}
+
+<ST_IN_SCRIPTING>"insteadof" {
+ return T_INSTEADOF;
+}
+
+<ST_IN_SCRIPTING>"global" {
+ return T_GLOBAL;
+}
+
+<ST_IN_SCRIPTING>"isset" {
+ return T_ISSET;
+}
+
+<ST_IN_SCRIPTING>"empty" {
+ return T_EMPTY;
+}
+
+<ST_IN_SCRIPTING>"__halt_compiler" {
+ return T_HALT_COMPILER;
+}
+
+<ST_IN_SCRIPTING>"static" {
+ return T_STATIC;
+}
+
+<ST_IN_SCRIPTING>"abstract" {
+ return T_ABSTRACT;
+}
+
+<ST_IN_SCRIPTING>"final" {
+ return T_FINAL;
+}
+
+<ST_IN_SCRIPTING>"private" {
+ return T_PRIVATE;
+}
+
+<ST_IN_SCRIPTING>"protected" {
+ return T_PROTECTED;
+}
+
+<ST_IN_SCRIPTING>"public" {
+ return T_PUBLIC;
+}
+
+<ST_IN_SCRIPTING>"unset" {
+ return T_UNSET;
+}
+
+<ST_IN_SCRIPTING>"=>" {
+ return T_DOUBLE_ARROW;
+}
+
+<ST_IN_SCRIPTING>"list" {
+ return T_LIST;
+}
+
+<ST_IN_SCRIPTING>"array" {
+ return T_ARRAY;
+}
+
+<ST_IN_SCRIPTING>"callable" {
+ return T_CALLABLE;
+}
+
+<ST_IN_SCRIPTING>"++" {
+ return T_INC;
+}
+
+<ST_IN_SCRIPTING>"--" {
+ return T_DEC;
+}
+
+<ST_IN_SCRIPTING>"===" {
+ return T_IS_IDENTICAL;
+}
+
+<ST_IN_SCRIPTING>"!==" {
+ return T_IS_NOT_IDENTICAL;
+}
+
+<ST_IN_SCRIPTING>"==" {
+ return T_IS_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"!="|"<>" {
+ return T_IS_NOT_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"<=" {
+ return T_IS_SMALLER_OR_EQUAL;
+}
+
+<ST_IN_SCRIPTING>">=" {
+ return T_IS_GREATER_OR_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"+=" {
+ return T_PLUS_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"-=" {
+ return T_MINUS_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"*=" {
+ return T_MUL_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"/=" {
+ return T_DIV_EQUAL;
+}
+
+<ST_IN_SCRIPTING>".=" {
+ return T_CONCAT_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"%=" {
+ return T_MOD_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"<<=" {
+ return T_SL_EQUAL;
+}
+
+<ST_IN_SCRIPTING>">>=" {
+ return T_SR_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"&=" {
+ return T_AND_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"|=" {
+ return T_OR_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"^=" {
+ return T_XOR_EQUAL;
+}
+
+<ST_IN_SCRIPTING>"||" {
+ return T_BOOLEAN_OR;
+}
+
+<ST_IN_SCRIPTING>"&&" {
+ return T_BOOLEAN_AND;
+}
+
+<ST_IN_SCRIPTING>"OR" {
+ return T_LOGICAL_OR;
+}
+
+<ST_IN_SCRIPTING>"AND" {
+ return T_LOGICAL_AND;
+}
+
+<ST_IN_SCRIPTING>"XOR" {
+ return T_LOGICAL_XOR;
+}
+
+<ST_IN_SCRIPTING>"<<" {
+ return T_SL;
+}
+
+<ST_IN_SCRIPTING>">>" {
+ return T_SR;
+}
+
+<ST_IN_SCRIPTING>{TOKENS} {
+ return yytext[0];
+}
+
+
+<ST_IN_SCRIPTING>"{" {
+ yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
+ return '{';
+}
+
+
+<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"${" {
+ yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
+ return T_DOLLAR_OPEN_CURLY_BRACES;
+}
+
+
+<ST_IN_SCRIPTING>"}" {
+ RESET_DOC_COMMENT();
+ if (!zend_stack_is_empty(&SCNG(state_stack))) {
+ yy_pop_state(TSRMLS_C);
+ }
+ return '}';
+}
+
+
+<ST_LOOKING_FOR_VARNAME>{LABEL} {
+ zend_copy_value(zendlval, yytext, yyleng);
+ zendlval->type = IS_STRING;
+ yy_pop_state(TSRMLS_C);
+ yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
+ return T_STRING_VARNAME;
+}
+
+
+<ST_LOOKING_FOR_VARNAME>{ANY_CHAR} {
+ yyless(0);
+ yy_pop_state(TSRMLS_C);
+ yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
+ goto restart;
+}
+
+<ST_IN_SCRIPTING>{BNUM} {
+ char *bin = yytext + 2; /* Skip "0b" */
+ int len = yyleng - 2;
+
+ /* Skip any leading 0s */
+ while (*bin == '0') {
+ ++bin;
+ --len;
+ }
+
+ if (len < SIZEOF_LONG * 8) {
+ if (len == 0) {
+ zendlval->value.lval = 0;
+ } else {
+ zendlval->value.lval = strtol(bin, NULL, 2);
+ }
+ zendlval->type = IS_LONG;
+ return T_LNUMBER;
+ } else {
+ zendlval->value.dval = zend_bin_strtod(bin, NULL);
+ zendlval->type = IS_DOUBLE;
+ return T_DNUMBER;
+ }
+}
+
+<ST_IN_SCRIPTING>{LNUM} {
+ if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
+ zendlval->value.lval = strtol(yytext, NULL, 0);
+ } else {
+ errno = 0;
+ zendlval->value.lval = strtol(yytext, NULL, 0);
+ if (errno == ERANGE) { /* Overflow */
+ if (yytext[0] == '0') { /* octal overflow */
+ zendlval->value.dval = zend_oct_strtod(yytext, NULL);
+ } else {
+ zendlval->value.dval = zend_strtod(yytext, NULL);
+ }
+ zendlval->type = IS_DOUBLE;
+ return T_DNUMBER;
+ }
+ }
+
+ zendlval->type = IS_LONG;
+ return T_LNUMBER;
+}
+
+<ST_IN_SCRIPTING>{HNUM} {
+ char *hex = yytext + 2; /* Skip "0x" */
+ int len = yyleng - 2;
+
+ /* Skip any leading 0s */
+ while (*hex == '0') {
+ hex++;
+ len--;
+ }
+
+ if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) {
+ if (len == 0) {
+ zendlval->value.lval = 0;
+ } else {
+ zendlval->value.lval = strtol(hex, NULL, 16);
+ }
+ zendlval->type = IS_LONG;
+ return T_LNUMBER;
+ } else {
+ zendlval->value.dval = zend_hex_strtod(hex, NULL);
+ zendlval->type = IS_DOUBLE;
+ return T_DNUMBER;
+ }
+}
+
+<ST_VAR_OFFSET>[0]|([1-9][0-9]*) { /* Offset could be treated as a long */
+ if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
+ zendlval->value.lval = strtol(yytext, NULL, 10);
+ zendlval->type = IS_LONG;
+ } else {
+ zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ }
+ return T_NUM_STRING;
+}
+
+<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */
+ zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ return T_NUM_STRING;
+}
+
+<ST_IN_SCRIPTING>{DNUM}|{EXPONENT_DNUM} {
+ zendlval->value.dval = zend_strtod(yytext, NULL);
+ zendlval->type = IS_DOUBLE;
+ return T_DNUMBER;
+}
+
+<ST_IN_SCRIPTING>"__CLASS__" {
+ const char *class_name = NULL;
+
+ if (CG(active_class_entry)
+ && (ZEND_ACC_TRAIT ==
+ (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT))) {
+ /* We create a special __CLASS__ constant that is going to be resolved
+ at run-time */
+ zendlval->value.str.len = sizeof("__CLASS__")-1;
+ zendlval->value.str.val = estrndup("__CLASS__", zendlval->value.str.len);
+ zendlval->type = IS_CONSTANT;
+ } else {
+ if (CG(active_class_entry)) {
+ class_name = CG(active_class_entry)->name;
+ }
+
+ if (!class_name) {
+ class_name = "";
+ }
+
+ zendlval->value.str.len = strlen(class_name);
+ zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
+ zendlval->type = IS_STRING;
+ }
+ return T_CLASS_C;
+}
+
+<ST_IN_SCRIPTING>"__TRAIT__" {
+ const char *trait_name = NULL;
+
+ if (CG(active_class_entry)
+ && (ZEND_ACC_TRAIT ==
+ (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT))) {
+ trait_name = CG(active_class_entry)->name;
+ }
+
+ if (!trait_name) {
+ trait_name = "";
+ }
+
+ zendlval->value.str.len = strlen(trait_name);
+ zendlval->value.str.val = estrndup(trait_name, zendlval->value.str.len);
+ zendlval->type = IS_STRING;
+
+ return T_TRAIT_C;
+}
+
+<ST_IN_SCRIPTING>"__FUNCTION__" {
+ const char *func_name = NULL;
+
+ if (CG(active_op_array)) {
+ func_name = CG(active_op_array)->function_name;
+ }
+
+ if (!func_name) {
+ func_name = "";
+ }
+ zendlval->value.str.len = strlen(func_name);
+ zendlval->value.str.val = estrndup(func_name, zendlval->value.str.len);
+ zendlval->type = IS_STRING;
+ return T_FUNC_C;
+}
+
+<ST_IN_SCRIPTING>"__METHOD__" {
+ const char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
+ const char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
+ size_t len = 0;
+
+ if (class_name) {
+ len += strlen(class_name) + 2;
+ }
+ if (func_name) {
+ len += strlen(func_name);
+ }
+
+ zendlval->value.str.len = zend_spprintf(&zendlval->value.str.val, 0, "%s%s%s",
+ class_name ? class_name : "",
+ class_name && func_name ? "::" : "",
+ func_name ? func_name : ""
+ );
+ zendlval->type = IS_STRING;
+ return T_METHOD_C;
+}
+
+<ST_IN_SCRIPTING>"__LINE__" {
+ zendlval->value.lval = CG(zend_lineno);
+ zendlval->type = IS_LONG;
+ return T_LINE;
+}
+
+<ST_IN_SCRIPTING>"__FILE__" {
+ char *filename = zend_get_compiled_filename(TSRMLS_C);
+
+ if (!filename) {
+ filename = "";
+ }
+ zendlval->value.str.len = strlen(filename);
+ zendlval->value.str.val = estrndup(filename, zendlval->value.str.len);
+ zendlval->type = IS_STRING;
+ return T_FILE;
+}
+
+<ST_IN_SCRIPTING>"__DIR__" {
+ char *filename = zend_get_compiled_filename(TSRMLS_C);
+ const size_t filename_len = strlen(filename);
+ char *dirname;
+
+ if (!filename) {
+ filename = "";
+ }
+
+ dirname = estrndup(filename, filename_len);
+ zend_dirname(dirname, filename_len);
+
+ if (strcmp(dirname, ".") == 0) {
+ dirname = erealloc(dirname, MAXPATHLEN);
+#if HAVE_GETCWD
+ VCWD_GETCWD(dirname, MAXPATHLEN);
+#elif HAVE_GETWD
+ VCWD_GETWD(dirname);
+#endif
+ }
+
+ zendlval->value.str.len = strlen(dirname);
+ zendlval->value.str.val = dirname;
+ zendlval->type = IS_STRING;
+ return T_DIR;
+}
+
+<ST_IN_SCRIPTING>"__NAMESPACE__" {
+ if (CG(current_namespace)) {
+ *zendlval = *CG(current_namespace);
+ zval_copy_ctor(zendlval);
+ } else {
+ ZVAL_EMPTY_STRING(zendlval);
+ }
+ return T_NS_C;
+}
+
+<INITIAL>"<script"{WHITESPACE}+"language"{WHITESPACE}*"="{WHITESPACE}*("php"|"\"php\""|"'php'"){WHITESPACE}*">" {
+ YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
+
+ if (bracket != SCNG(yy_text)) {
+ /* Handle previously scanned HTML, as possible <script> tags found are assumed to not be PHP's */
+ YYCURSOR = bracket;
+ goto inline_html;
+ }
+
+ HANDLE_NEWLINES(yytext, yyleng);
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ BEGIN(ST_IN_SCRIPTING);
+ return T_OPEN_TAG;
+}
+
+
+<INITIAL>"<%=" {
+ if (CG(asp_tags)) {
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ BEGIN(ST_IN_SCRIPTING);
+ return T_OPEN_TAG_WITH_ECHO;
+ } else {
+ goto inline_char_handler;
+ }
+}
+
+
+<INITIAL>"<?=" {
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ BEGIN(ST_IN_SCRIPTING);
+ return T_OPEN_TAG_WITH_ECHO;
+}
+
+
+<INITIAL>"<%" {
+ if (CG(asp_tags)) {
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ BEGIN(ST_IN_SCRIPTING);
+ return T_OPEN_TAG;
+ } else {
+ goto inline_char_handler;
+ }
+}
+
+
+<INITIAL>"<?php"([ \t]|{NEWLINE}) {
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ HANDLE_NEWLINE(yytext[yyleng-1]);
+ BEGIN(ST_IN_SCRIPTING);
+ return T_OPEN_TAG;
+}
+
+
+<INITIAL>"<?" {
+ if (CG(short_tags)) {
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ BEGIN(ST_IN_SCRIPTING);
+ return T_OPEN_TAG;
+ } else {
+ goto inline_char_handler;
+ }
+}
+
+<INITIAL>{ANY_CHAR} {
+ if (YYCURSOR > YYLIMIT) {
+ return 0;
+ }
+
+inline_char_handler:
+
+ while (1) {
+ YYCTYPE *ptr = memchr(YYCURSOR, '<', YYLIMIT - YYCURSOR);
+
+ YYCURSOR = ptr ? ptr + 1 : YYLIMIT;
+
+ if (YYCURSOR < YYLIMIT) {
+ switch (*YYCURSOR) {
+ case '?':
+ if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */
+ break;
+ }
+ continue;
+ case '%':
+ if (CG(asp_tags)) {
+ break;
+ }
+ continue;
+ case 's':
+ case 'S':
+ /* Probably NOT an opening PHP <script> tag, so don't end the HTML chunk yet
+ * If it is, the PHP <script> tag rule checks for any HTML scanned before it */
+ YYCURSOR--;
+ yymore();
+ default:
+ continue;
+ }
+
+ YYCURSOR--;
+ }
+
+ break;
+ }
+
+inline_html:
+ yyleng = YYCURSOR - SCNG(yy_text);
+
+ if (SCNG(output_filter)) {
+ int readsize;
+ size_t sz = 0;
+ readsize = SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC);
+ zendlval->value.str.len = sz;
+ if (readsize < yyleng) {
+ yyless(readsize);
+ }
+ } else {
+ zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
+ zendlval->value.str.len = yyleng;
+ }
+ zendlval->type = IS_STRING;
+ HANDLE_NEWLINES(yytext, yyleng);
+ return T_INLINE_HTML;
+}
+
+
+/* Make sure a label character follows "->", otherwise there is no property
+ * and "->" will be taken literally
+ */
+<ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"->"[a-zA-Z_\x7f-\xff] {
+ yyless(yyleng - 3);
+ yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
+ zend_copy_value(zendlval, (yytext+1), (yyleng-1));
+ zendlval->type = IS_STRING;
+ return T_VARIABLE;
+}
+
+/* A [ always designates a variable offset, regardless of what follows
+ */
+<ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"[" {
+ yyless(yyleng - 1);
+ yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
+ zend_copy_value(zendlval, (yytext+1), (yyleng-1));
+ zendlval->type = IS_STRING;
+ return T_VARIABLE;
+}
+
+<ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {
+ zend_copy_value(zendlval, (yytext+1), (yyleng-1));
+ zendlval->type = IS_STRING;
+ return T_VARIABLE;
+}
+
+<ST_VAR_OFFSET>"]" {
+ yy_pop_state(TSRMLS_C);
+ return ']';
+}
+
+<ST_VAR_OFFSET>{TOKENS}|[{}"`] {
+ /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
+ return yytext[0];
+}
+
+<ST_VAR_OFFSET>[ \n\r\t\\'#] {
+ /* Invalid rule to return a more explicit parse error with proper line number */
+ yyless(0);
+ yy_pop_state(TSRMLS_C);
+ return T_ENCAPSED_AND_WHITESPACE;
+}
+
+<ST_IN_SCRIPTING,ST_VAR_OFFSET>{LABEL} {
+ zend_copy_value(zendlval, yytext, yyleng);
+ zendlval->type = IS_STRING;
+ return T_STRING;
+}
+
+
+<ST_IN_SCRIPTING>"#"|"//" {
+ while (YYCURSOR < YYLIMIT) {
+ switch (*YYCURSOR++) {
+ case '\r':
+ if (*YYCURSOR == '\n') {
+ YYCURSOR++;
+ }
+ /* fall through */
+ case '\n':
+ CG(zend_lineno)++;
+ break;
+ case '%':
+ if (!CG(asp_tags)) {
+ continue;
+ }
+ /* fall through */
+ case '?':
+ if (*YYCURSOR == '>') {
+ YYCURSOR--;
+ break;
+ }
+ /* fall through */
+ default:
+ continue;
+ }
+
+ break;
+ }
+
+ yyleng = YYCURSOR - SCNG(yy_text);
+
+ return T_COMMENT;
+}
+
+<ST_IN_SCRIPTING>"/*"|"/**"{WHITESPACE} {
+ int doc_com;
+
+ if (yyleng > 2) {
+ doc_com = 1;
+ RESET_DOC_COMMENT();
+ } else {
+ doc_com = 0;
+ }
+
+ while (YYCURSOR < YYLIMIT) {
+ if (*YYCURSOR++ == '*' && *YYCURSOR == '/') {
+ break;
+ }
+ }
+
+ if (YYCURSOR < YYLIMIT) {
+ YYCURSOR++;
+ } else {
+ zend_error(E_COMPILE_WARNING, "Unterminated comment starting line %d", CG(zend_lineno));
+ }
+
+ yyleng = YYCURSOR - SCNG(yy_text);
+ HANDLE_NEWLINES(yytext, yyleng);
+
+ if (doc_com) {
+ CG(doc_comment) = estrndup(yytext, yyleng);
+ CG(doc_comment_len) = yyleng;
+ return T_DOC_COMMENT;
+ }
+
+ return T_COMMENT;
+}
+
+<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ BEGIN(INITIAL);
+ return T_CLOSE_TAG; /* implicit ';' at php-end tag */
+}
+
+
+<ST_IN_SCRIPTING>"%>"{NEWLINE}? {
+ if (CG(asp_tags)) {
+ BEGIN(INITIAL);
+ zendlval->value.str.len = yyleng;
+ zendlval->type = IS_STRING;
+ zendlval->value.str.val = yytext; /* no copying - intentional */
+ return T_CLOSE_TAG; /* implicit ';' at php-end tag */
+ } else {
+ yyless(1);
+ return yytext[0];
+ }
+}
+
+
+<ST_IN_SCRIPTING>b?['] {
+ register char *s, *t;
+ char *end;
+ int bprefix = (yytext[0] != '\'') ? 1 : 0;
+
+ while (1) {
+ if (YYCURSOR < YYLIMIT) {
+ if (*YYCURSOR == '\'') {
+ YYCURSOR++;
+ yyleng = YYCURSOR - SCNG(yy_text);
+
+ break;
+ } else if (*YYCURSOR++ == '\\' && YYCURSOR < YYLIMIT) {
+ YYCURSOR++;
+ }
+ } else {
+ yyleng = YYLIMIT - SCNG(yy_text);
+
+ /* Unclosed single quotes; treat similar to double quotes, but without a separate token
+ * for ' (unrecognized by parser), instead of old flex fallback to "Unexpected character..."
+ * rule, which continued in ST_IN_SCRIPTING state after the quote */
+ return T_ENCAPSED_AND_WHITESPACE;
+ }
+ }
+
+ zendlval->value.str.val = estrndup(yytext+bprefix+1, yyleng-bprefix-2);
+ zendlval->value.str.len = yyleng-bprefix-2;
+ zendlval->type = IS_STRING;
+
+ /* convert escape sequences */
+ s = t = zendlval->value.str.val;
+ end = s+zendlval->value.str.len;
+ while (s<end) {
+ if (*s=='\\') {
+ s++;
+
+ switch(*s) {
+ case '\\':
+ case '\'':
+ *t++ = *s;
+ zendlval->value.str.len--;
+ break;
+ default:
+ *t++ = '\\';
+ *t++ = *s;
+ break;
+ }
+ } else {
+ *t++ = *s;
+ }
+
+ if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
+ CG(zend_lineno)++;
+ }
+ s++;
+ }
+ *t = 0;
+
+ if (SCNG(output_filter)) {
+ size_t sz = 0;
+ s = zendlval->value.str.val;
+ SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)s, (size_t)zendlval->value.str.len TSRMLS_CC);
+ zendlval->value.str.len = sz;
+ efree(s);
+ }
+ return T_CONSTANT_ENCAPSED_STRING;
+}
+
+
+<ST_IN_SCRIPTING>b?["] {
+ int bprefix = (yytext[0] != '"') ? 1 : 0;
+
+ while (YYCURSOR < YYLIMIT) {
+ switch (*YYCURSOR++) {
+ case '"':
+ yyleng = YYCURSOR - SCNG(yy_text);
+ zend_scan_escape_string(zendlval, yytext+bprefix+1, yyleng-bprefix-2, '"' TSRMLS_CC);
+ return T_CONSTANT_ENCAPSED_STRING;
+ case '$':
+ if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
+ break;
+ }
+ continue;
+ case '{':
+ if (*YYCURSOR == '$') {
+ break;
+ }
+ continue;
+ case '\\':
+ if (YYCURSOR < YYLIMIT) {
+ YYCURSOR++;
+ }
+ /* fall through */
+ default:
+ continue;
+ }
+
+ YYCURSOR--;
+ break;
+ }
+
+ /* Remember how much was scanned to save rescanning */
+ SET_DOUBLE_QUOTES_SCANNED_LENGTH(YYCURSOR - SCNG(yy_text) - yyleng);
+
+ YYCURSOR = SCNG(yy_text) + yyleng;
+
+ BEGIN(ST_DOUBLE_QUOTES);
+ return '"';
+}
+
+
+<ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}({LABEL}|([']{LABEL}['])|(["]{LABEL}["])){NEWLINE} {
+ char *s;
+ int bprefix = (yytext[0] != '<') ? 1 : 0;
+
+ /* save old heredoc label */
+ Z_STRVAL_P(zendlval) = CG(heredoc);
+ Z_STRLEN_P(zendlval) = CG(heredoc_len);
+
+ CG(zend_lineno)++;
+ CG(heredoc_len) = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0);
+ s = yytext+bprefix+3;
+ while ((*s == ' ') || (*s == '\t')) {
+ s++;
+ CG(heredoc_len)--;
+ }
+
+ if (*s == '\'') {
+ s++;
+ CG(heredoc_len) -= 2;
+
+ BEGIN(ST_NOWDOC);
+ } else {
+ if (*s == '"') {
+ s++;
+ CG(heredoc_len) -= 2;
+ }
+
+ BEGIN(ST_HEREDOC);
+ }
+
+ CG(heredoc) = estrndup(s, CG(heredoc_len));
+
+ /* Check for ending label on the next line */
+ if (CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, CG(heredoc_len))) {
+ YYCTYPE *end = YYCURSOR + CG(heredoc_len);
+
+ if (*end == ';') {
+ end++;
+ }
+
+ if (*end == '\n' || *end == '\r') {
+ BEGIN(ST_END_HEREDOC);
+ }
+ }
+
+ return T_START_HEREDOC;
+}
+
+
+<ST_IN_SCRIPTING>[`] {
+ BEGIN(ST_BACKQUOTE);
+ return '`';
+}
+
+
+<ST_END_HEREDOC>{ANY_CHAR} {
+ YYCURSOR += CG(heredoc_len) - 1;
+ yyleng = CG(heredoc_len);
+
+ Z_STRVAL_P(zendlval) = CG(heredoc);
+ Z_STRLEN_P(zendlval) = CG(heredoc_len);
+ CG(heredoc) = NULL;
+ CG(heredoc_len) = 0;
+ BEGIN(ST_IN_SCRIPTING);
+ return T_END_HEREDOC;
+}
+
+
+<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"{$" {
+ zendlval->value.lval = (long) '{';
+ yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
+ yyless(1);
+ return T_CURLY_OPEN;
+}
+
+
+<ST_DOUBLE_QUOTES>["] {
+ BEGIN(ST_IN_SCRIPTING);
+ return '"';
+}
+
+<ST_BACKQUOTE>[`] {
+ BEGIN(ST_IN_SCRIPTING);
+ return '`';
+}
+
+
+<ST_DOUBLE_QUOTES>{ANY_CHAR} {
+ if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
+ YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
+ SET_DOUBLE_QUOTES_SCANNED_LENGTH(0);
+
+ goto double_quotes_scan_done;
+ }
+
+ if (YYCURSOR > YYLIMIT) {
+ return 0;
+ }
+ if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
+ YYCURSOR++;
+ }
+
+ while (YYCURSOR < YYLIMIT) {
+ switch (*YYCURSOR++) {
+ case '"':
+ break;
+ case '$':
+ if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
+ break;
+ }
+ continue;
+ case '{':
+ if (*YYCURSOR == '$') {
+ break;
+ }
+ continue;
+ case '\\':
+ if (YYCURSOR < YYLIMIT) {
+ YYCURSOR++;
+ }
+ /* fall through */
+ default:
+ continue;
+ }
+
+ YYCURSOR--;
+ break;
+ }
+
+double_quotes_scan_done:
+ yyleng = YYCURSOR - SCNG(yy_text);
+
+ zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC);
+ return T_ENCAPSED_AND_WHITESPACE;
+}
+
+
+<ST_BACKQUOTE>{ANY_CHAR} {
+ if (YYCURSOR > YYLIMIT) {
+ return 0;
+ }
+ if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
+ YYCURSOR++;
+ }
+
+ while (YYCURSOR < YYLIMIT) {
+ switch (*YYCURSOR++) {
+ case '`':
+ break;
+ case '$':
+ if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
+ break;
+ }
+ continue;
+ case '{':
+ if (*YYCURSOR == '$') {
+ break;
+ }
+ continue;
+ case '\\':
+ if (YYCURSOR < YYLIMIT) {
+ YYCURSOR++;
+ }
+ /* fall through */
+ default:
+ continue;
+ }
+
+ YYCURSOR--;
+ break;
+ }
+
+ yyleng = YYCURSOR - SCNG(yy_text);
+
+ zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC);
+ return T_ENCAPSED_AND_WHITESPACE;
+}
+
+
+<ST_HEREDOC>{ANY_CHAR} {
+ int newline = 0;
+
+ if (YYCURSOR > YYLIMIT) {
+ return 0;
+ }
+
+ YYCURSOR--;
+
+ while (YYCURSOR < YYLIMIT) {
+ switch (*YYCURSOR++) {
+ case '\r':
+ if (*YYCURSOR == '\n') {
+ YYCURSOR++;
+ }
+ /* fall through */
+ case '\n':
+ /* Check for ending label on the next line */
+ if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) {
+ YYCTYPE *end = YYCURSOR + CG(heredoc_len);
+
+ if (*end == ';') {
+ end++;
+ }
+
+ if (*end == '\n' || *end == '\r') {
+ /* newline before label will be subtracted from returned text, but
+ * yyleng/yytext will include it, for zend_highlight/strip, tokenizer, etc. */
+ if (YYCURSOR[-2] == '\r' && YYCURSOR[-1] == '\n') {
+ newline = 2; /* Windows newline */
+ } else {
+ newline = 1;
+ }
+
+ CG(increment_lineno) = 1; /* For newline before label */
+ BEGIN(ST_END_HEREDOC);
+
+ goto heredoc_scan_done;
+ }
+ }
+ continue;
+ case '$':
+ if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
+ break;
+ }
+ continue;
+ case '{':
+ if (*YYCURSOR == '$') {
+ break;
+ }
+ continue;
+ case '\\':
+ if (YYCURSOR < YYLIMIT && *YYCURSOR != '\n' && *YYCURSOR != '\r') {
+ YYCURSOR++;
+ }
+ /* fall through */
+ default:
+ continue;
+ }
+
+ YYCURSOR--;
+ break;
+ }
+
+heredoc_scan_done:
+ yyleng = YYCURSOR - SCNG(yy_text);
+
+ zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0 TSRMLS_CC);
+ return T_ENCAPSED_AND_WHITESPACE;
+}
+
+
+<ST_NOWDOC>{ANY_CHAR} {
+ int newline = 0;
+
+ if (YYCURSOR > YYLIMIT) {
+ return 0;
+ }
+
+ YYCURSOR--;
+
+ while (YYCURSOR < YYLIMIT) {
+ switch (*YYCURSOR++) {
+ case '\r':
+ if (*YYCURSOR == '\n') {
+ YYCURSOR++;
+ }
+ /* fall through */
+ case '\n':
+ /* Check for ending label on the next line */
+ if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) {
+ YYCTYPE *end = YYCURSOR + CG(heredoc_len);
+
+ if (*end == ';') {
+ end++;
+ }
+
+ if (*end == '\n' || *end == '\r') {
+ /* newline before label will be subtracted from returned text, but
+ * yyleng/yytext will include it, for zend_highlight/strip, tokenizer, etc. */
+ if (YYCURSOR[-2] == '\r' && YYCURSOR[-1] == '\n') {
+ newline = 2; /* Windows newline */
+ } else {
+ newline = 1;
+ }
+
+ CG(increment_lineno) = 1; /* For newline before label */
+ BEGIN(ST_END_HEREDOC);
+
+ goto nowdoc_scan_done;
+ }
+ }
+ /* fall through */
+ default:
+ continue;
+ }
+ }
+
+nowdoc_scan_done:
+ yyleng = YYCURSOR - SCNG(yy_text);
+
+ zend_copy_value(zendlval, yytext, yyleng - newline);
+ zendlval->type = IS_STRING;
+ HANDLE_NEWLINES(yytext, yyleng - newline);
+ return T_ENCAPSED_AND_WHITESPACE;
+}
+
+
+<ST_IN_SCRIPTING,ST_VAR_OFFSET>{ANY_CHAR} {
+ if (YYCURSOR > YYLIMIT) {
+ return 0;
+ }
+
+ zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
+ goto restart;
+}
+
+*/
+}
diff --git a/recherches/parsers/lime.tar.gz b/recherches/parsers/lime.tar.gz
new file mode 100644
index 0000000..f3f8f89
--- /dev/null
+++ b/recherches/parsers/lime.tar.gz
Binary files differ
diff --git a/recherches/parsers/nikic-PHP-Parser-v0.9.2.txt b/recherches/parsers/nikic-PHP-Parser-v0.9.2.txt
new file mode 100644
index 0000000..016af6f
--- /dev/null
+++ b/recherches/parsers/nikic-PHP-Parser-v0.9.2.txt
@@ -0,0 +1 @@
+https://github.com/nikic/PHP-Parser
diff --git a/tests/test01-parsing/src/composer.json b/tests/test01-parsing/src/composer.json
new file mode 100644
index 0000000..a366739
--- /dev/null
+++ b/tests/test01-parsing/src/composer.json
@@ -0,0 +1,6 @@
+{
+ "require": {
+ "nikic/php-parser": "0.9.2"
+ }
+}
+
diff --git a/tests/test01-parsing/src/get_deps.sh b/tests/test01-parsing/src/get_deps.sh
new file mode 100755
index 0000000..67c84c3
--- /dev/null
+++ b/tests/test01-parsing/src/get_deps.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+php ../../../composer.phar install
diff --git a/tests/test01-parsing/src/php-weave/main.php b/tests/test01-parsing/src/php-weave/main.php
new file mode 100644
index 0000000..2a4df55
--- /dev/null
+++ b/tests/test01-parsing/src/php-weave/main.php
@@ -0,0 +1,64 @@
+<?php
+require '../vendor/nikic/php-parser/lib/bootstrap.php';
+require './visitors.inc.php';
+
+ini_set('xdebug.max_nesting_level', 2000);
+
+function dbg($indent, $text) {
+ for($i=0;$i<$indent;$i++) echo ".";
+ echo "$text\n";
+}
+
+function recursive_parse($src_filepath, $stmts1_filepath, $stmts2_filepath, $level=0) {
+ global $parser,$nodeDumper;
+
+ try {
+ dbg($level,"Parsing '$src_filepath'");
+ $stmts = $parser->parse(file_get_contents($src_filepath));
+
+ if (strlen($stmts1_filepath) > 0 ) {
+ dbg($level,"Dumping1 '$src_filepath' AST to '$stmts1_filepath'");
+ file_put_contents($stmts1_filepath, $nodeDumper->dump($stmts));
+ }
+
+ dbg($level,"Transforming '$src_filepath'");
+ $traverser = new PHPParser_NodeTraverser;
+/*
+ $traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
+ $traverser->addVisitor(new NodeVisitor_NamespaceConverter);
+*/
+ // FIXME : getcwd is quick and dirty here
+ $traverser->addVisitor(new NodeVisitor_PreprocessInclude($level, getcwd(), $src_filepath));
+ $stmts = $traverser->traverse($stmts);
+ $traverser=null; //Destroy
+
+ if (strlen($stmts2_filepath) > 0) {
+ dbg($level,"Dumping2 '$src_filepath' AST to '$stmts2_filepath'");
+ file_put_contents($stmts2_filepath, $nodeDumper->dump($stmts));
+ }
+
+ } catch (PHPParser_Error $e) {
+ echo 'Parse Error: ', $e->getMessage();
+ }
+ return $stmts;
+}
+
+
+// Main
+$src_filepath = "./main.php";
+#$src_filepath = "./to_parse.php";
+$stmts1_filepath = "out/stmts1.ast";
+$stmts2_filepath = "out/stmts2.ast";
+$dest_filepath = "out/result.php";
+
+$parser = new PHPParser_Parser(new PHPParser_Lexer);
+$nodeDumper = new PHPParser_NodeDumper;
+
+$level=0;
+$stmts=recursive_parse($src_filepath, $stmts1_filepath, $stmts2_filepath);
+
+dbg(0,"Outputing '$dest_filepath'");
+$prettyPrinter = new PHPParser_PrettyPrinter_Zend;
+file_put_contents($dest_filepath, "<?php\n" . $prettyPrinter->prettyPrint($stmts) . "\n?>");
+
+?>
diff --git a/tests/test01-parsing/src/php-weave/to_parse.php b/tests/test01-parsing/src/php-weave/to_parse.php
new file mode 100644
index 0000000..7b953d5
--- /dev/null
+++ b/tests/test01-parsing/src/php-weave/to_parse.php
@@ -0,0 +1,5 @@
+<?php
+if (1){
+include('./inc.php');
+}
+?>
diff --git a/tests/test01-parsing/src/php-weave/visitors.inc.php b/tests/test01-parsing/src/php-weave/visitors.inc.php
new file mode 100644
index 0000000..3f997ad
--- /dev/null
+++ b/tests/test01-parsing/src/php-weave/visitors.inc.php
@@ -0,0 +1,91 @@
+<?php
+/*
+class NodeVisitor_NamespaceConverter extends PHPParser_NodeVisitorAbstract
+{
+ public function leaveNode(PHPParser_Node $node) {
+ if ($node instanceof PHPParser_Node_Name) {
+ return new PHPParser_Node_Name($node->toString('_'));
+ } elseif ($node instanceof PHPParser_Node_Stmt_Class
+ || $node instanceof PHPParser_Node_Stmt_Interface
+ || $node instanceof PHPParser_Node_Stmt_Function) {
+ $node->name = $node->namespacedName->toString('_');
+ } elseif ($node instanceof PHPParser_Node_Stmt_Const) {
+ foreach ($node->consts as $const) {
+ $const->name = $const->namespacedName->toString('_');
+ }
+ } elseif ($node instanceof PHPParser_Node_Stmt_Namespace) {
+ // returning an array merges is into the parent array
+ return $node->stmts;
+ } elseif ($node instanceof PHPParser_Node_Stmt_Use) {
+ // returning false removed the node altogether
+ return false;
+ }
+ }
+}
+*/
+
+class NodeVisitor_PreprocessInclude extends PHPParser_NodeVisitorAbstract {
+ protected $level;
+ protected $cwd;
+ protected $filepath;
+ protected $prettyPrinter;
+
+ public function __construct($level, $cwd, $filepath) {
+ $this->level=$level;
+ $this->cwd=$cwd;
+ $this->filepath=$filepath;
+ $this->prettyPrinter = new PHPParser_PrettyPrinter_Zend;
+ }
+
+ protected function resolveIncludePath($node) {
+ //FIXME : Quick and dirty
+ // no classpath checks...
+ // no check if compound value like "dirname(__FILE__) . '/PHPParser/Autoloader.php'"
+ return $node->expr->value;
+ }
+
+ public function enterNode(PHPParser_Node $node) {
+ if ($node instanceof PHPParser_Node_Expr_Include) {
+ // Already processed, go out (occurs if an unresolved include has left as is in the previous recursion level)
+ if (is_array($node->attributes) && array_key_exists('NodeVisitor_PreprocessInclude', $node->attributes)) return $node;
+
+ switch($node->type) {
+ case PHPParser_Node_Expr_Include::TYPE_INCLUDE:
+ case PHPParser_Node_Expr_Include::TYPE_REQUIRE:
+ $once=0;
+ break;
+ case PHPParser_Node_Expr_Include::TYPE_INCLUDE_ONCE:
+ case PHPParser_Node_Expr_Include::TYPE_REQUIRE_ONCE:
+ $once=1;
+ echo "TODO : include_once or require_once\n";
+ break;
+ default:
+ echo "FIXME : BUG NodeVisitor_PreprocessInclude::enterNode !!\n";
+ return $node;
+ }
+
+ $path=$this->resolveIncludePath($node);
+
+ //FIXME : No infinite recursion check like test.php contains include('./test.php');
+ // Preprocess include if readable
+ $comment_suffix=" */";
+ if ( ($this->level < 3) && is_readable($path)) {
+ $comment_prefix="/* ";
+ //FIXME : use a closure or sort of here (dependancy injection)
+ //$stmts=recursive_parse($path, "out/rec.out1", "out/rec.out2", $this->level+1);
+ $stmts=recursive_parse($path, "", "", $this->level+1);
+ } else {
+ $comment_prefix="/* UNRESOLVED : ";
+ $node->attributes['NodeVisitor_PreprocessInclude']='unresolved';
+ $stmts=array($node); // Caution : can cause infinite loop (will be tried at the next step)
+ }
+
+ $comment= new PHPParser_Comment($comment_prefix . $this->prettyPrinter->prettyPrint(array($node)) . $comment_suffix);
+
+ // FIXME : Get out this if() that is a trick for not returning here an array instead of a node
+ return new PHPParser_Node_Stmt_If(new PHPParser_Node_Scalar_LNumber(1),array('stmts'=>$stmts),array('comments'=>array($comment)));
+ }
+
+ }
+}
+