作者: 閑舎
日時: 2006/7/07(09:58)
wtnabe@... (ねこ丸) さん wrote.

>   えーと、僕や Zazel さんの方法ではサブクラスまで考える必要はないんで、
> 普通に $this->line などを参照すればいいと思ってるんですけど。

おいおい。

まあいいとして。PHP は 4 も 5 も名前空間を持たないために、グローバル変数
でなければローカル変数という 2者択一しかなく、変数の扱いを厳密にしようと
すると非常に手間がかかるということがわかりました。Python はファイル単位
で名前空間を持っているため、簡単のもよう。

取りあえず、クラスレベルでの再帰を使い(一応 $this->line はきかなくなるの
で)、ちょっとした処理をほどこし、$line みたいにサイズが大きくなる可能性
があるものはリファレンスにし、渡すタイミングは new を使う時、あとはご勝
手に、というのが無難。

<?php
$obj = new mkhtml("\n\nab\nc\n\ndef");

class mkhtml {
  function mkhtml($str) {
    $body = new Block($str, strlen($str), 0, "body", 0);
    $body->parse();
    $body->toText();
  }
}
class Block {
  function Block(&$line, $length, $pt, $name, $start) {
    list($this->line, $this->length, $this->pt) = array(&$line, $length, $pt);
    list($this->name, $this->next, $this->start, $this->len) = array($name, null, $start, 0);
  }
  function parse() {
    if (preg_match("/\n\n+/", $this->line, $matches ,PREG_OFFSET_CAPTURE, $this->pt)) {
      $this->len = $matches[0][1] - $this->start;
      $this->pt = $matches[0][1] + strlen($matches[0][0]);
      $this->next = new Block($this->line, $this->length, $this->pt, "p", $this->pt);
      $this->next->parse();
    } else if ($this->name != "body") {
      $this->len = $this->length - $this->start;
      $this->next = new Block($this->line, $this->length, $this->pt, "body", $this->length);
    }
  }
  function toText() {
    if ($this->name != "body") echo "<" . $this->name . ">";
    echo substr($this->line, $this->start,  $this->len);
    if ($this->name != "body") echo "</" . $this->name . ">\n";
    if ($this->next != null) $this->next->totext();
  }
}
?>

こんな感じでしょうか。一応表から変数を隠したことになります。echo でなく
値を返せとか、タグを増やせ、とかいう要求は却下いたします:-p。

# 本当に興味があったのは、PHP のコードを、Perl とか、ruby とか、Python 
# とかで書くと一体どんな感じになるのか? クラスとか、継承とか、オーバー
# ライドとか、そういった扱いだったんですけど、そういう要素が消えてしまい
# ました、残念、これじゃあね(^^;。

--
本田博通(閑舎)
テキストとスクリプトの http://www.rakunet.org/TSNET/