]> granicus.if.org Git - php/commitdiff
Switch to bison location tracking
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 15 Mar 2019 11:36:49 +0000 (12:36 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 21 Mar 2019 15:27:48 +0000 (16:27 +0100)
Locations for AST nodes are now tracked with the help of bison
location tracking. This is more accurate than what we currently do
and easier to extend with more information.

A zend_ast_loc structure is introduced, which is used for the location
stack. Currently it only holds the start lineno, but can be extended
to also hold end lineno and offset/column information in the future.

All AST constructors now accept a zend_ast_loc* as first argument, and
will use it to determine their lineno. Previously this used either the
CG(zend_lineno), or the smallest AST lineno of child nodes.

On the parser side, the location structure for a whole rule can be
obtained using the &@$ character salad.

Zend/zend_ast.c
Zend/zend_ast.h
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_globals.h
Zend/zend_highlight.c
Zend/zend_language_parser.y
Zend/zend_language_scanner.l
ext/tokenizer/tokenizer.c

index 2cacd532878bc279593f4dc01a57b134b35318eb..65f9030f5d243ccd3825468c23aef718ac11d361 100644 (file)
@@ -45,75 +45,75 @@ static inline size_t zend_ast_list_size(uint32_t children) {
        return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(zend_ast_loc *loc, znode *node) {
        zend_ast_znode *ast;
 
        ast = zend_ast_alloc(sizeof(zend_ast_znode));
        ast->kind = ZEND_AST_ZNODE;
        ast->attr = 0;
-       ast->lineno = CG(zend_lineno);
+       ast->lineno = loc->start_line;
        ast->node = *node;
        return (zend_ast *) ast;
 }
 
-static zend_always_inline zend_ast * zend_ast_create_zval_int(zval *zv, uint32_t attr, uint32_t lineno) {
+static zend_always_inline zend_ast * zend_ast_create_zval_int(
+               zend_ast_loc *loc, zval *zv, uint32_t attr) {
        zend_ast_zval *ast;
 
        ast = zend_ast_alloc(sizeof(zend_ast_zval));
        ast->kind = ZEND_AST_ZVAL;
        ast->attr = attr;
        ZVAL_COPY_VALUE(&ast->val, zv);
-       Z_LINENO(ast->val) = lineno;
+       Z_LINENO(ast->val) = loc->start_line;
        return (zend_ast *) ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(zval *zv, uint32_t lineno) {
-       return zend_ast_create_zval_int(zv, 0, lineno);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(
+               zend_ast_loc *loc, zval *zv, zend_ast_attr attr) {
+       return zend_ast_create_zval_int(loc, zv, attr);
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
-       return zend_ast_create_zval_int(zv, attr, CG(zend_lineno));
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zend_ast_loc *loc, zval *zv) {
+       return zend_ast_create_zval_int(loc, zv, 0);
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zval *zv) {
-       return zend_ast_create_zval_int(zv, 0, CG(zend_lineno));
-}
-
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_ast_loc *loc, zend_string *str) {
        zval zv;
        ZVAL_STR(&zv, str);
-       return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
+       return zend_ast_create_zval_int(loc, &zv, 0);
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_ast_loc *loc, zend_long lval) {
        zval zv;
        ZVAL_LONG(&zv, lval);
-       return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
+       return zend_ast_create_zval_int(loc, &zv, 0);
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(
+               zend_ast_loc *loc, zend_string *name, zend_ast_attr attr) {
        zend_ast_zval *ast;
 
        ast = zend_ast_alloc(sizeof(zend_ast_zval));
        ast->kind = ZEND_AST_CONSTANT;
        ast->attr = attr;
        ZVAL_STR(&ast->val, name);
-       Z_LINENO(ast->val) = CG(zend_lineno);
+       Z_LINENO(ast->val) = loc->start_line;
        return (zend_ast *) ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(
+               zend_ast_loc *loc, zend_ast *class_name, zend_ast *name) {
        zend_string *name_str = zend_ast_get_str(name);
        if (zend_string_equals_literal_ci(name_str, "class")) {
                zend_string_release(name_str);
-               return zend_ast_create(ZEND_AST_CLASS_NAME, class_name);
+               return zend_ast_create(loc, ZEND_AST_CLASS_NAME, class_name);
        } else {
-               return zend_ast_create(ZEND_AST_CLASS_CONST, class_name, name);
+               return zend_ast_create(loc, ZEND_AST_CLASS_CONST, class_name, name);
        }
 }
 
 ZEND_API zend_ast *zend_ast_create_decl(
-       zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
+       zend_ast_loc *loc, zend_ast_kind kind, uint32_t flags, zend_string *doc_comment,
        zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3
 ) {
        zend_ast_decl *ast;
@@ -121,7 +121,7 @@ ZEND_API zend_ast *zend_ast_create_decl(
        ast = zend_ast_alloc(sizeof(zend_ast_decl));
        ast->kind = kind;
        ast->attr = 0;
-       ast->start_lineno = start_lineno;
+       ast->start_lineno = loc->start_line;
        ast->end_lineno = CG(zend_lineno);
        ast->flags = flags;
        ast->lex_pos = LANG_SCNG(yy_text);
@@ -136,41 +136,35 @@ ZEND_API zend_ast *zend_ast_create_decl(
 }
 
 #if ZEND_AST_SPEC
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_loc *loc, zend_ast_kind kind) {
        zend_ast *ast;
 
        ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 0);
        ast = zend_ast_alloc(zend_ast_size(0));
        ast->kind = kind;
        ast->attr = 0;
-       ast->lineno = CG(zend_lineno);
+       ast->lineno = loc->start_line;
 
        return ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast *child) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(
+               zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child) {
        zend_ast *ast;
-       uint32_t lineno;
 
        ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 1);
        ast = zend_ast_alloc(zend_ast_size(1));
        ast->kind = kind;
        ast->attr = 0;
        ast->child[0] = child;
-       if (child) {
-               lineno = zend_ast_get_lineno(child);
-       } else {
-               lineno = CG(zend_lineno);
-       }
-       ast->lineno = lineno;
-       ast->lineno = lineno;
+       ast->lineno = loc->start_line;
 
        return ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(
+               zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
        zend_ast *ast;
-       uint32_t lineno;
 
        ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 2);
        ast = zend_ast_alloc(zend_ast_size(2));
@@ -178,21 +172,14 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast
        ast->attr = 0;
        ast->child[0] = child1;
        ast->child[1] = child2;
-       if (child1) {
-               lineno = zend_ast_get_lineno(child1);
-       } else if (child2) {
-               lineno = zend_ast_get_lineno(child2);
-       } else {
-               lineno = CG(zend_lineno);
-       }
-       ast->lineno = lineno;
+       ast->lineno = loc->start_line;
 
        return ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(
+               zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
        zend_ast *ast;
-       uint32_t lineno;
 
        ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 3);
        ast = zend_ast_alloc(zend_ast_size(3));
@@ -201,23 +188,14 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast
        ast->child[0] = child1;
        ast->child[1] = child2;
        ast->child[2] = child3;
-       if (child1) {
-               lineno = zend_ast_get_lineno(child1);
-       } else if (child2) {
-               lineno = zend_ast_get_lineno(child2);
-       } else if (child3) {
-               lineno = zend_ast_get_lineno(child3);
-       } else {
-               lineno = CG(zend_lineno);
-       }
-       ast->lineno = lineno;
+       ast->lineno = loc->start_line;
 
        return ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(
+               zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4) {
        zend_ast *ast;
-       uint32_t lineno;
 
        ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 4);
        ast = zend_ast_alloc(zend_ast_size(4));
@@ -227,23 +205,12 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_kind kind, zend_ast
        ast->child[1] = child2;
        ast->child[2] = child3;
        ast->child[3] = child4;
-       if (child1) {
-               lineno = zend_ast_get_lineno(child1);
-       } else if (child2) {
-               lineno = zend_ast_get_lineno(child2);
-       } else if (child3) {
-               lineno = zend_ast_get_lineno(child3);
-       } else if (child4) {
-               lineno = zend_ast_get_lineno(child4);
-       } else {
-               lineno = CG(zend_lineno);
-       }
-       ast->lineno = lineno;
+       ast->lineno = loc->start_line;
 
        return ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_loc *loc, zend_ast_kind kind) {
        zend_ast *ast;
        zend_ast_list *list;
 
@@ -251,16 +218,16 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) {
        list = (zend_ast_list *) ast;
        list->kind = kind;
        list->attr = 0;
-       list->lineno = CG(zend_lineno);
+       list->lineno = loc->start_line;
        list->children = 0;
 
        return ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zend_ast *child) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(
+               zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child) {
        zend_ast *ast;
        zend_ast_list *list;
-       uint32_t lineno;
 
        ast = zend_ast_alloc(zend_ast_list_size(4));
        list = (zend_ast_list *) ast;
@@ -268,23 +235,15 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zen
        list->attr = 0;
        list->children = 1;
        list->child[0] = child;
-       if (child) {
-               lineno = zend_ast_get_lineno(child);
-               if (lineno > CG(zend_lineno)) {
-                       lineno = CG(zend_lineno);
-               }
-       } else {
-               lineno = CG(zend_lineno);
-       }
-       list->lineno = lineno;
+       list->lineno = loc->start_line;
 
        return ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(
+               zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
        zend_ast *ast;
        zend_ast_list *list;
-       uint32_t lineno;
 
        ast = zend_ast_alloc(zend_ast_list_size(4));
        list = (zend_ast_list *) ast;
@@ -293,74 +252,49 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zen
        list->children = 2;
        list->child[0] = child1;
        list->child[1] = child2;
-       if (child1) {
-               lineno = zend_ast_get_lineno(child1);
-               if (lineno > CG(zend_lineno)) {
-                       lineno = CG(zend_lineno);
-               }
-       } else if (child2) {
-               lineno = zend_ast_get_lineno(child2);
-               if (lineno > CG(zend_lineno)) {
-                       lineno = CG(zend_lineno);
-               }
-       } else {
-               list->children = 0;
-               lineno = CG(zend_lineno);
-       }
-       list->lineno = lineno;
+       list->lineno = loc->start_line;
 
        return ast;
 }
 #else
-static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
+static zend_ast *zend_ast_create_from_va_list(
+               zend_ast_loc *loc, zend_ast_kind kind, zend_ast_attr attr, va_list va) {
        uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
        zend_ast *ast;
 
        ast = zend_ast_alloc(zend_ast_size(children));
        ast->kind = kind;
        ast->attr = attr;
-       ast->lineno = (uint32_t) -1;
-
-       for (i = 0; i < children; ++i) {
-               ast->child[i] = va_arg(va, zend_ast *);
-               if (ast->child[i] != NULL) {
-                       uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
-                       if (lineno < ast->lineno) {
-                               ast->lineno = lineno;
-                       }
-               }
-       }
-
-       if (ast->lineno == UINT_MAX) {
-               ast->lineno = CG(zend_lineno);
-       }
+       ast->lineno = loc->start_line;
 
        return ast;
 }
 
-ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
+ZEND_API zend_ast *zend_ast_create_ex(
+               zend_ast_loc *loc, zend_ast_kind kind, zend_ast_attr attr, ...) {
        va_list va;
        zend_ast *ast;
 
        va_start(va, attr);
-       ast = zend_ast_create_from_va_list(kind, attr, va);
+       ast = zend_ast_create_from_va_list(loc, kind, attr, va);
        va_end(va);
 
        return ast;
 }
 
-ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
+ZEND_API zend_ast *zend_ast_create(zend_ast_loc *loc, zend_ast_kind kind, ...) {
        va_list va;
        zend_ast *ast;
 
        va_start(va, kind);
-       ast = zend_ast_create_from_va_list(kind, 0, va);
+       ast = zend_ast_create_from_va_list(loc, kind, 0, va);
        va_end(va);
 
        return ast;
 }
 
-ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
+ZEND_API zend_ast *zend_ast_create_list(
+               zend_ast_loc *loc, uint32_t init_children, zend_ast_kind kind, ...) {
        zend_ast *ast;
        zend_ast_list *list;
 
@@ -368,7 +302,7 @@ ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind ki
        list = (zend_ast_list *) ast;
        list->kind = kind;
        list->attr = 0;
-       list->lineno = CG(zend_lineno);
+       list->lineno = loc->start_line;
        list->children = 0;
 
        {
@@ -378,12 +312,6 @@ ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind ki
                for (i = 0; i < init_children; ++i) {
                        zend_ast *child = va_arg(va, zend_ast *);
                        ast = zend_ast_list_add(ast, child);
-                       if (child != NULL) {
-                               uint32_t lineno = zend_ast_get_lineno(child);
-                               if (lineno < ast->lineno) {
-                                       ast->lineno = lineno;
-                               }
-                       }
                }
                va_end(va);
        }
index 499b8b4191747b7439f3eb2dc94a75e633b18267..a49f93b157907efd1f2824f78dd9b5b59a42459d 100644 (file)
@@ -196,78 +196,84 @@ typedef struct _zend_ast_decl {
 typedef void (*zend_ast_process_t)(zend_ast *ast);
 extern ZEND_API zend_ast_process_t zend_ast_process;
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(zval *zv, uint32_t lineno);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zval *zv);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval);
+typedef struct _zend_ast_loc {
+       uint32_t start_line;
+} zend_ast_loc;
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zend_ast_loc *loc, zval *zv, zend_ast_attr attr);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zend_ast_loc *loc, zval *zv);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_ast_loc *loc, zend_string *str);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_ast_loc *loc, zend_long lval);
+
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_ast_loc *loc, zend_string *name, zend_ast_attr attr);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast_loc *loc, zend_ast *class_name, zend_ast *name);
+
+struct _znode;
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(zend_ast_loc *loc, struct _znode *node);
 
 #if ZEND_AST_SPEC
 # define ZEND_AST_SPEC_CALL(name, ...) \
        ZEND_EXPAND_VA(ZEND_AST_SPEC_CALL_(name, __VA_ARGS__, _4, _3, _2, _1, _0)(__VA_ARGS__))
