本章主要讲了词法与语法分析,我们讲了词法分析的基本原理呢,就是用正则表达式来处理字符串,这个是一个知识点,那么用正则表达式去处理字符串的方式呢,有一种方式叫状态机,我们讲了NFA和DFA分别都可以用来处理正则表达式,但是NFA有一定的缺陷,会导致状态流转停滞一个状态,而DFA很好地解决这个问题,但DFA,每次为一个正则表达式去编写那么一个DFA的话是不太现实的,所以有一个很好的工具叫RE2C,可以帮我们自动生成这么一个DFA,这是第2个知识点。我们通过RE2C可以生成DFA来做词法分析。
第3个知识点是语法分析,语法是可以递归的用巴科斯范式来表示,我们也有一种工具叫bison,可以帮你把巴科斯范式生成状态机 ,这是第3个知识点,在PHP里边呢,用到了RE2C和bison分别写了zend_language_scaner.L和zend_language_parse.c分别写了token,对应的token词法解释部分,还有巴科斯范式用来做语法解释,这部分的相关内容呢,我也会写在慕课网的首页里面,让大家进一步去查看,词法和语法分析,总共这么4个知识点。
接下来呢,我们又讲解了抽象语法树,词法语法分析最终带来的结果就是抽象语法树 ,抽象语法树里面我们有这么几个知识点。
第1抽象语法树在PHP里面实现了几个数据结构,分别是zend_ast和zend_ast_list、zend_ast_zval,这些基本结构呢,是根据kind来区分它的子女个数,其中一个知识点呢是对于zend_ast_list,它会由一个chidlren的数目来确定子女的个数,像其他的比如说他的kind呢是zend_ast_asign的话,它一定有两个子女,对于zend_ast_zval这种的是叶子节点,他就是对应的里边有一个zval结构的val,可以存储我们的基本变量,这是抽象语法树。我们通过分析$a=1,简历一个比较简单的抽象语法树。
接下来的一个知识点是我们将这个AST通过递归遍历的方式将它变成了指令集。指令集里面有哪些内容呢,第一比较重要的内容是handler op1 op2 result 以及op1 op2和result的类型,它比较像汇编,当我们执行一条指令的时候,就是对op1 op2进行handler操作 结果保存在result中。在对AST编译过程中呢,我们就会确定每个op1 op2 和result 执行的位置,在什么上面执行的位置呢,在zend的虚拟的堆栈上面,zend虚拟机的zend_vm_stack上边的具体位置,那AST通过遍历完以后呢,只是计算好op1 op2以及result,还需要通过一个重要的函数pass_two去将handler跟opcode对应起来,这样呢就完成了指令集的生成,这就是AST的编译。
接下来比较重要的点就是zend虚拟机的基本原理和zend虚拟上边的指令集执行过程。zend虚拟机是在硬件机器上边建立的一层软件虚拟机,它核心的三个点就是,执行命令集、符号表和执行堆栈。我们知道这里面有个非常重要的点就是执行堆栈的起始位置前80个字节是用来存放zend_execute_data的,当前执行的一些数据,我们所有的压栈操作的,比如op1都是从80这个位置往下进行,比如说以$a=1为例,我们op1的位置呢就是$a的存放的位置,而$a里面的a是存在了我们的符号表的hashtable里面,hashtable里边的key就是a,value就是指向我们op1在堆栈上的位置,当我们进行asign操作的时候,就是把一个常量的1赋值给了对应的op1的位置,这时候符号表指向的位置,我们可以去用op1的位置做其他操作,这就是zend虚拟机的执行原理