PHP-Zend引擎剖析之词法分析(一)

前言

闲来研究一下PHP底层的Zend引擎源码,Zend引擎是PHP脚本的虚拟机。
在PHP上层有SAPI接口,负责对各个接入层的抽象,例如PHP在Apache模块里边的实现,Fast-CGI的实现,命令行的实现。在PHP底层便是Zend虚拟机,Zend虚拟机负责解析PHP语法的文件,上层可以在虚拟机中注册函数/变量提供给虚拟机调用,例如从Apache分发过来的HTTP请求经过PHP的Apache SAPI接口后,便会注册一些$_COOKIE、$_GET等全局变量,而在命令行模式下便没有这些跟HTTP相关的全局变量。
Zend引擎跟其他编译器跟解释器一样,会经历词法分析/语法分析,语法分析后会生成op code,也就是PHP的中间代码,最终Zend虚拟机执行的是op code。第一篇贡献给Zend引擎的理当是词法分析的源码剖析。
PS:分析的代码是PHP-5.5.5的源码包,下载地址: http://windows.php.net/downloads/releases/php-5.5.5-src.zip

词法分析

词法分析阶段就是从输入流里边一个字符一个字符的扫描,识别出对应的词素,最后把源文件转换成为一个TOKEN序列,然后丢给语法分析器。
从词法分析阶段中,词法分析器也能检测到源代码里边的一些错误。例如在Zend引擎的词法分析阶段就有这样一段代码:

          zend_error(E_COMPILE_WARNING, "Unterminated comment starting line %d", CG(zend_lineno));

当检测到/*开头,但是没有*/结尾时,Zend引擎会抛出一个Waring提示,但是并不影响接下来的词法解析,词法分析阶段一般都不会造成严重的解析错误,因为词法分析阶段的职责就是识别出Token序列而已,它并不需要知道Token跟Token之间是否具备什么联系(那个应该是语法分析阶段的职责)。在Zend引擎的词法分析器中也会抛出致命的解析错误而终止词法分析阶段,如下代码:

           zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
                                   "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));

这个解析错误是因为从输入流里边检测到的代码的编码不合法,显然,这里是应该终止掉整个解析过程的。
Zend引擎的词法分析器re2c来生成,词法分析的阶段会涉及到各个状态,其变量命名均为yy开头(下文会说明)。

源码高亮

我找了一个清晰的流程来分析怎么进入到词法分析阶段的。
我们以命令行的PHP为入口来研究一下,以HelloWorld的例子来看,我们在命令行执行:php -s HelloWorld.php,结果如下:
php -s是高亮源代码的命令,所谓高亮源代码其实就是对词素进行一个颜色高亮,我们通过入口文件分析到在$PHPSRC/sapi/cli/php_cli.c中的do_cli函数里边接收了命令行的参数输入。
-s的输入对应的是高亮源码。
紧接着,便是调用了Zend引擎的代码高亮的函数:zend_highlight。
$PHPSRC/Zend/zend_highlight.c中,我们找到了zend_highlight的定义,zend_highlight()调用的就是词法分析器lex_scan来获取Token,然后加入对应的颜色。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值