-# define ZEND_AST_SPEC_CALL_(name, _, _4, _3, _2, _1, suffix, ...) \
+# define ZEND_AST_SPEC_CALL_(name, _loc, _kind, _4, _3, _2, _1, suffix, ...) \
        name ## suffix
 # define ZEND_AST_SPEC_CALL_EX(name, ...) \
        ZEND_EXPAND_VA(ZEND_AST_SPEC_CALL_EX_(name, __VA_ARGS__, _4, _3, _2, _1, _0)(__VA_ARGS__))
-# define ZEND_AST_SPEC_CALL_EX_(name, _, _5, _4, _3, _2, _1, suffix, ...) \
+# define ZEND_AST_SPEC_CALL_EX_(name, _loc, _kind, _attr, _4, _3, _2, _1, suffix, ...) \
        name ## suffix
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast *child);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_loc *loc, zend_ast_kind kind);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child1, zend_ast *child2);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4);
 
-static zend_always_inline zend_ast * zend_ast_create_ex_0(zend_ast_kind kind, zend_ast_attr attr) {
-       zend_ast *ast = zend_ast_create_0(kind);
+static zend_always_inline zend_ast * zend_ast_create_ex_0(zend_ast_loc *loc, zend_ast_kind kind, zend_ast_attr attr) {
+       zend_ast *ast = zend_ast_create_0(loc, kind);
        ast->attr = attr;
        return ast;
 }
-static zend_always_inline zend_ast * zend_ast_create_ex_1(zend_ast_kind kind, zend_ast_attr attr, zend_ast *child) {
-       zend_ast *ast = zend_ast_create_1(kind, child);
+static zend_always_inline zend_ast * zend_ast_create_ex_1(zend_ast_loc *loc, zend_ast_kind kind, zend_ast_attr attr, zend_ast *child) {
+       zend_ast *ast = zend_ast_create_1(loc, kind, child);
        ast->attr = attr;
        return ast;
 }
-static zend_always_inline zend_ast * zend_ast_create_ex_2(zend_ast_kind kind, zend_ast_attr attr, zend_ast *child1, zend_ast *child2) {
-       zend_ast *ast = zend_ast_create_2(kind, child1, child2);
+static zend_always_inline zend_ast * zend_ast_create_ex_2(zend_ast_loc *loc, zend_ast_kind kind, zend_ast_attr attr, zend_ast *child1, zend_ast *child2) {
+       zend_ast *ast = zend_ast_create_2(loc, kind, child1, child2);
        ast->attr = attr;
        return ast;
 }
-static zend_always_inline zend_ast * zend_ast_create_ex_3(zend_ast_kind kind, zend_ast_attr attr, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
-       zend_ast *ast = zend_ast_create_3(kind, child1, child2, child3);
+static zend_always_inline zend_ast * zend_ast_create_ex_3(zend_ast_loc *loc, zend_ast_kind kind, zend_ast_attr attr, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
+       zend_ast *ast = zend_ast_create_3(loc, kind, child1, child2, child3);
        ast->attr = attr;
        return ast;
 }
-static zend_always_inline zend_ast * zend_ast_create_ex_4(zend_ast_kind kind, zend_ast_attr attr, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4) {
-       zend_ast *ast = zend_ast_create_4(kind, child1, child2, child3, child4);
+static zend_always_inline zend_ast * zend_ast_create_ex_4(zend_ast_loc *loc, zend_ast_kind kind, zend_ast_attr attr, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4) {
+       zend_ast *ast = zend_ast_create_4(loc, kind, child1, child2, child3, child4);
        ast->attr = attr;
        return ast;
 }
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zend_ast *child);
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_loc *loc, zend_ast_kind kind);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child);
+ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_loc *loc, zend_ast_kind kind, zend_ast *child1, zend_ast *child2);
 
 # define zend_ast_create(...) \
        ZEND_AST_SPEC_CALL(zend_ast_create, __VA_ARGS__)
 # define zend_ast_create_ex(...) \
        ZEND_AST_SPEC_CALL_EX(zend_ast_create_ex, __VA_ARGS__)
-# define zend_ast_create_list(init_children, ...) \
-       ZEND_AST_SPEC_CALL(zend_ast_create_list, __VA_ARGS__)
+# define zend_ast_create_list(loc, init_children, ...) \
+       ZEND_AST_SPEC_CALL(zend_ast_create_list, loc, __VA_ARGS__)
 
 #else
-ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...);
-ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...);
-ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...);
+ZEND_API zend_ast *zend_ast_create(zend_ast_loc *loc, zend_ast_kind kind, ...);
+ZEND_API zend_ast *zend_ast_create_ex(zend_ast_loc *loc, zend_ast_kind kind, zend_ast_attr attr, ...);
+ZEND_API zend_ast *zend_ast_create_list(zend_ast_loc *loc, uint32_t init_children, zend_ast_kind kind, ...);
 #endif
 
 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *list, zend_ast *op);
 
 ZEND_API zend_ast *zend_ast_create_decl(
-       zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
+       zend_ast_loc *loc, zend_ast_kind kind, uint32_t flags, zend_string *doc_comment,
        zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3
 );
 
@@ -318,14 +324,20 @@ static zend_always_inline uint32_t zend_ast_get_lineno(zend_ast *ast) {
        }
 }
 
-static zend_always_inline zend_ast *zend_ast_create_binary_op(uint32_t opcode, zend_ast *op0, zend_ast *op1) {
-       return zend_ast_create_ex(ZEND_AST_BINARY_OP, opcode, op0, op1);
+static inline zend_ast_loc zend_ast_get_loc(zend_ast *ast) {
+       zend_ast_loc loc;
+       loc.start_line = zend_ast_get_lineno(ast);
+       return loc;
+}
+
+static zend_always_inline zend_ast *zend_ast_create_binary_op(zend_ast_loc *loc, uint32_t opcode, zend_ast *op0, zend_ast *op1) {
+       return zend_ast_create_ex(loc, ZEND_AST_BINARY_OP, opcode, op0, op1);
 }
-static zend_always_inline zend_ast *zend_ast_create_assign_op(uint32_t opcode, zend_ast *op0, zend_ast *op1) {
-       return zend_ast_create_ex(ZEND_AST_ASSIGN_OP, opcode, op0, op1);
+static zend_always_inline zend_ast *zend_ast_create_assign_op(zend_ast_loc *loc, uint32_t opcode, zend_ast *op0, zend_ast *op1) {
+       return zend_ast_create_ex(loc, ZEND_AST_ASSIGN_OP, opcode, op0, op1);
 }
-static zend_always_inline zend_ast *zend_ast_create_cast(uint32_t type, zend_ast *op0) {
-       return zend_ast_create_ex(ZEND_AST_CAST, type, op0);
+static zend_always_inline zend_ast *zend_ast_create_cast(zend_ast_loc *loc, uint32_t type, zend_ast *op0) {
+       return zend_ast_create_ex(loc, ZEND_AST_CAST, type, op0);
 }
 static zend_always_inline zend_ast *zend_ast_list_rtrim(zend_ast *ast) {
        zend_ast_list *list = zend_ast_get_list(ast);
index 2fa847d180d6c92cdd5a715ed4093d6a2daa08ef..73ea21325c888079bc3c0f728025ce2c5fc59766 100644 (file)
@@ -1526,16 +1526,10 @@ ZEND_API void zend_activate_auto_globals(void) /* {{{ */
 }
 /* }}} */
 
-int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem) /* {{{ */
+int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem, zend_ast_loc *loc) /* {{{ */
 {
        zval zv;
-
-       if (CG(increment_lineno)) {
-               CG(zend_lineno)++;
-               CG(increment_lineno) = 0;
-       }
-
-       return lex_scan(&zv, elem);
+       return lex_scan(&zv, elem, loc);
 }
 /* }}} */
 
@@ -2335,8 +2329,9 @@ void zend_compile_assign(znode *result, zend_ast *ast);
 static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
 {
        znode dummy_node;
-       zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast,
-               zend_ast_create_znode(value_node));
+       zend_ast_loc loc = zend_ast_get_loc(var_ast);
+       zend_ast *assign_ast = zend_ast_create(&loc, ZEND_AST_ASSIGN, var_ast,
+               zend_ast_create_znode(&loc, value_node));
        zend_compile_assign(&dummy_node, assign_ast);
        zend_do_free(&dummy_node);
 }
@@ -2843,8 +2838,9 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
 
 static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
 {
-       zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
-               zend_ast_create_znode(value_node));
+       zend_ast_loc loc = zend_ast_get_loc(var_ast);
+       zend_ast *assign_ast = zend_ast_create(&loc, ZEND_AST_ASSIGN_REF, var_ast,
+               zend_ast_create_znode(&loc, value_node));
        zend_compile_assign_ref(NULL, assign_ast);
 }
 /* }}} */
@@ -3446,9 +3442,10 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string
                    (args->child[0]->kind != ZEND_AST_ZVAL ||
                     Z_TYPE_P(zend_ast_get_zval(args->child[0])) != IS_STRING)) {
                        /* add "assert(condition) as assertion message */
+                       zend_ast_loc loc = zend_ast_get_loc(args->child[0]);
                        zend_ast_list_add((zend_ast*)args,
                                zend_ast_create_zval_from_str(
-                                       zend_ast_export("assert(", args->child[0], ")")));
+                                       &loc, zend_ast_export("assert(", args->child[0], ")")));
                }
 
                zend_compile_call_common(result, (zend_ast*)args, fbc);
@@ -4041,8 +4038,9 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */
                        zend_string_addref(Z_STR(name_node.u.constant));
                }
 
+               zend_ast_loc loc = zend_ast_get_loc(var_ast);
                zend_emit_assign_ref_znode(
-                       zend_ast_create(ZEND_AST_VAR, zend_ast_create_znode(&name_node)),
+                       zend_ast_create(&loc, ZEND_AST_VAR, zend_ast_create_znode(&loc, &name_node)),
                        &result
                );
        }
@@ -6542,7 +6540,9 @@ void zend_compile_group_use(zend_ast *ast) /* {{{ */
                zend_string *compound_ns = zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
                zend_string_release_ex(name, 0);
                ZVAL_STR(name_zval, compound_ns);
