baiyanphp
所有视频:https://segmentfault.com/a/11...node
原视频地址:http://replay.xesv5.com/ll/24...segmentfault
拓展:对于树的中序遍历,有递归与非递归两种方式:数组
非递归中序遍历:借助栈数据结构
- 碰到等号压栈,而后往左子树走 - 将a压栈,a没有左右子树,a出栈(a) - 等号出栈(a =) - 将它的右子树加号压栈 - 加号有左子树,将b压栈 - b没有左右子树,b出栈(a = b) - 加号出栈(a = b +) - 加号有右子树c,将c压栈 - c没有左右子树,c出栈(a = b + c)
struct Tree { char type //结点类型,表示是运算符仍是操做数 Tree *left //左孩子 Tree *right //右孩子 }
struct Tree { char type //结点类型,表示是运算符仍是操做数 int children //有多少个孩子 Tree child[] //用一个数组存储全部孩子 }
struct _zend_ast { zend_ast_kind kind; /* 结点类型,至关于咱们上面的type */ zend_ast_attr attr; /* 先忽略 */ uint32_t lineno; /* 行号(进行语法分析的时候须要记录代码所在行号) */ zend_ast *child[1]; /* 柔性数组,存储孩子结点*/ };
typedef uint16_t zend_ast_kind;
enum _zend_ast_kind { /* special nodes 特殊类型结点*/ ZEND_AST_ZVAL = 1 << ZEND_AST_SPECIAL_SHIFT, (1 << 6 = 64) ZEND_AST_ZNODE, (65) /* declaration nodes 定义类型结点*/ ZEND_AST_FUNC_DECL, ZEND_AST_CLOSURE, ZEND_AST_METHOD, ZEND_AST_CLASS, /* list nodes LIST类型结点*/ ZEND_AST_ARG_LIST = 1 << ZEND_AST_IS_LIST_SHIFT,(1 << 7 = 128) ZEND_AST_ARRAY, ZEND_AST_ENCAPS_LIST, ZEND_AST_EXPR_LIST, ZEND_AST_STMT_LIST, ZEND_AST_IF, ZEND_AST_SWITCH_LIST, ZEND_AST_CATCH_LIST, ZEND_AST_PARAM_LIST, ZEND_AST_CLOSURE_USES, ZEND_AST_PROP_DECL, ZEND_AST_CONST_DECL, ZEND_AST_CLASS_CONST_DECL, ZEND_AST_NAME_LIST, ZEND_AST_TRAIT_ADAPTATIONS, ZEND_AST_USE, /* 0 child nodes 0个孩子结点*/ ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT,(0 << 8 = 0) ZEND_AST_TYPE, /* 1 child node 1个孩子结点*/ ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT,(1 << 8 = 256) ZEND_AST_CONST, ZEND_AST_UNPACK, ZEND_AST_UNARY_PLUS, ZEND_AST_UNARY_MINUS, ZEND_AST_CAST, ZEND_AST_EMPTY, ZEND_AST_ISSET, ZEND_AST_SILENCE, ZEND_AST_SHELL_EXEC, ZEND_AST_CLONE, ZEND_AST_EXIT, ZEND_AST_PRINT, ZEND_AST_INCLUDE_OR_EVAL, ZEND_AST_UNARY_OP, ZEND_AST_PRE_INC, ZEND_AST_PRE_DEC, ZEND_AST_POST_INC, ZEND_AST_POST_DEC, ZEND_AST_YIELD_FROM, ZEND_AST_GLOBAL, ZEND_AST_UNSET, ZEND_AST_RETURN, ZEND_AST_LABEL, ZEND_AST_REF, ZEND_AST_HALT_COMPILER, ZEND_AST_ECHO, ZEND_AST_THROW, ZEND_AST_GOTO, ZEND_AST_BREAK, ZEND_AST_CONTINUE, /* 2 child nodes 2个孩子结点*/ ZEND_AST_DIM = 2 << ZEND_AST_NUM_CHILDREN_SHIFT,(2 << 8 = 512) ZEND_AST_PROP, ZEND_AST_STATIC_PROP, ZEND_AST_CALL, ZEND_AST_CLASS_CONST, ZEND_AST_ASSIGN, ZEND_AST_ASSIGN_REF, ZEND_AST_ASSIGN_OP, ZEND_AST_BINARY_OP, ZEND_AST_GREATER, ZEND_AST_GREATER_EQUAL, ZEND_AST_AND, ZEND_AST_OR, ZEND_AST_ARRAY_ELEM, ZEND_AST_NEW, ZEND_AST_INSTANCEOF, ZEND_AST_YIELD, ZEND_AST_COALESCE, ZEND_AST_STATIC, ZEND_AST_WHILE, ZEND_AST_DO_WHILE, ZEND_AST_IF_ELEM, ZEND_AST_SWITCH, ZEND_AST_SWITCH_CASE, ZEND_AST_DECLARE, ZEND_AST_USE_TRAIT, ZEND_AST_TRAIT_PRECEDENCE, ZEND_AST_METHOD_REFERENCE, ZEND_AST_NAMESPACE, ZEND_AST_USE_ELEM, ZEND_AST_TRAIT_ALIAS, ZEND_AST_GROUP_USE, /* 3 child nodes 3个孩子结点*/ ZEND_AST_METHOD_CALL = 3 << ZEND_AST_NUM_CHILDREN_SHIFT, ZEND_AST_STATIC_CALL, ZEND_AST_CONDITIONAL, ZEND_AST_TRY, ZEND_AST_CATCH, ZEND_AST_PARAM, ZEND_AST_PROP_ELEM, ZEND_AST_CONST_ELEM, /* 4 child nodes 4个孩子结点*/ ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT, ZEND_AST_FOREACH, };
/* Same as zend_ast, but with children count, which is updated dynamically */ /*与zend_ast结点的功能相同可是多了一个子结点的计数,它会被动态地更新*/ typedef struct _zend_ast_list { zend_ast_kind kind; zend_ast_attr attr; uint32_t lineno; uint32_t children; zend_ast *child[1]; } zend_ast_list;
/* Lineno is stored in val.u2.lineno */ /* Lineno 字段存储在zval中的 val.u2.lineno中 */ typedef struct _zend_ast_zval { zend_ast_kind kind; zend_ast_attr attr; zval val; } zend_ast_zval;
/* Separate structure for function and class declaration, as they need extra information. */ /* 为函数和类设计的特殊结构,它们须要额外的描述信息 */ typedef struct _zend_ast_decl { zend_ast_kind kind; zend_ast_attr attr; /* Unused - for structure compatibility */ uint32_t start_lineno; //类和函数是一个区间,因此记录开始行号和结束行号 uint32_t end_lineno; uint32_t flags; unsigned char *lex_pos; zend_string *doc_comment; zend_string *name; zend_ast *child[4]; } zend_ast_decl;
<?php $a = 1; $b = $a + 2;
<?php $a = (1+2)*3;