zoukankan      html  css  js  c++  java
  • PHP Tokenizer 学习笔记

    简介:这是PHP Tokenizer 学习笔记的详细页面,介绍了和php,有关的知识、技巧、经验,和一些php源码等。

    class='pingjiaF' frameborder='0' src='http://biancheng.dnbcw.info/pingjia.php?id=323132' scrolling='no'>

    简述

    在某个项目中需要分析 PHP 代码,分离出对应的函数调用(以及源代码对应的位置)。虽然这使用正则也可以实现,但无论从效率还是代码复杂度方面考虑,这都不是最优的方式。

    查询了 PHP 手册,发现其实 PHP 已经内置解析器的接口,那就是 PHP Tokenizer,这工具正是我想要的。使用 PHP Tokenizer 能简单、高效、准确的分析出 PHP 源代码的组成。

    实例

    官方站点对 Tokenizer 的文档很少,不过这不影响我们理解它。Tokenizer 组件仅仅包含两个函数:token_get_all 以及 token_name,它们分别用于分析 PHP 代码以及获取代码对应的标识符名称。

    下面是个简单的实例,说明如何使用这两个函数:

    以下为引用的内容:

    $code = '<?php echo "string1"."string2"; ?>';
    $tokens = token_get_all($code);
    foreach ($tokens as $token) {
        if (is_array($token)) {
            // 行号、标识符字面量、对应内容
            printf("%d - %s\t%s\n", $token[2], token_name($token[0]), $token[1]);
        }
    }

    对应的输出为

    以下为引用的内容:

    1 - T_OPEN_TAG    <?php 
    1 - T_ECHO    echo
    1 - T_WHITESPACE     
    1 - T_CONSTANT_ENCAPSED_STRING    "string1"
    1 - T_CONSTANT_ENCAPSED_STRING    "string2"
    1 - T_WHITESPACE     
    1 - T_CLOSE_TAG    ?>

    这里顺便说明下,$token 如果为数组,那么分别对应的三个数组成员为 token 标识符(可以用 token_name 获得字面量)、对应的源代码内容、以及对应的行号。

    还有中情况就是 $token 为字符串,这可能的情况之一就是为 T_CONSTANT_ENCAPSED_STRING 等常量,在分析代码时要注意。如果对这点很在意,可以考虑使用这里的代码。

    是的,调用方式非常的简单,我们的野心当然远远要比写个简单的循环要大得多。我们可以利用这个组件做写实事,例如下面的代码用于“压缩” PHP 代码,去除不不要的换行、空白以及注释

    以下为引用的内容:

    /**
     * “压缩”PHP 源代码
     *
     * @see http://c7y.phparch.com/c/entry/1/art,practical_uses_tokenizer
     */
    class CompactCode
    {
        static protected $out;
        static protected $tokens;
    
        static public function compact($source)
        {
            // 解析 PHP 源代码
            self::$tokens = token_get_all($source);   
            self::$out = '';
    
            reset(self::$tokens);
    
            // 递归判断每个标记符的类型
            while ($t = current(self::$tokens)) {
                if (is_array($t)) {
                    // 过滤空白、注释
                    if ($t[0] == T_WHITESPACE || $t[0] == T_DOC_COMMENT || $t[0] == T_COMMENT) {
                        self::skipWhiteAndComments();
                        continue;
                    }       
                    self::$out .= $t[1];
                } else {
                    self::$out .= $t;
                }
    
                next(self::$tokens);
            }
    
            return self::$out;
        }
    
        static private function skipWhiteAndComments()
        {
            // 增加个空格,用于分割关键字
            self::$out .= ' ';
            while ($t = current(self::$tokens)) {
                // 再次贪婪查找
                if (is_array($t) && ($t[0] == T_WHITESPACE || $t[0] == T_DOC_COMMENT || $t[0] == T_COMMENT)) {
                    next(self::$tokens);
                } else {
                    return;
                }
            }
        }
    }

    调用方式很简单,只需要使用

    以下为引用的内容:

    CompactCode::compact($source_code);

    即可,返回的字符串就是压缩以后的内容。在这里还有更多使用 Tokenizer 的实例,推荐阅读。

    “PHP Tokenizer 学习笔记”的更多相关文章 》

    爱J2EE关注Java迈克尔杰克逊视频站JSON在线工具

    http://biancheng.dnbcw.info/php/323132.html pageNo:16
  • 相关阅读:
    Echarts图表 相关技术点
    Jquery off() on() data()
    Js 正则表达式
    Java jar项目获取配置文件的项
    Java String.split 的坑,会忽略空值
    C# 工作流 状态机 门控制
    二维码SDK,高效率,高识别率,甩zxing,zbar几条街
    C#文本转语音,可导出在本地mp3或者wav文件
    api接口签名验证(MD5)
    C# 站点IP访问频率限制 针对单个站点的实现方法
  • 原文地址:https://www.cnblogs.com/ooooo/p/2255928.html
Copyright © 2011-2022 走看看