您的位置:首页 > 编程语言 > PHP开发

php手册中的tokenizer详细总结,基本看它就够了

2016-10-16 10:45 393 查看

tokenizer - 解析器

简介:

    tokenizer函数提供了一个内嵌在Zend引擎的"PHP tokenizer"的调用接口。使用这些函数,你可以写出你自己的PHP源码分析或者修改工具,而无需处理词法分析级别上的语言规范。

仅包含2个函数:

    token_get_all(string $source)

        1.token_get_all() 解析提供的 source 源码字符,然后使用 Zend 引擎的语法分析器获取源码中的 PHP 语言的解析器代号

        2.$source - 需要解析的php源码

        3.返回值:返回源码解析后的所有token标志符数组。

        4.每个单独的token标志符,有2种形式:

            1>单个字符,例如:: ; , .

            2>一个包含3个元素的数组,0-token索引(可调用token_name()来获取字面量) | 1-token源码字符串 | 2-行号

        5.实例:

       
$tokens = token_get_all('<?php echo "dongxuemin"; echo "zhangrui";?>');


        解析后:
Array
(
[0] => Array
(
[0] => 379
[1] =>  1
)

[1] => Array
(
[0] => 328
[1] => echo
[2] => 1
)

[2] => Array
(
[0] => 382
[1] =>
[2] => 1
)

[3] => Array
(
[0] => 323
[1] => "dongxuemin"
[2] => 1
)

[4] => ;
[5] => Array
(
[0] => 382
[1] =>
[2] => 1
)

[6] => Array
(
[0] => 328
[1] => echo
[2] => 1
)

[7] => Array
(
[0] => 382
[1] =>
[2] => 1
)

[8] => Array
(
[0] => 323
[1] => "zhangrui"
[2] => 1
)

[9] => ;
[10] => Array
(
[0] => 381
[1] => ?>
[2] => 1
)
)


    token_name(int $token)

        1.获取提供的 PHP 解析器代号的符号名称

        2.$token - 解析器代号的值。接收的是 token_get_all()解析出来的token数组中的第一个元素(token索引),是个int类型

        3.返回值:提供的token的符号名

        4.实例:

           
token_name(328);    // 返回 'T_OPEN_TAG'

解析器代号列表

    1.PHP 语言的不同部分在内部被表示为类似 T_SR 的类型。PHP 在解析错误时输出这样的标识符,例如 "Parse error: unexpected T_SR, expecting ',' or ';' in script.php on line 10."。

    2.应该知道 T_SR 的含义。对于所有不知道的人,下表列出了这些标识符,PHP 语法和在手册中适当位置的参考。

    3.注意:T_*常量的使用

        所有下面列出的token,也被定义为PHP常量。它们的值是基于PHP底层的解析器,自动生成的。这意味着:在两个不同的PHP版本间,同样的token代表的值可能不同。例如:T_FILE常量在PHP5.3是365,在PHP5.4就是369。这也意味着:你的代码绝对不能直接依赖具体某个PHP版本的原始 'T_*' token值,去提供PHP跨版本的兼容性(就是我们不能使用token值作为版本兼容,同一token的值不同版本可能是不同的)。相反你的代码应利用自定义的值 (使用大的数字,像 10000)和适当的策略,来实现
'T_*' 的值和PHP版本兼容性。(我们得将列表中所有的token的值,重新定义,而不采用系统的)

    4.不过这里有个疑问:常量的值不可重新定义,也不清楚具体该怎么做,使用变量?主要是不清楚需求...

    5.通过解析器代号列表,我们就可以查找我们通过 token_name() 获取到的 token名代表的内容。

        该列表,并没有列出token对应的int类型的值,就是因为上面讲的:值是自动生成的,不同版本相同的token是不同的值

上面几点,就是手册上涉及的几个重要概念,我们大概也了解到了,就是:解析php源代码,然后我们自己实现自己的逻辑,接下来,写几个实例(参照别人的博客,或其他地方资料):

    1.源码高亮展示,php自带的相关方法有 highlight_string(),highlight_file(),我顺便对这2个方法进行了查看,总结,可参照:
       
php的语法高亮函数,highlight_string和highlight_file(别名是:show_resource),以及highlight在php.ini中的配置

    2.压缩php代码,去除不要的换行、空白以及注释,转载别人的博客,可参照:
       
 


PHP Tokenizer 学习笔记

        有人指出了 'php_strip_whitespace' 可做相同的事情,就研究下这个函数,看了下手册,里面有个评论,也写了一个压缩php的代码,干脆再写篇文章了

PHP的php_strip_whitespace函数描述,以及手册中写的代码压缩函数-可看看函数是怎么实现的

    3.上面博客有人评论说:可做一个能列出某php文件所有函数名,和参数表,感觉这个想法不错,只要和源码相关的,我们都可以想着做

    4.在stackoverflow.com上查看了个类似的问题,有人回答,参照链接:
        tokenizer的一些实用实例:http://stackoverflow.com/questions/5727951/what-are-some-practical-uses-of-php-tokenizer
        1>有的框架用tokenizer生成缓存文件或中间class类文件
        2>源代码格式化、高亮显示
        3>可收集所有定义的class,methods,variables,文档,注释等
        4>一些安全检测等,保证代码更安全。不允许使用的php函数,反正各种安全检测。。。
        5>基本上,能使用php代码作为数据的任何地方,我们都可以使用tokennizer。它比使用正则表达式,或其他处理函数,来解析php代码都更可靠。
    5.如何在php文件中,查看是否定义了某个类?上面评论里的问题,挺有意思:
        1>当可以使用include命令时:
$before = get_declared_classes();
include "myfile.php";
$after = get_declared_classes();
$new_classes = array_diff($before, $after);     // 取差集
print_r($new_classes);  // Outputs all classes defined in myfile.php

            对比加载该文件前后,已经定义的类
        2>当不可以使用include命令时(有可能因为该文件定义了一个同名的类,会报错!)
            可以使用tokenizer分析出该文件所有的class

总结下:

    偶然的在dedecms中看源码,看到使用了这个tokenizer函数,就引申出一连串的东西,对手册等函数,一些扩展,稍微底层点的东西,必需都了解!与大家共勉!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息