<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[PHP Tokenizer 的学习笔记_PHP教程]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Php/Js/Shell/Go]]></category>
<pubDate>Mon, 08 Oct 2012 06:17:15 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	简述<br/>在某个项目中需要分析 PHP 代码，分离出对应的函数调用（以及源代码对应的位置）。虽然这使用正则也可以实现，但无论从效率还是代码复杂度方面考虑，这都不是最优的方式。<br/>查询了 PHP 手册，发现其实 PHP 已经内置解析器的接口，那就是 PHP Tokenizer，这工具正是我想要的。使用 PHP Tokenizer 能简单、高效、准确的分析出 PHP 源代码的组成。<br/>实例<br/>官方站点对 Tokenizer 的文档很少，不过这不影响我们理解它。Tokenizer 组件仅仅包含两个函数：token_get_all 以及 token_name，它们分别用于分析 PHP 代码以及获取代码对应的标识符名称。<br/>下面是个简单的实例，说明如何使用这两个函数：<br/>以下为引用的内容：<br/><textarea name="code" class="php" rows="15" cols="100">
$code = &#039;&lt;?php echo &quot;string1&quot;.&quot;string2&quot;; ?&gt;&#039;;
$tokens = token_get_all($code);
foreach ($tokens as $token) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;if (is_array($token)) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 行号、标识符字面量、对应内容
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%d - %s&#92;t%s&#92;n&quot;, $token[2], token_name($token[0]), $token[1]);
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&#125;
</textarea><br/>对应的输出为<br/>以下为引用的内容：<br/>1 - T_OPEN_TAG&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php <br/>1 - T_ECHO&nbsp;&nbsp;&nbsp;&nbsp;echo<br/>1 - T_WHITESPACE&nbsp;&nbsp;&nbsp;&nbsp; <br/>1 - T_CONSTANT_ENCAPSED_STRING&nbsp;&nbsp;&nbsp;&nbsp;&quot;string1&quot;<br/>1 - T_CONSTANT_ENCAPSED_STRING&nbsp;&nbsp;&nbsp;&nbsp;&quot;string2&quot;<br/>1 - T_WHITESPACE&nbsp;&nbsp;&nbsp;&nbsp; <br/>1 - T_CLOSE_TAG&nbsp;&nbsp;&nbsp;&nbsp;?&gt;<br/>这里顺便说明下，$token 如果为数组，那么分别对应的三个数组成员为 token 标识符（可以用 token_name 获得字面量）、对应的源代码内容、以及对应的行号。<br/>还有中情况就是 $token 为字符串，这可能的情况之一就是为 T_CONSTANT_ENCAPSED_STRING 等常量，在分析代码时要注意。如果对这点很在意，可以考虑使用这里的代码。<br/>是的，调用方式非常的简单，我们的野心当然远远要比写个简单的循环要大得多。我们可以利用这个组件做写实事，例如下面的代码用于“压缩” PHP 代码，去除不不要的换行、空白以及注释<br/>以下为引用的内容：<br/><textarea name="code" class="php" rows="15" cols="100">
/**
 * “压缩”PHP 源代码
 *
 * @see http://c7y.phparch.com/c/entry/1/art,practical_uses_tokenizer
 */
class CompactCode
&#123;
&nbsp;&nbsp;&nbsp;&nbsp;static protected $out;
&nbsp;&nbsp;&nbsp;&nbsp;static protected $tokens;

&nbsp;&nbsp;&nbsp;&nbsp;static public function compact($source)
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 解析 PHP 源代码
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$tokens = token_get_all($source);&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$out = &#039;&#039;;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reset(self::$tokens);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 递归判断每个标记符的类型
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while ($t = current(self::$tokens)) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (is_array($t)) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 过滤空白、注释
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($t[0] == T_WHITESPACE &#124;&#124; $t[0] == T_DOC_COMMENT &#124;&#124; $t[0] == T_COMMENT) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::skipWhiteAndComments();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$out .= $t[1];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$out .= $t;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next(self::$tokens);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return self::$out;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;

&nbsp;&nbsp;&nbsp;&nbsp;static private function skipWhiteAndComments()
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 增加个空格，用于分割关键字
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self::$out .= &#039; &#039;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while ($t = current(self::$tokens)) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 再次贪婪查找
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (is_array($t) &amp;&amp; ($t[0] == T_WHITESPACE &#124;&#124; $t[0] == T_DOC_COMMENT &#124;&#124; $t[0] == T_COMMENT)) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next(self::$tokens);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&#125;
</textarea><br/>调用方式很简单，只需要使用<br/>以下为引用的内容：<br/>CompactCode::compact($source_code);<br/>即可，返回的字符串就是压缩以后的内容。
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] PHP Tokenizer 的学习笔记_PHP教程]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>