人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

php or JavaScriptでのパースについて。

http://tyrano.jp/
このプログラムのように「タグ付きのテキストをパースして、ノベルゲームのように表示」したいと考えています。


例えば下記テキストをパースして [l] があると「クリック待ち」、[p]があると「クリック待ちでクリックがあるとセリフを全消しで続きのセリフを表示」のようにします。

--------
昔々あるところに、[l]おじいさんと、おばあさんがいました。[p][cm]

ある日、おばあさんが川に行くと、[l]どんぶらこ、どんぶらこと、[l]桃が流れてきました。[p][cm]
--------

上記の参考URLのソースは難読化されていて、アルゴリズムがつかめませんでした。

参考テキスト(文章の中に、[]で囲まれた命令タグが挿入されているもの)をパースして、上記URLのスクリプトのようなことを実現したいと考えています。

phpでパースして出力し、JavaScriptでは表示のみの予定です。

アドバイスを頂けると助かります。よろしくお願いします。

●質問者: onigirin
●カテゴリ:ウェブ制作
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● だわかき
●34ポイント

preg_split関数を使って、いったん配列(アクション記号とテキスト本体からなる2次元配列)に格納するといいでしょう。
http://www.kokin.rr-livelife.net/php/php_post/php_post_20.html


onigirinさんのコメント
どうもありがとうございます。 preg_splitで [xx] による分割をすると、セリフなどの文字列は分割できますが、命令文(アクション記号) [xx] 系が全て消えてしまうため、どうすれば命令文のところも一緒に分割できるんだろう、というところで迷子になっていました。

2 ● a-kuma3
●33ポイント

preg_match_all を使ってみました。

<?php

 $str = <<<EOT
昔々あるところに、[l]おじいさんと、おばあさんがいました。[p][cm]
ある日、おばあさんが川に行くと、[l]どんぶらこ、どんぶらこと、[l]桃が流れてきました。[p][cm]
EOT;

 preg_match_all("/(.*)\[(l|p|cm)\]/Us", $str, $out, PREG_SET_ORDER);
 foreach ($out as $val) {
 echo "TEXT: " . $val[1] . "<br>\n";
 echo "CMD : " . $val[2] . "<br>\n";
 }

?>

出力結果。

TEXT: 昔々あるところに、
CMD : l
TEXT: おじいさんと、おばあさんがいました。
CMD : p
TEXT:
CMD : cm
TEXT: ある日 ある日、おばあさんが川に行くと、
CMD : l
TEXT: どんぶらこ、どんぶらこと、
CMD : l
TEXT: 桃が流れてきました。
CMD : p
TEXT:
CMD : cm

onigirinさんのコメント
どうもありがとうございます。 これは面白い方法ですね。テキストとコマンドを1セットずつ抽出ですね。 目的としては達成できそうですが、もう少しパースのパターンをいろいろ待ってみます。

3 ● Lhankor_Mhy
●33ポイント ベストアンサー

パースはjavascriptでやった方がいいんじゃないかな、と思います。どうせコマンドを判別して表示制御するのはjavascriptなんですし。
↓サンプル
http://jsfiddle.net/VMH8D/


a-kuma3さんのコメント
おおぅ Deferred Object だ!

onigirinさんのコメント
どうもありがとうございます。 参考URLのものも、JavaScriptでパースしていたのですが、スマホでクライアント側に処理させると重くならないかなあと気になったので、php側で考えていました。 []でsplitして、ループで順にチェックして、命令ならその処理を、文章なら表示、ということですね。命令が多くなるとelseifが膨大になりそうだなあというのがちょっと気になりました。 Deferred Objectは知らなかったので、サンプルを参考に、jsでパースする方向でも一度試してみます。 やはりjsパースの方が、最近のノリにあってますかね・・・。

Lhankor_Mhyさんのコメント
if文をなくすべくダイエットしてみました^^ http://jsfiddle.net/VMH8D/1/

onigirinさんのコメント
どうもありがとうございます。 JSで[xx]命令のパースがうまくいきました! 読みやすいコードありがとうございます。 基本的に[xx]のみなら、文字列分割がベストみたいですね。 http://tyrano.jp/ こちらのような場合は、 *foo でラベルをつけてジャンプ先にしたり、 [link]xxx[endlink]のように、クリックでリンクタグもあるので、文字列分割じゃないかたちで、もう少し汎用的にパースの手順があるかもしれないので、もう少し質問はおいておきますね。

onigirinさんのコメント
すみません、もしかすると単純に、1行ずつ上から順に評価して進めるかたちかもしれません・・・。

Lhankor_Mhyさんのコメント
タグっぽい処理ができるようにしてみました。 http://jsfiddle.net/VMH8D/3/ ソースが汚い……!

onigirinさんのコメント
どうもありがとうございます。 おおよそ無事取り込めました。 実は1文字ずつ表示するようにしたくて、他のサンプルと合わせています。クリック連打で文字が表示され終わる前に次が表示されるところで先週は限界がやってきました(笑) いただいたソースのおかげで、Deferred Objectでの処理の流れがなんとなくわかってきたので、resolveしそうです。 この形式だと、カラー指定などの [em color="red"]等もすぐに応用できそうですね。本当に助かります。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