1. 程式人生 > >php手冊中的tokenizer詳細總結,基本看它就夠了

php手冊中的tokenizer詳細總結,基本看它就夠了

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個方法進行了檢視,總結,可參照:



    2.壓縮php程式碼,去除不要的換行、空白以及註釋,轉載別人的部落格,可參照:

        有人指出了 'php_strip_whitespace' 可做相同的事情,就研究下這個函式,看了下手冊,裡面有個評論,也寫了一個壓縮php的程式碼,乾脆再寫篇文章了



    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函式,就引申出一連串的東西,對手冊等函式,一些擴充套件,稍微底層點的東西,必需都瞭解!與大家共勉!