-               inline_use = zend_ast_create_list(1, ZEND_AST_USE, use);
+
+               zend_ast_loc loc = zend_ast_get_loc(ast);
+               inline_use = zend_ast_create_list(&loc, 1, ZEND_AST_USE, use);
                inline_use->attr = ast->attr ? ast->attr : use->attr;
                zend_compile_use(inline_use);
        }
@@ -7544,7 +7544,8 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
        if (!zend_is_variable(var_ast)) {
                if (ast->kind == ZEND_AST_EMPTY) {
                        /* empty(expr) can be transformed to !expr */
-                       zend_ast *not_ast = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
+                       zend_ast_loc loc = zend_ast_get_loc(ast);
+                       zend_ast *not_ast = zend_ast_create_ex(&loc, ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
                        zend_compile_expr(result, not_ast);
                        return;
                } else {
@@ -7614,9 +7615,10 @@ void zend_compile_shell_exec(znode *result, zend_ast *ast) /* {{{ */
        zend_ast *name_ast, *args_ast, *call_ast;
 
        ZVAL_STRING(&fn_name, "shell_exec");
-       name_ast = zend_ast_create_zval(&fn_name);
-       args_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, expr_ast);
-       call_ast = zend_ast_create(ZEND_AST_CALL, name_ast, args_ast);
+       zend_ast_loc loc = zend_ast_get_loc(ast);
+       name_ast = zend_ast_create_zval(&loc, &fn_name);
+       args_ast = zend_ast_create_list(&loc, 1, ZEND_AST_ARG_LIST, expr_ast);
+       call_ast = zend_ast_create(&loc, ZEND_AST_CALL, name_ast, args_ast);
 
        zend_compile_expr(result, call_ast);
 
@@ -8020,7 +8022,8 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
        zend_ast_destroy(ast);
        zend_string_release_ex(class_name, 0);
 
-       *ast_ptr = zend_ast_create_constant(name, fetch_type | ZEND_FETCH_CLASS_EXCEPTION);
+       zend_ast_loc loc = zend_ast_get_loc(ast);
+       *ast_ptr = zend_ast_create_constant(&loc, name, fetch_type | ZEND_FETCH_CLASS_EXCEPTION);
 }
 /* }}} */
 
@@ -8055,6 +8058,7 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
        zend_bool is_fully_qualified;
        zval result;
        zend_string *resolved_name;
+       zend_ast_loc loc = zend_ast_get_loc(ast);
 
        resolved_name = zend_resolve_const_name(
                orig_name, name_ast->attr, &is_fully_qualified);
@@ -8062,24 +8066,25 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
        if (zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) {
                zend_string_release_ex(resolved_name, 0);
                zend_ast_destroy(ast);
-               *ast_ptr = zend_ast_create_zval(&result);
+               *ast_ptr = zend_ast_create_zval(&loc, &result);
                return;
        }
 
        zend_ast_destroy(ast);
-       *ast_ptr = zend_ast_create_constant(resolved_name, !is_fully_qualified ? IS_CONSTANT_UNQUALIFIED : 0);
+       *ast_ptr = zend_ast_create_constant(&loc, resolved_name, !is_fully_qualified ? IS_CONSTANT_UNQUALIFIED : 0);
 }
 /* }}} */
 
 void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
 {
        zend_ast *ast = *ast_ptr;
+       zend_ast_loc loc = zend_ast_get_loc(ast);
 
        /* Other cases already resolved by constant folding */
        ZEND_ASSERT(ast->attr == T_CLASS_C);
 
        zend_ast_destroy(ast);
-       *ast_ptr = zend_ast_create(ZEND_AST_CONSTANT_CLASS);
+       *ast_ptr = zend_ast_create(&loc, ZEND_AST_CONSTANT_CLASS);
 }
 /* }}} */
 
@@ -8726,7 +8731,8 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
                        return;
        }
 
+       zend_ast_loc loc = zend_ast_get_loc(ast);
        zend_ast_destroy(ast);
-       *ast_ptr = zend_ast_create_zval(&result);
+       *ast_ptr = zend_ast_create_zval(&loc, &result);
 }
 /* }}} */
index 82d70fd4b026ddc51556965e31581781ec2f365c..646aef4663310f3868dc36022d51fb92c576cfd2 100644 (file)
@@ -94,8 +94,6 @@ typedef struct _zend_ast_znode {
        znode node;
 } zend_ast_znode;
 
-ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node);
-
 static zend_always_inline znode *zend_ast_get_znode(zend_ast *ast) {
        return &((zend_ast_znode *) ast)->node;
 }
@@ -732,7 +730,7 @@ void zend_file_context_end(zend_file_context *prev_context);
 extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
 extern ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename);
 
-ZEND_API int ZEND_FASTCALL lex_scan(zval *zendlval, zend_parser_stack_elem *elem);
+ZEND_API int ZEND_FASTCALL lex_scan(zval *zendlval, zend_parser_stack_elem *elem, zend_ast_loc *loc);
 void startup_scanner(void);
 void shutdown_scanner(void);
 
@@ -845,7 +843,7 @@ ZEND_API zend_bool zend_is_auto_global_str(char *name, size_t len);
 ZEND_API size_t zend_dirname(char *path, size_t len);
 ZEND_API void zend_set_function_arg_flags(zend_function *func);
 
-int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem);
+int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem, zend_ast_loc *loc);
 
 void zend_assert_valid_class_name(const zend_string *const_name);
 
index c95faef22b67e8b63b243986ecaa57c57c11e705..24ca1c52a2d656ab8caeb2ac84fff01aa9d45ad7 100644 (file)
@@ -94,7 +94,6 @@ struct _zend_compiler_globals {
        struct _zend_ini_parser_param *ini_parser_param;
 
        uint32_t start_lineno;
-       zend_bool increment_lineno;
 
        zend_string *doc_comment;
        uint32_t extra_fn_flags;
index 5e94df0a9911c9c650450fc3b1ed6018fdf316b1..168a51ca3006f4379dfd433b0ab47cf9e192f9f1 100644 (file)
@@ -85,13 +85,14 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
 {
        zval token;
        int token_type;
+       zend_ast_loc loc;
        char *last_color = syntax_highlighter_ini->highlight_html;
        char *next_color;
 
        zend_printf("<code>");
        zend_printf("<span style=\"color: %s\">\n", last_color);
        /* highlight stuff coming back from zendlex() */
-       while ((token_type=lex_scan(&token, NULL))) {
+       while ((token_type = lex_scan(&token, NULL, &loc))) {
                switch (token_type) {
                        case T_INLINE_HTML:
                                next_color = syntax_highlighter_ini->highlight_html;
@@ -174,10 +175,11 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
 ZEND_API void zend_strip(void)
 {
        zval token;
+       zend_ast_loc loc;
        int token_type;
        int prev_space = 0;
 
-       while ((token_type=lex_scan(&token, NULL))) {
+       while ((token_type = lex_scan(&token, NULL, &loc))) {
                switch (token_type) {
                        case T_WHITESPACE:
                                if (!prev_space) {
@@ -193,7 +195,7 @@ ZEND_API void zend_strip(void)
                        case T_END_HEREDOC:
                                zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
                                /* read the following character, either newline or ; */
-                               if (lex_scan(&token, NULL) != T_WHITESPACE) {
+                               if (lex_scan(&token, NULL, &loc) != T_WHITESPACE) {
                                        zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
                                }
                                zend_write("\n", sizeof("\n") - 1);
index af5ce87fa2daca887111954c4daa04c61ffa3a2a..cd2303fe392c1d526d288b2862b936722a10a1ad 100644 (file)
@@ -35,6 +35,15 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
 #define YYERROR_VERBOSE
 #define YYSTYPE zend_parser_stack_elem
 
+#define YYLTYPE zend_ast_loc
+#define YYLLOC_DEFAULT(Res, RHS, N) do { \
+       if (N) { \
+               (Res).start_line = YYRHSLOC(RHS, 1).start_line; \
+       } else { \
+               (Res).start_line = yylloc.start_line; \
+       } \
+} while (0)
+
 #ifdef _MSC_VER
 #define YYMALLOC malloc
 #define YYFREE free
@@ -240,19 +249,19 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
 %type <ast> variable_class_name dereferencable_scalar constant dereferencable
 %type <ast> callable_expr callable_variable static_member new_variable
 %type <ast> encaps_var encaps_var_offset isset_variables
-%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt
-%type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list
-%type <ast> echo_expr_list unset_variables catch_name_list catch_list parameter_list class_statement_list
-%type <ast> implements_list case_list if_stmt_without_else
+%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt elseif_stmt
+%type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list else_stmt
+%type <ast> echo_expr_list unset_variables catch_name_list catch_list parameter_list
+%type <ast> implements_list case_list case if_stmt_without_else catch class_statement_list
 %type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list
 %type <ast> class_const_list class_const_decl name_list trait_adaptations method_body non_empty_for_exprs
 %type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
-%type <ast> lexical_var_list encaps_list
+%type <ast> lexical_var_list encaps_list alt_elseif_stmt alt_else_stmt
 %type <ast> array_pair non_empty_array_pair_list array_pair_list possible_array_pair
 %type <ast> isset_variable type return_type type_expr
 %type <ast> identifier
 
-%type <num> returns_ref function is_reference is_variadic variable_modifiers
+%type <num> returns_ref is_reference is_variadic variable_modifiers
 %type <num> method_modifiers non_empty_member_modifiers member_modifier
 %type <num> class_modifiers class_modifier use_type backup_fn_flags
 
@@ -284,13 +293,13 @@ identifier:
        |       semi_reserved  {
                        zval zv;
                        zend_lex_tstring(&zv);
-                       $$ = zend_ast_create_zval(&zv);
+                       $$ = zend_ast_create_zval(&@$, &zv);
                }
 ;
 
 top_statement_list:
                top_statement_list top_statement { $$ = zend_ast_list_add($1, $2); }
-       |       /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); }
+       |       /* empty */ { $$ = zend_ast_create_list(&@$, 0, ZEND_AST_STMT_LIST); }
 ;
 
 namespace_name:
@@ -311,18 +320,18 @@ top_statement:
        |       trait_declaration_statement                     { $$ = $1; }
        |       interface_declaration_statement         { $$ = $1; }
        |       T_HALT_COMPILER '(' ')' ';'
-                       { $$ = zend_ast_create(ZEND_AST_HALT_COMPILER,
-                             zend_ast_create_zval_from_long(zend_get_scanned_file_offset()));
+                       { $$ = zend_ast_create(&@$, ZEND_AST_HALT_COMPILER,
+                             zend_ast_create_zval_from_long(&@$, zend_get_scanned_file_offset()));
                          zend_stop_lexing(); }
        |       T_NAMESPACE namespace_name ';'
-                       { $$ = zend_ast_create(ZEND_AST_NAMESPACE, $2, NULL);
+                       { $$ = zend_ast_create(&@$, ZEND_AST_NAMESPACE, $2, NULL);
                          RESET_DOC_COMMENT(); }
        |       T_NAMESPACE namespace_name { RESET_DOC_COMMENT(); }
                '{' top_statement_list '}'
-                       { $$ = zend_ast_create(ZEND_AST_NAMESPACE, $2, $5); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_NAMESPACE, $2, $5); }
        |       T_NAMESPACE { RESET_DOC_COMMENT(); }
                '{' top_statement_list '}'
-                       { $$ = zend_ast_create(ZEND_AST_NAMESPACE, NULL, $4); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_NAMESPACE, NULL, $4); }
        |       T_USE mixed_group_use_declaration ';'           { $$ = $2; }
        |       T_USE use_type group_use_declaration ';'        { $$ = $3; $$->attr = $2; }
        |       T_USE use_declarations ';'                                      { $$ = $2; $$->attr = ZEND_SYMBOL_CLASS; }
@@ -337,16 +346,16 @@ use_type:
 
 group_use_declaration:
                namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations possible_comma '}'
-                       { $$ = zend_ast_create(ZEND_AST_GROUP_USE, $1, $4); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_GROUP_USE, $1, $4); }
        |       T_NS_SEPARATOR namespace_name T_NS_SEPARATOR '{' unprefixed_use_declarations possible_comma '}'
-                       { $$ = zend_ast_create(ZEND_AST_GROUP_USE, $2, $5); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_GROUP_USE, $2, $5); }
 ;
 
 mixed_group_use_declaration:
                namespace_name T_NS_SEPARATOR '{' inline_use_declarations possible_comma '}'
-                       { $$ = zend_ast_create(ZEND_AST_GROUP_USE, $1, $4);}
+                       { $$ = zend_ast_create(&@$, ZEND_AST_GROUP_USE, $1, $4);}
        |       T_NS_SEPARATOR namespace_name T_NS_SEPARATOR '{' inline_use_declarations possible_comma '}'
-                       { $$ = zend_ast_create(ZEND_AST_GROUP_USE, $2, $5); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_GROUP_USE, $2, $5); }
 ;
 
 possible_comma:
@@ -358,21 +367,21 @@ inline_use_declarations:
                inline_use_declarations ',' inline_use_declaration
                        { $$ = zend_ast_list_add($1, $3); }
        |       inline_use_declaration
-                       { $$ = zend_ast_create_list(1, ZEND_AST_USE, $1); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_USE, $1); }
 ;
 
 unprefixed_use_declarations:
                unprefixed_use_declarations ',' unprefixed_use_declaration
                        { $$ = zend_ast_list_add($1, $3); }
        |       unprefixed_use_declaration
-                       { $$ = zend_ast_create_list(1, ZEND_AST_USE, $1); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_USE, $1); }
 ;
 
 use_declarations:
                use_declarations ',' use_declaration
                        { $$ = zend_ast_list_add($1, $3); }
        |       use_declaration
-                       { $$ = zend_ast_create_list(1, ZEND_AST_USE, $1); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_USE, $1); }
 ;
 
 inline_use_declaration:
@@ -382,9 +391,9 @@ inline_use_declaration:
 
 unprefixed_use_declaration:
                namespace_name
-                       { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $1, NULL); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_USE_ELEM, $1, NULL); }
        |       namespace_name T_AS T_STRING
