PHPでPHPコードを解析したい
解決済
回答 4
投稿
- 評価
- クリップ 3
- VIEW 3,831
この際、独自形式のテキストファイルに記述された
{}
で囲まれた範囲のPHPコードを正確に抽出し、かつ、特定の関数や定数、変数を、文字列に置き換える処理が必要になります。
{}
で囲まれた範囲のPHPコードを抽出するだけでも厄介です。
PHPコード内では制御構造・コールバックに使用する
{}
やそのネスト、文字列(''
,""
)の他、ヒアドキュメント、Nowdoc、実行演算子などでも{}
が出現します。
これら全てを考慮し、PHPコードの終了位置にある
}
を抽出するだけでも面倒です。
またそれ以外に、特定の名前の関数を実行している箇所の式などを、PHPコードを文字列として扱いつつ別のコードに置き換えなくてはなりません。
例えば、関数
_elem
の実行箇所を置き換える場合、以下のようになります:
$i = 0;
foreach ($list as $user) {
$color = ++$i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
_elem();
}
↓
$i = 0;
foreach ($list as $user) {
$color = ++$i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
?>
<tr bgcolor="<?php echo $color; ?>">
<td><?php echo htmlspecialchars($user['name']); ?></td>
<td><?php echo $user['mail']; ?></td>
</tr>
<?php
}
関数_elem
の実行箇所を、別のPHPコードで置き換えています。
$i = 0;
foreach ($list as $user) {
$color = ++$i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
- _elem();
+ ?>
+ <tr bgcolor="<?php echo $color; ?>">
+ <td><?php echo htmlspecialchars($user['name']); ?></td>
+ <td><?php echo $user['mail']; ?></td>
+ </tr>
+ <?php
}
このような処理を行うためには、PHPでPHPコードを解析する必要があります。
しかしながら、そのようなライブラリは一向に見つかりません。
そもそも、「PHPでPHPを解析する」という意味を検索するためのキーワードすら捻り出せません。
「PHP PHPを解析」で検索しても、まるで無関係な内容がヒットしてしまい、検索すらままならない状況です。
PHPでPHPを解析するライブラリはありますか?
または、そのための方法は存在しますか?
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
- nikic/PHP-Parser
字句解析だけしか必要ないなら Tokenizer でも良いと思います。これは単にトークンのリストが得られたと思います。
- PHP: Tokenizer - Manual
ただ、字句解析だけだと識別子(
T_STRING
トークン)がなんなのか直ちに特定できないので、質問にかかれているような用途だと難しいかもしれません。
参考までに、Smarty3 は下記の字句解析器/構文解析器ジェネレータが使われているそうです。
- PHP_LexerGenerator
- PHP_ParserGenerator
と思っていたんですが、いつの間にか fork?していたようでした。
- smarty-php/smarty-lexer
独自形式のテキストファイル のパーサに使えたりするかもしれません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
-1
「独自形式のテキストファイルに記述された{}で囲まれた範囲のPHPコード」
とありますが、{}で囲まれた範囲のPHPコードは、sounisi5011さんのおっしゃるようにいろいろな意味で使われいますよね。
独自形式のテキストファイルということは、sounisi5011さんが意味を決めてPHPコードを{}を囲っていると思うのですけど、何のために囲っているのでしょうか?
私もPHPでキーワードを決めた部分を置き換えることをやっていますが、「PHPでPHPを解析する」なんてややこしいことはしていません。
置き換える文字列が複数ある場合、
・置き換える文字列をキーとした連想配列を記述とたファイルを作成します。
・そして、それぞれのキーに対応する置き換えられるPHPコードを文字列として記述して起きます。
・実行時に、このファイルをインクルードします。
・実行したいPHPファイルを読み込みます。
・読み込んたPHPファイルに置き換える文字列があったら、その文字列をキーとした連想配列に
記憶しているPHPコードを置き換えます。
・読み込んたPHPファイルを保存して実行します。
このようにして対応したことがあります。
私の頭では、なぜ、わざわざ、混乱するような内容のファイルで設計するのかが理解に苦しむところです。
sounisi5011さんが考えて、{}で囲ったPHPコードのファイルを導入されていると思いますので、参考にはならないとは思いますが・・・
sounisi5011さんがを設計段階から{}で囲ったPHPコードのファイルを導入れているのでしょうか?
また、{}で囲ったPHPコードのファイルは、どのようなフォーマットなのでしょうか?
教えいただけると嬉しいです。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
-2
難しく考えすぎてはないでしょうか。
このコードですよね。
-------------------------------------
#row {
attrs: "bgcolor" $color;
logic: {
$i = 0;
foreach ($list as $user) {
$color = ++$i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
_elem();
}
}
}
------------------------------------------------------
私の考えは、関数などの内容を分析をする必要はなく、{}は必ずどのような関数であろうとPHPは
入れ子構造ですから'{'に対応する'}'は一番最初に出てくるものです。
ですから、このようにすればいいと思います。
1.table1.php.plogicをファイルとして読み込み$fileに代入する
2.'logic:'をキーに$fileを$aと$bの2つに分ける。
list($a,$b) = split('logic:',$file);
これで$bには、
$b=' {
$i = 0;
foreach ($list as $user) {
$color = ++$i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
_elem();
}
}
}'
が代入されています。
3.$bの中の先頭よりの'{'より後がPHPコードなので、中の先頭よりの'{'以前を
削除し$bに代入する。
この時、先頭にスペースがある時とない時があるので考えてみてください。
4.$bの中に'{'がいくつあるか調べ$cに代入して置きます。
$c = mb_substr_count($b, '{');
5.$b文字列を'}'を区切りに分解して$array配列に入れる。
$array = split('}',$b)
実行すると
$array[0]には、'$i = 0;
foreach ($list as $user) {
$color = ++$i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
_elem();
';
$array[1]には、' ';
$array[2]には、'';
それぞれ入ります。
6.つまり、先に'{'の数を調べ$cに代入してあります。
$cが0であれば、'{'はなかったということですから、$php = $array[0]
$cが1であれば $array[1]以前がphpコードであるので、$php ="$array[0].}"
$cが2であれば $array[2]以前がphpコードであるので、$php ="$array[0].}.$array[1].}"
$cが3であれば 同様に $php ="$array[0].}.$array[1].}.$array[2].}"
という具合で抽出できます。
関数のコードが決まっていれば、先ほどの方法で置き換えできるのではないでしょうか?
いかがでしょうか
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
-2
>PHPの文字列には、引用符で囲まれたものとヒアドキュメントが存在します。
確かにその通りですが、関数に以外に、引用符で囲まれた文字定数とヒアドキュメントしかないのです。たくさんあるとさんあると思い込んでいませんか?
考えは単純です。文字定数とヒアドキュメントを探してその中にある
{'と'}
の数を数えておけば問題なく足し算と引き算で先ほどのアルゴリズムで問題なく抽出できますよ。
アルゴリズムがわかっているのですから、プログラム出来るはずです。
それ以外の所に
{'や'}
があったら、エラーで停止するはずです。元々、PHPを抽出するソースは、エラーがないものとして考えないと、事は進みません。
先ほどの私のアルゴリズムは文字定数やヒアドキュメントに現れたとしても、
{'の数を数え、その数分の消した'}
を元の位置に置いて抽出するPHPコードに組み直しているので、そのアルゴリズムで問題なく抽出できます。
'}`をもとの位置に戻す数を計算します。
{'の数から文字定数やヒアドキュメント内の
{'の数を引いて、
関数に使用されている`{'の数を出す。
文字定数やヒアドキュメント内の'}
の数に関数に使用されている
{'の数を足した足したものが'}`をもとの位置に戻す数です。
私の答えも100%ではないと思っていますし、sounisi5011さんの考えの方が優れている
かも知れません。
ダメだと否定していると、人間、思考停止しますから、それ以上考えることをやめて
何も進まなくなりますよ。ダメと思われる中に、ヒントが見つかるかもしれません。
一度、プログラムを作っていろいろなケースで試してみるたらいかがでしょうか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.13%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
9walk
2015/05/17 08:31
質問の意図はテンプレートエンジンを自作することでしょうか?
それともHTMLの生成が目的で、Kwartz以外によいテンプレートエンジンがあれば、それを使っても構わないと考えてもよいのでしょうか?
sounisi5011
2015/05/17 09:47
テンプレートエンジンの自作です。