Tokenizerを使用してPHPで作業する

参照用:

Tokenizer(lexer)は、コード分析のためのインターフェースを提供します。 したがって、言語仕様を操作しなくてもユーティリティを作成できます。

バージョンphp> = 4.3以降のTokenizerは、デフォルトでphpアセンブリに含まれています。



tokenizrで解決できるタスクは何ですか?

はい、コードの分析と変更に関連するさまざまなもの。



コードからコメントを削除する



最も簡単な例はphp.netにあります -コメントを削除するには:



<?php function strip_comments($fileName) { $source = file_get_contents($fileName); //     $tokens = token_get_all($source); $result = ''; foreach ($tokens as $token) { if (!is_array($token)) { //  1-  $result .= $token; } else { // - list($id, $value) = $token; switch ($id) { case T_COMMENT: case T_DOC_COMMENT: //   break; default: //   ->  " " $result .= $value; break; } } } return $result; } ?>
      
      





コードからわかるように、トークンの配列を取得し、そのタイプに応じて、脱退またはスキップします。

したがって、問題を解決したり、もっと面白いことができます-たとえば、phpファイルに基づいて、スタートアップ用のプロジェクトクラスのマップを生成します。



ファイルからクラスのリストを取得する



ファイルからクラスのリストを取得するために、次の関数を作成しました。



 <?php function getClasses($fileName) { $result = array(); $content = file_get_contents($fileName); $tokens = token_get_all($content); $waitingClassName = false; $waitingNamespace = false; $waitingNamespaceSeparator = false; $namespace = array(); for ($i = 0, $c = count($tokens); $i < $c; $i++) { if (is_array($tokens[$i])) { list($id, $value) = $tokens[$i]; switch ($id) { case T_NAMESPACE: $waitingNamespace = true; $waitingNamespaceSeparator = false; $namespace = array(); break; case T_CLASS: case T_INTERFACE: $waitingClassName = true; break; case T_STRING: if ($waitingNamespace) { $namespace[] = $value; $waitingNamespace = false; $waitingNamespaceSeparator = true; } elseif ($waitingClassName) { if (!empty($namespace)) { $value = sprintf('%s\\%s', implode('\\', $namespace), $value); } $result[] = $value; $waitingClassName = false; } break; case T_NS_SEPARATOR: if ($waitingNamespaceSeparator && !$waitingNamespace && !empty($namespace)) { $waitingNamespace = true; $waitingNamespaceSeparator = false; } break; } } else { if (($waitingNamespace || $waitingNamespaceSeparator) && ($tokens[$i] == '{' || $tokens[$i] == ';')) { $waitingNamespace = false; $waitingNamespaceSeparator = false; } } } return $result; } ?>
      
      







そして、プロジェクトファイルに基づいてオートローダーを生成する小さなユーティリティを考えて作成しました。

指定されたフォルダーにある拡張子* .phpのすべてのファイルを分析し、クラスマップを構築し(もちろん名前空間を考慮して)、それに基づいてオートローダーが生成されます。

彼女はgithub.comで見つけることができます



標準機能の無効化とオーバーライド



先日、私はかつてrunkit拡張機能をいじくり回したことを思い出しました。 その機能のうち、特定の機能の使用を禁止できる標準機能とサンドボックスの再定義に特に興味がありました。

そして今、私はこの拡張機能を使用せずにそのような機能を実装することが可能かどうか疑問に思っていました。 トークナイザーがこの問題に役立つことがわかった。

そのため、 ランタイムライブラリは、スクリプトの実行中に、標準機能の使用を禁止したり、オーバーライドしたりすることができます。

仕事の例を挙げます。



 <?php use Dm\Runtime; $code = <<<CODE <?php echo str_replace( 0, 1, 100 ); ?> CODE; //  Exception,    ,   str_replace  Runtime::code($code) ->disableFunction('str_replace') ->execute(); ?>
      
      







 <?php use Dm\Runtime; $code = <<<CODE <?php echo str_replace( 0, 1, 100 ); ?> CODE; //  000,  111 Runtime::code($code) ->overrideFunction('str_replace', function ($search, $replace, $subject) { //  1  2   echo str_replace($replace, $search, $subject); }) ->execute(); ?>
      
      







これらの機会をどのように使うかは個人的な問題です。 ただし、慎重に使用する必要があります。

私は少し研究をし、結果に満足しました。

ランタイムに関しては、どこで適用できるか、どこで適用できないかを言うのは難しいです。 ただし、ライブラリ自体は、トークナイザーの機能とその機能を明確に示しています。



参照資料


  1. トークナイザー
  2. ランキット
  3. github.comでのオートローダー生成
  4. github.comのランタイムライブラリ



All Articles