-                       { $$ = zend_ast_create(ZEND_AST_USE_ELEM, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_USE_ELEM, $1, $3); }
 ;
 
 use_declaration:
@@ -394,14 +403,14 @@ use_declaration:
 
 const_list:
                const_list ',' const_decl { $$ = zend_ast_list_add($1, $3); }
-       |       const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CONST_DECL, $1); }
+       |       const_decl { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_CONST_DECL, $1); }
 ;
 
 inner_statement_list:
                inner_statement_list inner_statement
                        { $$ = zend_ast_list_add($1, $2); }
        |       /* empty */
-                       { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); }
+                       { $$ = zend_ast_create_list(&@$, 0, ZEND_AST_STMT_LIST); }
 ;
 
 
@@ -422,48 +431,51 @@ statement:
        |       if_stmt { $$ = $1; }
        |       alt_if_stmt { $$ = $1; }
        |       T_WHILE '(' expr ')' while_statement
-                       { $$ = zend_ast_create(ZEND_AST_WHILE, $3, $5); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_WHILE, $3, $5); }
        |       T_DO statement T_WHILE '(' expr ')' ';'
-                       { $$ = zend_ast_create(ZEND_AST_DO_WHILE, $2, $5); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DO_WHILE, $2, $5); }
        |       T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement
-                       { $$ = zend_ast_create(ZEND_AST_FOR, $3, $5, $7, $9); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_FOR, $3, $5, $7, $9); }
        |       T_SWITCH '(' expr ')' switch_case_list
-                       { $$ = zend_ast_create(ZEND_AST_SWITCH, $3, $5); }
-       |       T_BREAK optional_expr ';'               { $$ = zend_ast_create(ZEND_AST_BREAK, $2); }
-       |       T_CONTINUE optional_expr ';'    { $$ = zend_ast_create(ZEND_AST_CONTINUE, $2); }
-       |       T_RETURN optional_expr ';'              { $$ = zend_ast_create(ZEND_AST_RETURN, $2); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_SWITCH, $3, $5); }
+       |       T_BREAK optional_expr ';'               { $$ = zend_ast_create(&@$, ZEND_AST_BREAK, $2); }
+       |       T_CONTINUE optional_expr ';'    { $$ = zend_ast_create(&@$, ZEND_AST_CONTINUE, $2); }
+       |       T_RETURN optional_expr ';'              { $$ = zend_ast_create(&@$, ZEND_AST_RETURN, $2); }
        |       T_GLOBAL global_var_list ';'    { $$ = $2; }
        |       T_STATIC static_var_list ';'    { $$ = $2; }
        |       T_ECHO echo_expr_list ';'               { $$ = $2; }
-       |       T_INLINE_HTML { $$ = zend_ast_create(ZEND_AST_ECHO, $1); }
+       |       T_INLINE_HTML { $$ = zend_ast_create(&@$, ZEND_AST_ECHO, $1); }
        |       expr ';' { $$ = $1; }
        |       T_UNSET '(' unset_variables possible_comma ')' ';' { $$ = $3; }
        |       T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
-                       { $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $5, NULL, $7); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_FOREACH, $3, $5, NULL, $7); }
        |       T_FOREACH '(' expr T_AS foreach_variable T_DOUBLE_ARROW foreach_variable ')'
                foreach_statement
-                       { $$ = zend_ast_create(ZEND_AST_FOREACH, $3, $7, $5, $9); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_FOREACH, $3, $7, $5, $9); }
        |       T_DECLARE '(' const_list ')'
                        { if (!zend_handle_encoding_declaration($3)) { YYERROR; } }
                declare_statement
-                       { $$ = zend_ast_create(ZEND_AST_DECLARE, $3, $6); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DECLARE, $3, $6); }
        |       ';'     /* empty statement */ { $$ = NULL; }
        |       T_TRY '{' inner_statement_list '}' catch_list finally_statement
-                       { $$ = zend_ast_create(ZEND_AST_TRY, $3, $5, $6); }
-       |       T_THROW expr ';' { $$ = zend_ast_create(ZEND_AST_THROW, $2); }
-       |       T_GOTO T_STRING ';' { $$ = zend_ast_create(ZEND_AST_GOTO, $2); }
-       |       T_STRING ':' { $$ = zend_ast_create(ZEND_AST_LABEL, $1); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_TRY, $3, $5, $6); }
+       |       T_THROW expr ';' { $$ = zend_ast_create(&@$, ZEND_AST_THROW, $2); }
+       |       T_GOTO T_STRING ';' { $$ = zend_ast_create(&@$, ZEND_AST_GOTO, $2); }
+       |       T_STRING ':' { $$ = zend_ast_create(&@$, ZEND_AST_LABEL, $1); }
 ;
 
 catch_list:
-               /* empty */
-                       { $$ = zend_ast_create_list(0, ZEND_AST_CATCH_LIST); }
-       |       catch_list T_CATCH '(' catch_name_list T_VARIABLE ')' '{' inner_statement_list '}'
-                       { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_CATCH, $4, $5, $8)); }
+               /* empty */ { $$ = zend_ast_create_list(&@$, 0, ZEND_AST_CATCH_LIST); }
+       |       catch_list catch { $$ = zend_ast_list_add($1, $2); }
+;
+
+catch:
+               T_CATCH '(' catch_name_list T_VARIABLE ')' '{' inner_statement_list '}'
+                       { $$ = zend_ast_create(&@$, ZEND_AST_CATCH, $3, $4, $7); }
 ;
 
 catch_name_list:
-               name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); }
+               name { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_NAME_LIST, $1); }
        |       catch_name_list '|' name { $$ = zend_ast_list_add($1, $3); }
 ;
 
@@ -473,18 +485,18 @@ finally_statement:
 ;
 
 unset_variables:
-               unset_variable { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }
+               unset_variable { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_STMT_LIST, $1); }
        |       unset_variables ',' unset_variable { $$ = zend_ast_list_add($1, $3); }
 ;
 
 unset_variable:
-               variable { $$ = zend_ast_create(ZEND_AST_UNSET, $1); }
+               variable { $$ = zend_ast_create(&@$, ZEND_AST_UNSET, $1); }
 ;
 
 function_declaration_statement:
-       function returns_ref T_STRING backup_doc_comment '(' parameter_list ')' return_type
+       T_FUNCTION returns_ref T_STRING backup_doc_comment '(' parameter_list ')' return_type
        backup_fn_flags '{' inner_statement_list '}' backup_fn_flags
-               { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2 | $13, $1, $4,
+               { $$ = zend_ast_create_decl(&@$, ZEND_AST_FUNC_DECL, $2 | $13, $4,
                      zend_ast_get_str($3), $6, NULL, $11, $8); CG(extra_fn_flags) = $9; }
 ;
 
@@ -499,12 +511,10 @@ is_variadic:
 ;
 
 class_declaration_statement:
-               class_modifiers T_CLASS { $<num>$ = CG(zend_lineno); }
-               T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
-                       { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $<num>3, $7, zend_ast_get_str($4), $5, $6, $9, NULL); }
-       |       T_CLASS { $<num>$ = CG(zend_lineno); }
-               T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
-                       { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $<num>2, $6, zend_ast_get_str($3), $4, $5, $8, NULL); }
+               class_modifiers T_CLASS T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
+                       { $$ = zend_ast_create_decl(&@$, ZEND_AST_CLASS, $1, $6, zend_ast_get_str($3), $4, $5, $8, NULL); }
+       |       T_CLASS T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}'
+                       { $$ = zend_ast_create_decl(&@$, ZEND_AST_CLASS, 0, $5, zend_ast_get_str($2), $3, $4, $7, NULL); }
 ;
 
 class_modifiers:
@@ -519,15 +529,13 @@ class_modifier:
 ;
 
 trait_declaration_statement:
-               T_TRAIT { $<num>$ = CG(zend_lineno); }
-               T_STRING backup_doc_comment '{' class_statement_list '}'
-                       { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $<num>2, $4, zend_ast_get_str($3), NULL, NULL, $6, NULL); }
+               T_TRAIT T_STRING backup_doc_comment '{' class_statement_list '}'
+                       { $$ = zend_ast_create_decl(&@$, ZEND_AST_CLASS, ZEND_ACC_TRAIT, $3, zend_ast_get_str($2), NULL, NULL, $5, NULL); }
 ;
 
 interface_declaration_statement:
-               T_INTERFACE { $<num>$ = CG(zend_lineno); }
-               T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}'
-                       { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $<num>2, $5, zend_ast_get_str($3), NULL, $4, $7, NULL); }
+               T_INTERFACE T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}'
+                       { $$ = zend_ast_create_decl(&@$, ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $4, zend_ast_get_str($2), NULL, $3, $6, NULL); }
 ;
 
 extends_from:
@@ -547,7 +555,7 @@ implements_list:
 
 foreach_variable:
                variable                        { $$ = $1; }
-       |       '&' variable            { $$ = zend_ast_create(ZEND_AST_REF, $2); }
+       |       '&' variable            { $$ = zend_ast_create(&@$, ZEND_AST_REF, $2); }
        |       T_LIST '(' array_pair_list ')' { $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_LIST; }
        |       '[' array_pair_list ']' { $$ = $2; $$->attr = ZEND_ARRAY_SYNTAX_SHORT; }
 ;
@@ -575,11 +583,15 @@ switch_case_list:
 ;
 
 case_list:
-               /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_SWITCH_LIST); }
-       |       case_list T_CASE expr case_separator inner_statement_list
-                       { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, $3, $5)); }
-       |       case_list T_DEFAULT case_separator inner_statement_list
-                       { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, NULL, $4)); }
+               /* empty */ { $$ = zend_ast_create_list(&@$, 0, ZEND_AST_SWITCH_LIST); }
+       |       case_list case { $$ = zend_ast_list_add($1, $2); }
+;
+
+case:
+               T_CASE expr case_separator inner_statement_list
+                       { $$ = zend_ast_create(&@$, ZEND_AST_SWITCH_CASE, $2, $4); }
+       |       T_DEFAULT case_separator inner_statement_list
+                       { $$ = zend_ast_create(&@$, ZEND_AST_SWITCH_CASE, NULL, $3); }
 ;
 
 case_separator:
@@ -596,53 +608,66 @@ while_statement:
 
 if_stmt_without_else:
                T_IF '(' expr ')' statement
