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;