PHP 7.3.30 的 AST 构建严格遵循词法分析→语法分析→AST生成三阶段流程,由 Zend 引擎驱动,使用 Re2c 和 Bison 实现;词法分析切分源码为 Token,语法分析依 BNF 规则归约为 zend_ast 结构,最终转换为 opcode。

PHP 7.3.30 的语法树(即抽象语法树,AST)构建过程严格遵循其内核中词法分析 → 语法分析 → AST 生成的三阶段流程,核心由 Zend 引擎驱动,依赖 Re2c 和 Bison 工具链实现。该版本属于 PHP 7 系列稳定分支,AST 是自 PHP 7.0 起引入的关键中间表示,取代了旧版直接生成 opcode 的方式,显著提升了优化与静态分析能力。
词法分析:源码切分为 Token
解析器逐字符扫描 PHP 源文件,依据预定义的正则规则(由 re2c 生成的确定性有限自动机 DFA)识别出有意义的词法单元(Token)。例如:
-
$name→T_VARIABLE -
=→T_ASSIGN -
"hello"→T_CONSTANT_ENCAPSED_STRING -
function→T_FUNCTION -
;→T_SEMICOLON
这些 Token 构成线性序列,可通过token_get_all()函数在用户态观察,但此时尚无结构关系。
语法分析:按 BNF 规则组装 Token 成树
Bison 生成的 LALR(1) 语法分析器读取 Token 流,对照 Zend 内核中定义的上下文无关文法(如 statement_list → statement_list statement | statement),进行移进-归约操作。关键点包括:
- 每个语法规则对应一个 AST 节点类型(如
ZEND_AST_ASSIGN,ZEND_AST_ECHO,ZEND_AST_FUNC_DECL) - 归约时动态分配
zend_ast结构体,填充kind、flags、子节点指针数组child[] - 作用域信息(如变量名绑定、函数嵌套)在此阶段初步标记,但不执行语义检查
例如 <?php $a = 1 + 2; ?> 会被归约为:
ZEND_AST_STMT_LIST
└── ZEND_AST_ASSIGN
├── ZEND_AST_VAR → $a
└── ZEND_AST_BINARY_OP (ADD)
├── ZEND_AST_ZVAL → 1
└── ZEND_AST_ZVAL → 2AST 节点生成与内存管理
- 所有 AST 节点统一通过
emalloc()在请求内存池中分配,生命周期与当前 PHP 请求绑定 - 节点类型定义在
Zend/zend_ast.h中,含ZEND_AST_*常量和zend_ast_decl、zend_ast_zval等专用结构 - 复合节点(如函数定义)包含
doc_comment字段,支持 PHPDoc 提取;控制结构(如if)节点携带ZEND_AST_IF及其cond,stmts,else_stmts子树 - AST 构建完成后暂存于编译器全局结构
zend_op_array->ast,供后续编译阶段消费
AST 到 opcode 的转换
AST 并非最终执行形式。zend_compile.c 中的 zend_compile_top_stmt() 等函数遍历 AST,为每个节点生成对应 opcode 指令(如 ZEND_ASSIGN, ZEND_ADD, ZEND_ECHO),并填入 op_array->opcodes[] 数组。此过程完成符号解析(如变量作用域查表)、常量折叠、简单死代码消除等轻量优化。
整个流程不依赖外部库,完全在 Zend 引擎内部闭环完成,确保解析一致性与性能可控。
立即学习“PHP免费学习笔记(深入)”;



