-                       { $$ = zend_ast_create_list(1, ZEND_AST_IF,
-                             zend_ast_create(ZEND_AST_IF_ELEM, $3, $5)); }
-       |       if_stmt_without_else T_ELSEIF '(' expr ')' statement
-                       { $$ = zend_ast_list_add($1,
-                             zend_ast_create(ZEND_AST_IF_ELEM, $4, $6)); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_IF,
+                             zend_ast_create(&@$, ZEND_AST_IF_ELEM, $3, $5)); }
+       |       if_stmt_without_else elseif_stmt
+                       { $$ = zend_ast_list_add($1, $2); }
+;
+
+elseif_stmt:
+               T_ELSEIF '(' expr ')' statement { $$ = zend_ast_create(&@$, ZEND_AST_IF_ELEM, $3, $5); }
+;
+
+else_stmt:
+               T_ELSE statement { $$ = zend_ast_create(&@$, ZEND_AST_IF_ELEM, NULL, $2); }
 ;
 
 if_stmt:
                if_stmt_without_else %prec T_NOELSE { $$ = $1; }
-       |       if_stmt_without_else T_ELSE statement
-                       { $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_IF_ELEM, NULL, $3)); }
+       |       if_stmt_without_else else_stmt { $$ = zend_ast_list_add($1, $2); }
 ;
 
 alt_if_stmt_without_else:
                T_IF '(' expr ')' ':' inner_statement_list
-                       { $$ = zend_ast_create_list(1, ZEND_AST_IF,
-                             zend_ast_create(ZEND_AST_IF_ELEM, $3, $6)); }
-       |       alt_if_stmt_without_else T_ELSEIF '(' expr ')' ':' inner_statement_list
-                       { $$ = zend_ast_list_add($1,
-                             zend_ast_create(ZEND_AST_IF_ELEM, $4, $7)); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_IF,
+                             zend_ast_create(&@$, ZEND_AST_IF_ELEM, $3, $6)); }
+       |       alt_if_stmt_without_else alt_elseif_stmt
+                       { $$ = zend_ast_list_add($1, $2); }
+;
+
+alt_elseif_stmt:
+               T_ELSEIF '(' expr ')' ':' inner_statement_list
+                       { $$ = zend_ast_create(&@$, ZEND_AST_IF_ELEM, $3, $6); }
+;
+
+alt_else_stmt:
+               T_ELSE ':' inner_statement_list T_ENDIF ';'
+                       { $$ = zend_ast_create(&@$, ZEND_AST_IF_ELEM, NULL, $3); }
 ;
 
 alt_if_stmt:
                alt_if_stmt_without_else T_ENDIF ';' { $$ = $1; }
-       |       alt_if_stmt_without_else T_ELSE ':' inner_statement_list T_ENDIF ';'
-                       { $$ = zend_ast_list_add($1,
-                             zend_ast_create(ZEND_AST_IF_ELEM, NULL, $4)); }
+       |       alt_if_stmt_without_else alt_else_stmt { $$ = zend_ast_list_add($1, $2); }
 ;
 
 parameter_list:
                non_empty_parameter_list { $$ = $1; }
-       |       /* empty */     { $$ = zend_ast_create_list(0, ZEND_AST_PARAM_LIST); }
+       |       /* empty */     { $$ = zend_ast_create_list(&@$, 0, ZEND_AST_PARAM_LIST); }
 ;
 
 
 non_empty_parameter_list:
                parameter
-                       { $$ = zend_ast_create_list(1, ZEND_AST_PARAM_LIST, $1); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_PARAM_LIST, $1); }
        |       non_empty_parameter_list ',' parameter
                        { $$ = zend_ast_list_add($1, $3); }
 ;
 
 parameter:
                optional_type is_reference is_variadic T_VARIABLE
-                       { $$ = zend_ast_create_ex(ZEND_AST_PARAM, $2 | $3, $1, $4, NULL); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_PARAM, $2 | $3, $1, $4, NULL); }
        |       optional_type is_reference is_variadic T_VARIABLE '=' expr
-                       { $$ = zend_ast_create_ex(ZEND_AST_PARAM, $2 | $3, $1, $4, $6); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_PARAM, $2 | $3, $1, $4, $6); }
 ;
 
 
@@ -657,8 +682,8 @@ type_expr:
 ;
 
 type:
-               T_ARRAY         { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); }
-       |       T_CALLABLE      { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_CALLABLE); }
+               T_ARRAY         { $$ = zend_ast_create_ex(&@$, ZEND_AST_TYPE, IS_ARRAY); }
+       |       T_CALLABLE      { $$ = zend_ast_create_ex(&@$, ZEND_AST_TYPE, IS_CALLABLE); }
        |       name            { $$ = $1; }
 ;
 
@@ -668,41 +693,41 @@ return_type:
 ;
 
 argument_list:
-               '(' ')' { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); }
+               '(' ')' { $$ = zend_ast_create_list(&@$, 0, ZEND_AST_ARG_LIST); }
        |       '(' non_empty_argument_list possible_comma ')' { $$ = $2; }
 ;
 
 non_empty_argument_list:
                argument
-                       { $$ = zend_ast_create_list(1, ZEND_AST_ARG_LIST, $1); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_ARG_LIST, $1); }
        |       non_empty_argument_list ',' argument
                        { $$ = zend_ast_list_add($1, $3); }
 ;
 
 argument:
                expr                    { $$ = $1; }
-       |       T_ELLIPSIS expr { $$ = zend_ast_create(ZEND_AST_UNPACK, $2); }
+       |       T_ELLIPSIS expr { $$ = zend_ast_create(&@$, ZEND_AST_UNPACK, $2); }
 ;
 
 global_var_list:
                global_var_list ',' global_var { $$ = zend_ast_list_add($1, $3); }
-       |       global_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }
+       |       global_var { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_STMT_LIST, $1); }
 ;
 
 global_var:
        simple_variable
-               { $$ = zend_ast_create(ZEND_AST_GLOBAL, zend_ast_create(ZEND_AST_VAR, $1)); }
+               { $$ = zend_ast_create(&@$, ZEND_AST_GLOBAL, zend_ast_create(&@$, ZEND_AST_VAR, $1)); }
 ;
 
 
 static_var_list:
                static_var_list ',' static_var { $$ = zend_ast_list_add($1, $3); }
-       |       static_var { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }
+       |       static_var { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_STMT_LIST, $1); }
 ;
 
 static_var:
-               T_VARIABLE                      { $$ = zend_ast_create(ZEND_AST_STATIC, $1, NULL); }
-       |       T_VARIABLE '=' expr     { $$ = zend_ast_create(ZEND_AST_STATIC, $1, $3); }
+               T_VARIABLE                      { $$ = zend_ast_create(&@$, ZEND_AST_STATIC, $1, NULL); }
+       |       T_VARIABLE '=' expr     { $$ = zend_ast_create(&@$, ZEND_AST_STATIC, $1, $3); }
 ;
 
 
@@ -710,26 +735,26 @@ class_statement_list:
                class_statement_list class_statement
                        { $$ = zend_ast_list_add($1, $2); }
        |       /* empty */
-                       { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); }
+                       { $$ = zend_ast_create_list(&@$, 0, ZEND_AST_STMT_LIST); }
 ;
 
 
 class_statement:
                variable_modifiers optional_type property_list ';'
-                       { $$ = zend_ast_create(ZEND_AST_PROP_GROUP, $2, $3);
+                       { $$ = zend_ast_create(&@$, ZEND_AST_PROP_GROUP, $2, $3);
                          $$->attr = $1; }
        |       method_modifiers T_CONST class_const_list ';'
                        { $$ = $3; $$->attr = $1; }
        |       T_USE name_list trait_adaptations
-                       { $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); }
-       |       method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')'
+                       { $$ = zend_ast_create(&@$, ZEND_AST_USE_TRAIT, $2, $3); }
+       |       method_modifiers T_FUNCTION returns_ref identifier backup_doc_comment '(' parameter_list ')'
                return_type backup_fn_flags method_body backup_fn_flags
-                       { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1 | $12, $2, $5,
+                       { $$ = zend_ast_create_decl(&@$, ZEND_AST_METHOD, $3 | $1 | $12, $5,
                                  zend_ast_get_str($4), $7, NULL, $11, $9); CG(extra_fn_flags) = $10; }
 ;
 
 name_list:
-               name { $$ = zend_ast_create_list(1, ZEND_AST_NAME_LIST, $1); }
+               name { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_NAME_LIST, $1); }
        |       name_list ',' name { $$ = zend_ast_list_add($1, $3); }
 ;
 
@@ -741,7 +766,7 @@ trait_adaptations:
 
 trait_adaptation_list:
                trait_adaptation
-                       { $$ = zend_ast_create_list(1, ZEND_AST_TRAIT_ADAPTATIONS, $1); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_TRAIT_ADAPTATIONS, $1); }
        |       trait_adaptation_list trait_adaptation
                        { $$ = zend_ast_list_add($1, $2); }
 ;
@@ -753,29 +778,29 @@ trait_adaptation:
 
 trait_precedence:
        absolute_trait_method_reference T_INSTEADOF name_list
-               { $$ = zend_ast_create(ZEND_AST_TRAIT_PRECEDENCE, $1, $3); }
+               { $$ = zend_ast_create(&@$, ZEND_AST_TRAIT_PRECEDENCE, $1, $3); }
 ;
 
 trait_alias:
                trait_method_reference T_AS T_STRING
-                       { $$ = zend_ast_create(ZEND_AST_TRAIT_ALIAS, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_TRAIT_ALIAS, $1, $3); }
        |       trait_method_reference T_AS reserved_non_modifiers
-                       { zval zv; zend_lex_tstring(&zv); $$ = zend_ast_create(ZEND_AST_TRAIT_ALIAS, $1, zend_ast_create_zval(&zv)); }
+                       { zval zv; zend_lex_tstring(&zv); $$ = zend_ast_create(&@$, ZEND_AST_TRAIT_ALIAS, $1, zend_ast_create_zval(&@3, &zv)); }
        |       trait_method_reference T_AS member_modifier identifier
-                       { $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, $3, $1, $4); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_TRAIT_ALIAS, $3, $1, $4); }
        |       trait_method_reference T_AS member_modifier
-                       { $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, $3, $1, NULL); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_TRAIT_ALIAS, $3, $1, NULL); }
 ;
 
 trait_method_reference:
                identifier
-                       { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, NULL, $1); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_METHOD_REFERENCE, NULL, $1); }
        |       absolute_trait_method_reference { $$ = $1; }
 ;
 
 absolute_trait_method_reference:
        name T_PAAMAYIM_NEKUDOTAYIM identifier
-               { $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, $1, $3); }
+               { $$ = zend_ast_create(&@$, ZEND_AST_METHOD_REFERENCE, $1, $3); }
 ;
 
 method_body:
@@ -811,35 +836,35 @@ member_modifier:
 
 property_list:
                property_list ',' property { $$ = zend_ast_list_add($1, $3); }
-       |       property { $$ = zend_ast_create_list(1, ZEND_AST_PROP_DECL, $1); }
+       |       property { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_PROP_DECL, $1); }
 ;
 
 property:
                T_VARIABLE backup_doc_comment
-                       { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, NULL, ($2 ? zend_ast_create_zval_from_str($2) : NULL)); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_PROP_ELEM, $1, NULL, ($2 ? zend_ast_create_zval_from_str(&@2, $2) : NULL)); }
        |       T_VARIABLE '=' expr backup_doc_comment
-                       { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_PROP_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str(&@4, $4) : NULL)); }
 ;
 
 class_const_list:
                class_const_list ',' class_const_decl { $$ = zend_ast_list_add($1, $3); }
-       |       class_const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CLASS_CONST_DECL, $1); }
+       |       class_const_decl { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_CLASS_CONST_DECL, $1); }
 ;
 
 class_const_decl:
-       identifier '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); }
+       identifier '=' expr backup_doc_comment { $$ = zend_ast_create(&@$, ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str(&@4, $4) : NULL)); }
 ;
 
 const_decl:
