PHP_CodeSniffer是一个用来检查PHP代码规范的开源项目。它主要通过词法分析的方式将PHP源码解析成TOKEN数组,然后在TOKEN中标记出不符合代码规范的代码位置。
今天,我们就一起来探究一下PHP_CodeSniffer的代码静态分析的原理。但在开始之前,需要先科普一些知识,便于后续的理解。
目前编程语言可以分为两大类:
第一类是像C/C++, .NET, Java之类的编译型语言, 它们的共性是: 运行之前必须对源代码进行编译,然后运行编译后的目标文件。
以Java举例,第一类编译的过程都是先进行词法分析、语法分析,然后才是编译。在经过语法分析之后,有一个抽象语法树(AST)的概念,算是语法分析的产出,之后的编译过程是编译器在AST基础上进行的。
第二类比如:PHP, Javascript, Ruby, Python这些解释型语言, 他们都无需经过编译即可”运行”,虽然可以理解为直接运行,但它们并不是真的直接就被能被机器理解, 机器只能理解机器语言,那这些语言是怎么被执行的呢, 一般这些语言都需要一个解释器, 由解释器来执行这些源码, 实际上这些语言还是会经过编译环节, 只不过它们一般会在运行的时候实时进行编译。
以PHP举例,PHP的运行过程是怎样的呢?
传递给php程序需要执行的文件, php程序完成基本的准备工作后启动PHP及Zend引擎, 加载注册的扩展模块。
初始化完成后读取脚本文件,Zend引擎对脚本文件进行词法分析,语法分析。然后编译成opcode执行。 如果安装了apc之类的opcode缓存, 编译环节可能会被跳过而直接从缓存中读取opcode执行。
TOKEN
在文章开头,我们已经知道PHP_CodeSniffer的主要原理是将PHP源码解析成TOKEN数组,同时在PHP_CodeSniffer源码中,很多操作的核心就围绕着TOKEN展开。
那么问题来了,TOKEN是什么?
PHP词法解析器在解析PHP语言的过程中,PHP 语言的不同部分在内部被表示为类似T_XXX 的类型,这个T_XXX的类型就叫TOKEN,也叫标识符~
标识符部分列表:
PHP官网共119个标识符
在PHP中提供了token_get_all(string $source)方法解析提供的 source 源码字符,然后使用 Zend引擎的词法分析器获取源码中的 PHP 语言的TOKEN代号,就是上文中的T_XXX。TOKEN代号都有对应的唯一值,比如T_ABSTRACT对应的是312,是之前定义好的。你也可以使用PHP自带的token_name(312)方法获取TOKEN代号,示例代码如下:
我们现在已经了解了PHP源码通过词法解析器解析后会变成TOKEN形态,但是这个词法解析的详细过程是怎样的呢?
PHP词法分析
在了解了TOKEN之后,就得详细了解一下词法分析了。词法分析就是从输入流里边一个字符一个字符的扫描,识别出对应的词素,最后把源文件转换成为一个TOKEN序列。以最简单的一行代码举例词法分析的流程:
在Zend引擎中,当扫描到”
我们已经进入了PHP脚本解析的状态了。在词法解析器扫描字符的过程中,需要记录扫描过程的各
个参数以及当前状态,这些变量都是以yy开头命名。常用到的就是:yy_state, yy_text, yyleng,
yy_cursor, yy_limit。
扫描 echo 前:
扫描 echo 后:
通过一个字符一个字符的扫描最终会得到一个TOKEN序列。我们来使用上文提到的PHP自带的 token_get_all() 方法来进行词法分析,查看这个TOKEN序列:
运行该文件后,输出结果:
从结果中看出序列里每一个TOKEN也是一个数组。在每个TOKEN数组中,第一个索引是TOKEN的唯一值,第二个索引默认是对应的代码,如果TOKEN不存在对应代码,那么代表所在行数的第三个索引会自动挪到第二个索引位置。我们继续来探究第一个索引的唯一值,通过token_name()方法来查看对应的TOKEN代号。
输出为:
结合这个TOKEN代号对应的语法以及TOKEN序列的输出,我们就能理解刚才那行代码词法分析后的TOKEN序列内容,并且能根据序列内容还原源代码。所以,只要有词法分析后的TOKEN序列内容,我们就可以结合我们自己的需求,在TOKEN序列内容的基础上进行PHP_CodeSniffer规则的定制。敬请关注下篇文章,结合原理教你如何自定义规则。
参考文章:
深入理解PHP内核:
http://www.php-internals.com/book/?p=chapt01/01-02-code-structure
PHPZend引擎剖析:
https://blog.csdn.net/raphealguo/article/details/16941531
Qtest是360旗下的专业测试团队!
是WEB平台部测试技术平台化、效率化的先锋力量!
领取专属 10元无门槛券
私享最新 技术干货