-       T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); }
+       T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(&@$, ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str(&@4, $4) : NULL)); }
 ;
 
 echo_expr_list:
                echo_expr_list ',' echo_expr { $$ = zend_ast_list_add($1, $3); }
-       |       echo_expr { $$ = zend_ast_create_list(1, ZEND_AST_STMT_LIST, $1); }
+       |       echo_expr { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_STMT_LIST, $1); }
 ;
 echo_expr:
-       expr { $$ = zend_ast_create(ZEND_AST_ECHO, $1); }
+       expr { $$ = zend_ast_create(&@$, ZEND_AST_ECHO, $1); }
 ;
 
 for_exprs:
@@ -849,22 +874,21 @@ for_exprs:
 
 non_empty_for_exprs:
                non_empty_for_exprs ',' expr { $$ = zend_ast_list_add($1, $3); }
-       |       expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); }
+       |       expr { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_EXPR_LIST, $1); }
 ;
 
 anonymous_class:
-        T_CLASS { $<num>$ = CG(zend_lineno); } ctor_arguments
-               extends_from implements_list backup_doc_comment '{' class_statement_list '}' {
+        T_CLASS ctor_arguments extends_from implements_list backup_doc_comment '{' class_statement_list '}' {
                        zend_ast *decl = zend_ast_create_decl(
-                               ZEND_AST_CLASS, ZEND_ACC_ANON_CLASS, $<num>2, $6, NULL,
-                               $4, $5, $8, NULL);
-                       $$ = zend_ast_create(ZEND_AST_NEW, decl, $3);
+                               &@$, ZEND_AST_CLASS, ZEND_ACC_ANON_CLASS, $5, NULL,
+                               $3, $4, $7, NULL);
+                       $$ = zend_ast_create(&@$, ZEND_AST_NEW, decl, $2);
                }
 ;
 
 new_expr:
                T_NEW class_name_reference ctor_arguments
-                       { $$ = zend_ast_create(ZEND_AST_NEW, $2, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_NEW, $2, $3); }
        |       T_NEW anonymous_class
                        { $$ = $2; }
 ;
@@ -873,131 +897,127 @@ expr:
                variable
                        { $$ = $1; }
        |       T_LIST '(' array_pair_list ')' '=' expr
-                       { $3->attr = ZEND_ARRAY_SYNTAX_LIST; $$ = zend_ast_create(ZEND_AST_ASSIGN, $3, $6); }
+                       { $3->attr = ZEND_ARRAY_SYNTAX_LIST; $$ = zend_ast_create(&@$, ZEND_AST_ASSIGN, $3, $6); }
        |       '[' array_pair_list ']' '=' expr
-                       { $2->attr = ZEND_ARRAY_SYNTAX_SHORT; $$ = zend_ast_create(ZEND_AST_ASSIGN, $2, $5); }
+                       { $2->attr = ZEND_ARRAY_SYNTAX_SHORT; $$ = zend_ast_create(&@$, ZEND_AST_ASSIGN, $2, $5); }
        |       variable '=' expr
-                       { $$ = zend_ast_create(ZEND_AST_ASSIGN, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_ASSIGN, $1, $3); }
        |       variable '=' '&' variable
-                       { $$ = zend_ast_create(ZEND_AST_ASSIGN_REF, $1, $4); }
-       |       T_CLONE expr { $$ = zend_ast_create(ZEND_AST_CLONE, $2); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_ASSIGN_REF, $1, $4); }
+       |       T_CLONE expr { $$ = zend_ast_create(&@$, ZEND_AST_CLONE, $2); }
        |       variable T_PLUS_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_ADD, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_ADD, $1, $3); }
        |       variable T_MINUS_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_SUB, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_SUB, $1, $3); }
        |       variable T_MUL_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_MUL, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_MUL, $1, $3); }
        |       variable T_POW_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_POW, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_POW, $1, $3); }
        |       variable T_DIV_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_DIV, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_DIV, $1, $3); }
        |       variable T_CONCAT_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_CONCAT, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_CONCAT, $1, $3); }
        |       variable T_MOD_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_MOD, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_MOD, $1, $3); }
        |       variable T_AND_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_BW_AND, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_BW_AND, $1, $3); }
        |       variable T_OR_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_BW_OR, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_BW_OR, $1, $3); }
        |       variable T_XOR_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_BW_XOR, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_BW_XOR, $1, $3); }
        |       variable T_SL_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_SL, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_SL, $1, $3); }
        |       variable T_SR_EQUAL expr
-                       { $$ = zend_ast_create_assign_op(ZEND_ASSIGN_SR, $1, $3); }
+                       { $$ = zend_ast_create_assign_op(&@$, ZEND_ASSIGN_SR, $1, $3); }
        |       variable T_COALESCE_EQUAL expr
-                       { $$ = zend_ast_create(ZEND_AST_ASSIGN_COALESCE, $1, $3); }
-       |       variable T_INC { $$ = zend_ast_create(ZEND_AST_POST_INC, $1); }
-       |       T_INC variable { $$ = zend_ast_create(ZEND_AST_PRE_INC, $2); }
-       |       variable T_DEC { $$ = zend_ast_create(ZEND_AST_POST_DEC, $1); }
-       |       T_DEC variable { $$ = zend_ast_create(ZEND_AST_PRE_DEC, $2); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_ASSIGN_COALESCE, $1, $3); }
+       |       variable T_INC { $$ = zend_ast_create(&@$, ZEND_AST_POST_INC, $1); }
+       |       T_INC variable { $$ = zend_ast_create(&@$, ZEND_AST_PRE_INC, $2); }
+       |       variable T_DEC { $$ = zend_ast_create(&@$, ZEND_AST_POST_DEC, $1); }
+       |       T_DEC variable { $$ = zend_ast_create(&@$, ZEND_AST_PRE_DEC, $2); }
        |       expr T_BOOLEAN_OR expr
-                       { $$ = zend_ast_create(ZEND_AST_OR, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_OR, $1, $3); }
        |       expr T_BOOLEAN_AND expr
-                       { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_AND, $1, $3); }
        |       expr T_LOGICAL_OR expr
-                       { $$ = zend_ast_create(ZEND_AST_OR, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_OR, $1, $3); }
        |       expr T_LOGICAL_AND expr
-                       { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_AND, $1, $3); }
        |       expr T_LOGICAL_XOR expr
-                       { $$ = zend_ast_create_binary_op(ZEND_BOOL_XOR, $1, $3); }
-       |       expr '|' expr   { $$ = zend_ast_create_binary_op(ZEND_BW_OR, $1, $3); }
-       |       expr '&' expr   { $$ = zend_ast_create_binary_op(ZEND_BW_AND, $1, $3); }
-       |       expr '^' expr   { $$ = zend_ast_create_binary_op(ZEND_BW_XOR, $1, $3); }
-       |       expr '.' expr   { $$ = zend_ast_create_binary_op(ZEND_CONCAT, $1, $3); }
-       |       expr '+' expr   { $$ = zend_ast_create_binary_op(ZEND_ADD, $1, $3); }
-       |       expr '-' expr   { $$ = zend_ast_create_binary_op(ZEND_SUB, $1, $3); }
-       |       expr '*' expr   { $$ = zend_ast_create_binary_op(ZEND_MUL, $1, $3); }
-       |       expr T_POW expr { $$ = zend_ast_create_binary_op(ZEND_POW, $1, $3); }
-       |       expr '/' expr   { $$ = zend_ast_create_binary_op(ZEND_DIV, $1, $3); }
-       |       expr '%' expr   { $$ = zend_ast_create_binary_op(ZEND_MOD, $1, $3); }
-       |       expr T_SL expr  { $$ = zend_ast_create_binary_op(ZEND_SL, $1, $3); }
-       |       expr T_SR expr  { $$ = zend_ast_create_binary_op(ZEND_SR, $1, $3); }
-       |       '+' expr %prec T_INC { $$ = zend_ast_create(ZEND_AST_UNARY_PLUS, $2); }
-       |       '-' expr %prec T_INC { $$ = zend_ast_create(ZEND_AST_UNARY_MINUS, $2); }
-       |       '!' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, $2); }
-       |       '~' expr { $$ = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BW_NOT, $2); }
+                       { $$ = zend_ast_create_binary_op(&@$, ZEND_BOOL_XOR, $1, $3); }
+       |       expr '|' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_BW_OR, $1, $3); }
+       |       expr '&' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_BW_AND, $1, $3); }
+       |       expr '^' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_BW_XOR, $1, $3); }
+       |       expr '.' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_CONCAT, $1, $3); }
+       |       expr '+' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_ADD, $1, $3); }
+       |       expr '-' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_SUB, $1, $3); }
+       |       expr '*' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_MUL, $1, $3); }
+       |       expr T_POW expr { $$ = zend_ast_create_binary_op(&@$, ZEND_POW, $1, $3); }
+       |       expr '/' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_DIV, $1, $3); }
+       |       expr '%' expr   { $$ = zend_ast_create_binary_op(&@$, ZEND_MOD, $1, $3); }
+       |       expr T_SL expr  { $$ = zend_ast_create_binary_op(&@$, ZEND_SL, $1, $3); }
+       |       expr T_SR expr  { $$ = zend_ast_create_binary_op(&@$, ZEND_SR, $1, $3); }
+       |       '+' expr %prec T_INC { $$ = zend_ast_create(&@$, ZEND_AST_UNARY_PLUS, $2); }
+       |       '-' expr %prec T_INC { $$ = zend_ast_create(&@$, ZEND_AST_UNARY_MINUS, $2); }
+       |       '!' expr { $$ = zend_ast_create_ex(&@$, ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, $2); }
+       |       '~' expr { $$ = zend_ast_create_ex(&@$, ZEND_AST_UNARY_OP, ZEND_BW_NOT, $2); }
        |       expr T_IS_IDENTICAL expr
-                       { $$ = zend_ast_create_binary_op(ZEND_IS_IDENTICAL, $1, $3); }
+                       { $$ = zend_ast_create_binary_op(&@$, ZEND_IS_IDENTICAL, $1, $3); }
        |       expr T_IS_NOT_IDENTICAL expr
-                       { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_IDENTICAL, $1, $3); }
+                       { $$ = zend_ast_create_binary_op(&@$, ZEND_IS_NOT_IDENTICAL, $1, $3); }
        |       expr T_IS_EQUAL expr
-                       { $$ = zend_ast_create_binary_op(ZEND_IS_EQUAL, $1, $3); }
+                       { $$ = zend_ast_create_binary_op(&@$, ZEND_IS_EQUAL, $1, $3); }
        |       expr T_IS_NOT_EQUAL expr
-                       { $$ = zend_ast_create_binary_op(ZEND_IS_NOT_EQUAL, $1, $3); }
+                       { $$ = zend_ast_create_binary_op(&@$, ZEND_IS_NOT_EQUAL, $1, $3); }
        |       expr '<' expr
-                       { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER, $1, $3); }
+                       { $$ = zend_ast_create_binary_op(&@$, ZEND_IS_SMALLER, $1, $3); }
        |       expr T_IS_SMALLER_OR_EQUAL expr
-                       { $$ = zend_ast_create_binary_op(ZEND_IS_SMALLER_OR_EQUAL, $1, $3); }
+                       { $$ = zend_ast_create_binary_op(&@$, ZEND_IS_SMALLER_OR_EQUAL, $1, $3); }
        |       expr '>' expr
-                       { $$ = zend_ast_create(ZEND_AST_GREATER, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_GREATER, $1, $3); }
        |       expr T_IS_GREATER_OR_EQUAL expr
-                       { $$ = zend_ast_create(ZEND_AST_GREATER_EQUAL, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_GREATER_EQUAL, $1, $3); }
        |       expr T_SPACESHIP expr
-                       { $$ = zend_ast_create_binary_op(ZEND_SPACESHIP, $1, $3); }
+                       { $$ = zend_ast_create_binary_op(&@$, ZEND_SPACESHIP, $1, $3); }
        |       expr T_INSTANCEOF class_name_reference
-                       { $$ = zend_ast_create(ZEND_AST_INSTANCEOF, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_INSTANCEOF, $1, $3); }
        |       '(' expr ')' { $$ = $2; }
        |       new_expr { $$ = $1; }
        |       expr '?' expr ':' expr
-                       { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, $3, $5); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_CONDITIONAL, $1, $3, $5); }
        |       expr '?' ':' expr
-                       { $$ = zend_ast_create(ZEND_AST_CONDITIONAL, $1, NULL, $4); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_CONDITIONAL, $1, NULL, $4); }
        |       expr T_COALESCE expr
-                       { $$ = zend_ast_create(ZEND_AST_COALESCE, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_COALESCE, $1, $3); }
        |       internal_functions_in_yacc { $$ = $1; }
-       |       T_INT_CAST expr         { $$ = zend_ast_create_cast(IS_LONG, $2); }
-       |       T_DOUBLE_CAST expr      { $$ = zend_ast_create_cast(IS_DOUBLE, $2); }
-       |       T_STRING_CAST expr      { $$ = zend_ast_create_cast(IS_STRING, $2); }
-       |       T_ARRAY_CAST expr       { $$ = zend_ast_create_cast(IS_ARRAY, $2); }
-       |       T_OBJECT_CAST expr      { $$ = zend_ast_create_cast(IS_OBJECT, $2); }
-       |       T_BOOL_CAST expr        { $$ = zend_ast_create_cast(_IS_BOOL, $2); }
-       |       T_UNSET_CAST expr       { $$ = zend_ast_create_cast(IS_NULL, $2); }
-       |       T_EXIT exit_expr        { $$ = zend_ast_create(ZEND_AST_EXIT, $2); }
-       |       '@' expr                        { $$ = zend_ast_create(ZEND_AST_SILENCE, $2); }
+       |       T_INT_CAST expr         { $$ = zend_ast_create_cast(&@$, IS_LONG, $2); }
+       |       T_DOUBLE_CAST expr      { $$ = zend_ast_create_cast(&@$, IS_DOUBLE, $2); }
+       |       T_STRING_CAST expr      { $$ = zend_ast_create_cast(&@$, IS_STRING, $2); }
+       |       T_ARRAY_CAST expr       { $$ = zend_ast_create_cast(&@$, IS_ARRAY, $2); }
+       |       T_OBJECT_CAST expr      { $$ = zend_ast_create_cast(&@$, IS_OBJECT, $2); }
+       |       T_BOOL_CAST expr        { $$ = zend_ast_create_cast(&@$, _IS_BOOL, $2); }
+       |       T_UNSET_CAST expr       { $$ = zend_ast_create_cast(&@$, IS_NULL, $2); }
+       |       T_EXIT exit_expr        { $$ = zend_ast_create(&@$, ZEND_AST_EXIT, $2); }
+       |       '@' expr                        { $$ = zend_ast_create(&@$, ZEND_AST_SILENCE, $2); }
        |       scalar { $$ = $1; }
-       |       '`' backticks_expr '`' { $$ = zend_ast_create(ZEND_AST_SHELL_EXEC, $2); }
-       |       T_PRINT expr { $$ = zend_ast_create(ZEND_AST_PRINT, $2); }
-       |       T_YIELD { $$ = zend_ast_create(ZEND_AST_YIELD, NULL, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
-       |       T_YIELD expr { $$ = zend_ast_create(ZEND_AST_YIELD, $2, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
-       |       T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(ZEND_AST_YIELD, $4, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
-       |       T_YIELD_FROM expr { $$ = zend_ast_create(ZEND_AST_YIELD_FROM, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
-       |       function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type
+       |       '`' backticks_expr '`' { $$ = zend_ast_create(&@$, ZEND_AST_SHELL_EXEC, $2); }
+       |       T_PRINT expr { $$ = zend_ast_create(&@$, ZEND_AST_PRINT, $2); }
+       |       T_YIELD { $$ = zend_ast_create(&@$, ZEND_AST_YIELD, NULL, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
+       |       T_YIELD expr { $$ = zend_ast_create(&@$, ZEND_AST_YIELD, $2, NULL); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
+       |       T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(&@$, ZEND_AST_YIELD, $4, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
+       |       T_YIELD_FROM expr { $$ = zend_ast_create(&@$, ZEND_AST_YIELD_FROM, $2); CG(extra_fn_flags) |= ZEND_ACC_GENERATOR; }
+       |       T_FUNCTION returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type
                backup_fn_flags '{' inner_statement_list '}' backup_fn_flags
-                       { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2 | $13, $1, $3,
+                       { $$ = zend_ast_create_decl(&@$, ZEND_AST_CLOSURE, $2 | $13, $3,
                                  zend_string_init("{closure}", sizeof("{closure}") - 1, 0),
                              $5, $7, $11, $8); CG(extra_fn_flags) = $9; }
-       |       T_STATIC function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars
+       |       T_STATIC T_FUNCTION returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars
                return_type backup_fn_flags '{' inner_statement_list '}' backup_fn_flags
-                       { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $3 | $14 | ZEND_ACC_STATIC, $2, $4,
+                       { $$ = zend_ast_create_decl(&@$, ZEND_AST_CLOSURE, $3 | $14 | ZEND_ACC_STATIC, $4,
                              zend_string_init("{closure}", sizeof("{closure}") - 1, 0),
                              $6, $8, $12, $9); CG(extra_fn_flags) = $10; }
 ;
 
-function:
-       T_FUNCTION { $$ = CG(zend_lineno); }
-;
-
 backup_doc_comment:
        /* empty */ { $$ = CG(doc_comment); CG(doc_comment) = NULL; }
 ;
@@ -1018,7 +1038,7 @@ lexical_vars:
 
 lexical_var_list:
                lexical_var_list ',' lexical_var { $$ = zend_ast_list_add($1, $3); }
-       |       lexical_var { $$ = zend_ast_create_list(1, ZEND_AST_CLOSURE_USES, $1); }
+       |       lexical_var { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_CLOSURE_USES, $1); }
 ;
 
 lexical_var:
@@ -1028,19 +1048,19 @@ lexical_var:
 
 function_call:
                name argument_list
-                       { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_CALL, $1, $2); }
        |       class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
-                       { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_STATIC_CALL, $1, $3, $4); }
        |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
-                       { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_STATIC_CALL, $1, $3, $4); }
        |       callable_expr argument_list
-                       { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_CALL, $1, $2); }
 ;
 
 class_name:
                T_STATIC
                        { zval zv; ZVAL_INTERNED_STR(&zv, ZSTR_KNOWN(ZEND_STR_STATIC));
-                         $$ = zend_ast_create_zval_ex(&zv, ZEND_NAME_NOT_FQ); }
+                         $$ = zend_ast_create_zval_ex(&@$, &zv, ZEND_NAME_NOT_FQ); }
        |       name { $$ = $1; }
 ;
 
@@ -1056,14 +1076,14 @@ exit_expr:
 
 backticks_expr:
                /* empty */
-                       { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); }
+                       { $$ = zend_ast_create_zval_from_str(&@$, ZSTR_EMPTY_ALLOC()); }
        |       T_ENCAPSED_AND_WHITESPACE { $$ = $1; }
        |       encaps_list { $$ = $1; }
 ;
 
 
 ctor_arguments:
-               /* empty */     { $$ = zend_ast_create_list(0, ZEND_AST_ARG_LIST); }
+               /* empty */     { $$ = zend_ast_create_list(&@$, 0, ZEND_AST_ARG_LIST); }
        |       argument_list { $$ = $1; }
 ;
 
@@ -1077,17 +1097,17 @@ dereferencable_scalar:
 scalar:
                T_LNUMBER       { $$ = $1; }
        |       T_DNUMBER       { $$ = $1; }
-       |       T_LINE          { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_LINE); }
-       |       T_FILE          { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_FILE); }
-       |       T_DIR           { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_DIR); }
-       |       T_TRAIT_C       { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_TRAIT_C); }
-       |       T_METHOD_C      { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_METHOD_C); }
-       |       T_FUNC_C        { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_FUNC_C); }
-       |       T_NS_C          { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_NS_C); }
-       |       T_CLASS_C       { $$ = zend_ast_create_ex(ZEND_AST_MAGIC_CONST, T_CLASS_C); }
+       |       T_LINE          { $$ = zend_ast_create_ex(&@$, ZEND_AST_MAGIC_CONST, T_LINE); }
+       |       T_FILE          { $$ = zend_ast_create_ex(&@$, ZEND_AST_MAGIC_CONST, T_FILE); }
+       |       T_DIR           { $$ = zend_ast_create_ex(&@$, ZEND_AST_MAGIC_CONST, T_DIR); }
+       |       T_TRAIT_C       { $$ = zend_ast_create_ex(&@$, ZEND_AST_MAGIC_CONST, T_TRAIT_C); }
+       |       T_METHOD_C      { $$ = zend_ast_create_ex(&@$, ZEND_AST_MAGIC_CONST, T_METHOD_C); }
+       |       T_FUNC_C        { $$ = zend_ast_create_ex(&@$, ZEND_AST_MAGIC_CONST, T_FUNC_C); }
+       |       T_NS_C          { $$ = zend_ast_create_ex(&@$, ZEND_AST_MAGIC_CONST, T_NS_C); }
+       |       T_CLASS_C       { $$ = zend_ast_create_ex(&@$, ZEND_AST_MAGIC_CONST, T_CLASS_C); }
        |       T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; }
        |       T_START_HEREDOC T_END_HEREDOC
-                       { $$ = zend_ast_create_zval_from_str(ZSTR_EMPTY_ALLOC()); }
+                       { $$ = zend_ast_create_zval_from_str(&@$, ZSTR_EMPTY_ALLOC()); }
        |       '"' encaps_list '"'     { $$ = $2; }
        |       T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; }
        |       dereferencable_scalar   { $$ = $1; }
@@ -1095,11 +1115,11 @@ scalar:
 ;
 
 constant:
-               name { $$ = zend_ast_create(ZEND_AST_CONST, $1); }
+               name { $$ = zend_ast_create(&@$, ZEND_AST_CONST, $1); }
        |       class_name T_PAAMAYIM_NEKUDOTAYIM identifier
-                       { $$ = zend_ast_create_class_const_or_name($1, $3); }
+                       { $$ = zend_ast_create_class_const_or_name(&@$, $1, $3); }
        |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM identifier
-                       { $$ = zend_ast_create_class_const_or_name($1, $3); }
+                       { $$ = zend_ast_create_class_const_or_name(&@$, $1, $3); }
 ;
 
 optional_expr:
@@ -1125,15 +1145,15 @@ callable_expr:
 
 callable_variable:
                simple_variable
-                       { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $1); }
        |       dereferencable '[' optional_expr ']'
-                       { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DIM, $1, $3); }
        |       constant '[' optional_expr ']'
-                       { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DIM, $1, $3); }
        |       dereferencable '{' expr '}'
-                       { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DIM, $1, $3); }
        |       dereferencable T_OBJECT_OPERATOR property_name argument_list
-                       { $$ = zend_ast_create(ZEND_AST_METHOD_CALL, $1, $3, $4); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_METHOD_CALL, $1, $3, $4); }
        |       function_call { $$ = $1; }
 ;
 
@@ -1143,47 +1163,47 @@ variable:
        |       static_member
                        { $$ = $1; }
        |       dereferencable T_OBJECT_OPERATOR property_name
-                       { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_PROP, $1, $3); }
 ;
 
 simple_variable:
                T_VARIABLE                      { $$ = $1; }
        |       '$' '{' expr '}'        { $$ = $3; }
-       |       '$' simple_variable     { $$ = zend_ast_create(ZEND_AST_VAR, $2); }
+       |       '$' simple_variable     { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $2); }
 ;
 
 static_member:
                class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
-                       { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_STATIC_PROP, $1, $3); }
        |       variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
-                       { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_STATIC_PROP, $1, $3); }
 ;
 
 new_variable:
                simple_variable
-                       { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $1); }
        |       new_variable '[' optional_expr ']'
-                       { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DIM, $1, $3); }
        |       new_variable '{' expr '}'
-                       { $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DIM, $1, $3); }
        |       new_variable T_OBJECT_OPERATOR property_name
-                       { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_PROP, $1, $3); }
        |       class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
-                       { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_STATIC_PROP, $1, $3); }
        |       new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable
-                       { $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_STATIC_PROP, $1, $3); }
 ;
 
 member_name:
                identifier { $$ = $1; }
        |       '{' expr '}'    { $$ = $2; }
-       |       simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+       |       simple_variable { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $1); }
 ;
 
 property_name:
                T_STRING { $$ = $1; }
        |       '{' expr '}'    { $$ = $2; }
-       |       simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+       |       simple_variable { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $1); }
 ;
 
 array_pair_list:
@@ -1200,24 +1220,24 @@ non_empty_array_pair_list:
                non_empty_array_pair_list ',' possible_array_pair
                        { $$ = zend_ast_list_add($1, $3); }
        |       possible_array_pair
-                       { $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, $1); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_ARRAY, $1); }
 ;
 
 array_pair:
                expr T_DOUBLE_ARROW expr
-                       { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_ARRAY_ELEM, $3, $1); }
        |       expr
-                       { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $1, NULL); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_ARRAY_ELEM, $1, NULL); }
        |       expr T_DOUBLE_ARROW '&' variable
-                       { $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $4, $1); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_ARRAY_ELEM, 1, $4, $1); }
        |       '&' variable
-                       { $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $2, NULL); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_ARRAY_ELEM, 1, $2, NULL); }
        |       expr T_DOUBLE_ARROW T_LIST '(' array_pair_list ')'
                        { $5->attr = ZEND_ARRAY_SYNTAX_LIST;
-                         $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $5, $1); }
+                         $$ = zend_ast_create(&@$, ZEND_AST_ARRAY_ELEM, $5, $1); }
        |       T_LIST '(' array_pair_list ')'
                        { $3->attr = ZEND_ARRAY_SYNTAX_LIST;
-                         $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, NULL); }
+                         $$ = zend_ast_create(&@$, ZEND_AST_ARRAY_ELEM, $3, NULL); }
 ;
 
 encaps_list:
@@ -1226,27 +1246,27 @@ encaps_list:
        |       encaps_list T_ENCAPSED_AND_WHITESPACE
                        { $$ = zend_ast_list_add($1, $2); }
        |       encaps_var
-                       { $$ = zend_ast_create_list(1, ZEND_AST_ENCAPS_LIST, $1); }
+                       { $$ = zend_ast_create_list(&@$, 1, ZEND_AST_ENCAPS_LIST, $1); }
        |       T_ENCAPSED_AND_WHITESPACE encaps_var
-                       { $$ = zend_ast_create_list(2, ZEND_AST_ENCAPS_LIST, $1, $2); }
+                       { $$ = zend_ast_create_list(&@$, 2, ZEND_AST_ENCAPS_LIST, $1, $2); }
 ;
 
 encaps_var:
                T_VARIABLE
-                       { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $1); }
        |       T_VARIABLE '[' encaps_var_offset ']'
-                       { $$ = zend_ast_create(ZEND_AST_DIM,
-                             zend_ast_create(ZEND_AST_VAR, $1), $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DIM,
+                             zend_ast_create(&@1, ZEND_AST_VAR, $1), $3); }
        |       T_VARIABLE T_OBJECT_OPERATOR T_STRING
-                       { $$ = zend_ast_create(ZEND_AST_PROP,
-                             zend_ast_create(ZEND_AST_VAR, $1), $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_PROP,
+                             zend_ast_create(&@1, ZEND_AST_VAR, $1), $3); }
        |       T_DOLLAR_OPEN_CURLY_BRACES expr '}'
-                       { $$ = zend_ast_create(ZEND_AST_VAR, $2); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $2); }
        |       T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}'
-                       { $$ = zend_ast_create(ZEND_AST_VAR, $2); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $2); }
        |       T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
-                       { $$ = zend_ast_create(ZEND_AST_DIM,
-                             zend_ast_create(ZEND_AST_VAR, $2), $4); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_DIM,
+                             zend_ast_create(&@2, ZEND_AST_VAR, $2), $4); }
        |       T_CURLY_OPEN variable '}' { $$ = $2; }
 ;
 
@@ -1254,33 +1274,33 @@ encaps_var_offset:
                T_STRING                        { $$ = $1; }
        |       T_NUM_STRING            { $$ = $1; }
        |       '-' T_NUM_STRING        { $$ = zend_negate_num_string($2); }
-       |       T_VARIABLE                      { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+       |       T_VARIABLE                      { $$ = zend_ast_create(&@$, ZEND_AST_VAR, $1); }
 ;
 
 
 internal_functions_in_yacc:
                T_ISSET '(' isset_variables possible_comma ')' { $$ = $3; }
-       |       T_EMPTY '(' expr ')' { $$ = zend_ast_create(ZEND_AST_EMPTY, $3); }
+       |       T_EMPTY '(' expr ')' { $$ = zend_ast_create(&@$, ZEND_AST_EMPTY, $3); }
        |       T_INCLUDE expr
-                       { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2); }
        |       T_INCLUDE_ONCE expr
-                       { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2); }
        |       T_EVAL '(' expr ')'
-                       { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, $3); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, $3); }
        |       T_REQUIRE expr
-                       { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2); }
        |       T_REQUIRE_ONCE expr
-                       { $$ = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2); }
+                       { $$ = zend_ast_create_ex(&@$, ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2); }
 ;
 
 isset_variables:
                isset_variable { $$ = $1; }
        |       isset_variables ',' isset_variable
-                       { $$ = zend_ast_create(ZEND_AST_AND, $1, $3); }
+                       { $$ = zend_ast_create(&@$, ZEND_AST_AND, $1, $3); }
 ;
 
 isset_variable:
-               expr { $$ = zend_ast_create(ZEND_AST_ISSET, $1); }
+               expr { $$ = zend_ast_create(&@$, ZEND_AST_ISSET, $1); }
 ;
 
 %%
index b1e25ebae51b3b2ea18bbeaa236e79571b68d7e3..05f5ee226dfe406a1266967611fc9415fd4aaf6c 100644 (file)
@@ -567,7 +567,6 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle)
        }
 
        RESET_DOC_COMMENT();
-       CG(increment_lineno) = 0;
        return SUCCESS;
 }
 END_EXTERN_C()
@@ -720,7 +719,6 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename)
        zend_set_compiled_filename(new_compiled_filename);
        zend_string_release_ex(new_compiled_filename, 0);
        CG(zend_lineno) = 1;
-       CG(increment_lineno) = 0;
        RESET_DOC_COMMENT();
        return SUCCESS;
 }
@@ -1233,7 +1231,7 @@ static void copy_heredoc_label_stack(void *void_heredoc_label)
                goto skip_token; \
        } while (0)
 
-int ZEND_FASTCALL lex_scan(zval *zendlval, zend_parser_stack_elem *elem)
+int ZEND_FASTCALL lex_scan(zval *zendlval, zend_parser_stack_elem *elem, zend_ast_loc *loc)
 {
 int token;
 int offset;
@@ -2126,7 +2124,7 @@ inline_char_handler:
 <ST_IN_SCRIPTING>"?>"{NEWLINE}? {
        BEGIN(INITIAL);
        if (yytext[yyleng-1] != '>') {
-               CG(increment_lineno) = 1;
+               CG(zend_lineno)++;
        }
        if (PARSER_MODE()) {
                RETURN_TOKEN(';');  /* implicit ';' at php-end tag */
@@ -2363,9 +2361,10 @@ skip_escape_conversion:
                while (heredoc_nesting_level) {
                        zval zv;
                        int retval;
+                       zend_ast_loc loc;
 
                        ZVAL_UNDEF(&zv);
-                       retval = lex_scan(&zv, NULL);
+                       retval = lex_scan(&zv, NULL, &loc);
                        zval_ptr_dtor_nogc(&zv);
 
                        if (EG(exception)) {
@@ -2403,7 +2402,6 @@ skip_escape_conversion:
 
                zend_restore_lexical_state(&current_state);
                SCNG(heredoc_scan_ahead) = 0;
-               CG(increment_lineno) = 0;
        }
 
        RETURN_TOKEN(T_START_HEREDOC);
@@ -2603,8 +2601,6 @@ double_quotes_scan_done:
                                                newline = 1;
                                        }
 
-                                       CG(increment_lineno) = 1; /* For newline before label */
-
                                        if (SCNG(heredoc_scan_ahead)) {
                                                SCNG(heredoc_indentation) = indentation;
                                                SCNG(heredoc_indentation_uses_spaces) = (spacing == HEREDOC_USING_SPACES);
@@ -2665,6 +2661,9 @@ heredoc_scan_done:
                HANDLE_NEWLINES(yytext, yyleng - newline);
        }
 
+       if (newline) {
+               CG(zend_lineno)++;
+       }
        RETURN_TOKEN_WITH_VAL(T_ENCAPSED_AND_WHITESPACE);
 }
 
@@ -2724,8 +2723,6 @@ heredoc_scan_done:
                                                newline = 1;
                                        }
 
-                                       CG(increment_lineno) = 1; /* For newline before label */
-
                                        YYCURSOR -= indentation;
                                        heredoc_label->indentation = indentation;
 
@@ -2753,6 +2750,9 @@ nowdoc_scan_done:
        }
 
        HANDLE_NEWLINES(yytext, yyleng - newline);
+       if (newline) {
+               CG(zend_lineno)++;
+       }
        RETURN_TOKEN_WITH_VAL(T_ENCAPSED_AND_WHITESPACE);
 }
 
@@ -2774,13 +2774,15 @@ emit_token_with_str:
 emit_token_with_val:
        if (PARSER_MODE()) {
                ZEND_ASSERT(Z_TYPE_P(zendlval) != IS_UNDEF);
-               elem->ast = zend_ast_create_zval_with_lineno(zendlval, start_line);
+               loc->start_line = start_line;
+               elem->ast = zend_ast_create_zval(loc, zendlval);
        }
 
 emit_token:
        if (SCNG(on_event)) {
                SCNG(on_event)(ON_TOKEN, token, start_line, SCNG(on_event_context));
        }
+       loc->start_line = start_line;
        return token;
 
 return_whitespace:
@@ -2792,6 +2794,7 @@ return_whitespace:
                start_line = CG(zend_lineno);
                goto restart;
        } else {
+               loc->start_line = start_line;
                return T_WHITESPACE;
        }
 
index 91ace6f701770235c728332403b6e19d90cfb8a1..6d671f47e35f4413ab20757e79ad174c8dada3bf 100644 (file)
@@ -127,8 +127,8 @@ static zend_bool tokenize(zval *return_value, zend_string *source)
        zval source_zval;
        zend_lex_state original_lex_state;
        zval token;
+       zend_ast_loc loc;
        int token_type;
-       int token_line = 1;
        int need_tokens = -1; /* for __halt_compiler lexing. -1 = disabled */
 
        ZVAL_STR_COPY(&source_zval, source);
@@ -142,8 +142,8 @@ static zend_bool tokenize(zval *return_value, zend_string *source)
        LANG_SCNG(yy_state) = yycINITIAL;
        array_init(return_value);
 
-       while ((token_type = lex_scan(&token, NULL))) {
-               add_token(return_value, token_type, zendtext, zendleng, token_line);
+       while ((token_type = lex_scan(&token, NULL, &loc))) {
+               add_token(return_value, token_type, zendtext, zendleng, loc.start_line);
 
                if (Z_TYPE(token) != IS_UNDEF) {
                        zval_ptr_dtor_nogc(&token);
@@ -159,20 +159,13 @@ static zend_bool tokenize(zval *return_value, zend_string *source)
                                /* fetch the rest into a T_INLINE_HTML */
                                if (zendcursor != zendlimit) {
                                        add_token(return_value, T_INLINE_HTML,
-                                               zendcursor, zendlimit - zendcursor, token_line);
+                                               zendcursor, zendlimit - zendcursor, loc.start_line);
                                }
                                break;
                        }
                } else if (token_type == T_HALT_COMPILER) {
                        need_tokens = 3;
                }
-
-               if (CG(increment_lineno)) {
-                       CG(zend_lineno)++;
-                       CG(increment_lineno) = 0;
-               }
-
-               token_line = CG(zend_lineno);
        }
 
        zval_ptr_dtor_str(&source_zval);