<html xmlns="http://www.w3.org/1999/xhtml" a0:Name="SuikaWiki" xmlns:a0="urn:x-suika-fam-cx:markup:suikawiki:0:9:" a0:Version="0.9"><head></head><body><p><a0:anchor-end a0:anchor="8">[8]</a0:anchor-end> 誰も期待していないとは思いますが、元々『<a0:anchor>冬日</a0:anchor>』の記述のために
作られた(とされる)<a0:anchor>マーク付け言語</a0:anchor>, <a0:anchor>H2H</a0:anchor> の第2版 (2.0) の
予定をお知らせします。</p><p>H2H 言語のサンプル (そしておそらくは唯一の) 実装は、
parser と HTML などへの転写部分をほぼ完全に分離する
ことにしています。このうち parser 部分は昨日一気に
書き上げてしまい、今日はそれに肉付けしていました。</p><p>H2H/2.0 に適合する(完全な)文書はこんな感じになります。</p><pre>  H2H/2.0
  #V TENKI 雪
  NEW {cat=&gt;&quot;時候&quot;} はつまうで
  
  今日は
  LINK* http://www.tsurugi.co.jp/toyama-hiejinjya/ 神社
  におまいりに行きました。
  
  軽く参拝(謎)して帰ろうとしたとき、いきなり
  RUBY 雷鳴 らいめい
  が響きました。なにか
  DEL 不潔
  INS 不吉
  なものを感じました。</pre><p>段落を意味する P 要素の印は空行で代用できるようになります。
去年からの念願のウェブの掲示板への転用
FN
改行を BR 要素に変換する今の大多数のウェブの掲示板は
とっても汚い!
/FN
がようやく視野に入りました:-)</p><p>それはともかくスケジュール(予定):</p><p>2002年1月 サンプル実装の parser を完成させる
2002年2月 サンプル実装の HTML/XHTML 転写を完成させる
2002年3月 H2H/2.0 の仕様書の刊行</p><p>2002年前半 モジュール *1 の実装, plain-text 転写などの実装</p><p>注1  table (表) module, math (数学) module, chem (化学) module
を予定。</p><p>2002年夏休みまで (遊んでていいのか?)
『冬日』で供用開始 (動的生成対応)
用語集システム本格実装
ヱブサーバーで書き換えの実装 (去年失敗した:-)
その他(謎)</p><p><a0:anchor>わかば</a0:anchor>。  (予定はあくまで予定。) (2002年1月2日)</p><ul><li>2002-08-30 (Fri) 14:20:24 <em><a0:anchor>わかば</a0:anchor></em> : 結局それから全然進んでません。</li><li>2002-08-30 (Fri) 14:21:29 <em><a0:anchor>わかば</a0:anchor></em> : #V とかは規格から削除。</li><li>2002-08-30 (Fri) 14:22:21 <em><a0:anchor>わかば</a0:anchor></em> : 要素が行指向なのはなんとかならないのでこのまま突っ切るしかなさげ。</li><li>2002-08-30 (Fri) 14:22:59 <em><a0:anchor>わかば</a0:anchor></em> : 実は parser 本体は1月に完成していますから、あとはなんとかなる、はずなんだけど。</li><li>2002-08-30 (Fri) 14:24:09 <em><a0:anchor>わかば</a0:anchor></em> : <a0:anchor>Perl</a0:anchor> 実装で内部形式 <a0:anchor>DOM</a0:anchor> (XML::DOM) にすれば XML::* が使えて便利だと思ってたんだけど、今んとこ XML::XSLT とか使い物にならないから無理。</li><li><a0:anchor-end a0:anchor="1">[1]</a0:anchor-end> 2002-11-01 (金) 19:53 <em><a0:anchor>名無しさん</a0:anchor></em>: 今年の初めに作った実装は一旦破棄してもう一度作り直すことになりました。 (しかしとなると一体いつ出来るのやら・・・)</li><li><a0:anchor-end a0:anchor="2">[2]</a0:anchor-end> 2002-11-01 (金) 19:54 <em><a0:anchor>名無しさん</a0:anchor></em>: Object model に少々修正を加えます。属性と要素の区別を廃止します。 {foo=&gt;&quot;bar&quot;} と FOO / bar / /FOO は同義になります。</li><li><a0:anchor-end a0:anchor="3">[3]</a0:anchor-end> 2002-11-01 (金) 19:57 <em><a0:anchor>名無しさん</a0:anchor></em>: また、従来の行指向の他に、 inline 構文も取り入れます。 &quot;[&quot; element-type 1*( &quot;[&quot; content &quot;]&quot; ) [ trailer ] &quot;]&quot;</li><li><a0:anchor-end a0:anchor="4">[4]</a0:anchor-end> 2002-11-01 (金) 19:57 <em><a0:anchor>名無しさん</a0:anchor></em>: &quot;[&quot; &quot;[&quot; ... &quot;]]&quot; は入れ子に出来ます。</li><li><a0:anchor-end a0:anchor="5">[5]</a0:anchor-end> 2002-11-01 (金) 19:58 <em><a0:anchor>名無しさん</a0:anchor></em>: もちろんこれは <a0:anchor>SuikaWiki</a0:anchor> の構文に由来します。</li><li><a0:anchor-end a0:anchor="6">[6]</a0:anchor-end> 2002-11-01 (金) 19:58 <em><a0:anchor>名無しさん</a0:anchor></em>: <a0:anchor>SGML</a0:anchor> 風 entity も正式に仕様に入ります。 &quot;[&quot; を入れるときはこれを使います。</li><li><a0:anchor-end a0:anchor="7">[7]</a0:anchor-end> <em><a0:anchor>H2H</a0:anchor> が<a0:anchor>西瓜サーバー</a0:anchor>の標準<a0:anchor>記述言語</a0:anchor>となる</em>は <em><a0:anchor>Hurd</a0:anchor> が <a0:anchor>GNU</a0:anchor> System の <a0:anchor>kernel</a0:anchor> となる</em>, <em><a0:anchor>SuikaWiki</a0:anchor> が H2H を採用する</em>は <em>GNU <a0:anchor>Emacs</a0:anchor> が <a0:anchor>Guile</a0:anchor> を搭載する</em>位の意味だとでも思ってください:)
<a0:anchor-end a0:anchor="9">[9]</a0:anchor-end>  今年こそはなんとかしたいもんです:)</li></ul><p>現在の H2H/2.0 案による例文:</p><pre> #?H2H/2.0 ns:math=&quot;urn:x-suika-fam-cx:ns:h2h:math&quot;
 SECTION\ {h=&gt;&quot;はじめに&quot;}
 この文書は、<a0:anchor>云々かんぬん</a0:anchor>に付いて説明するものです。
 
 この文書は、<a0:anchor>かんぬん云々</a0:anchor>については説明しません。
 SECTION/\
  
 H= 次に。
  
  H2H/2.0 では大胆に構文を変えてしまうことにしますた。
  例えば <a0:anchor>Wiki</a0:anchor> でいう
 SEE= BracketName
  は parser により
 CODE= {t=&gt;H2H} SEE
  に展開します。
 
 空行は段落区切りです。勝手に 
 CODE= {t=&gt;H2H}  P/\
 が補われます。
 SECTION\ {h=&gt;要素}
 大文字の要素名の後に
 CODE= {t=&gt;H2H} \
 がつくのが開始タグで、
 CODE= {t=&gt;H2H} /
 がつくのが終了タグ、
 CODE= {t=&gt;H2H} =
 がつくのが一行タグ (その行で完結)。
 NOTE
 CODE= {t=&gt;H2H} \
 は省略可能です。なお、<a0:anchor>SGML</a0:anchor> 風に /ELEMENT ではなく
 CODE= {t=&gt;H2H} ELEMENT/
 なのは日本語入力モードの都合です:)
 NOTE/
 SECTION/
 SECTION= {h=&gt;属性} H2H/2.0 には属性はありません。属性のように見えるのは要素の短縮表記です。
 SECTION/
 (<a0:anchor>わかば</a0:anchor> <a0:weak>2003-01-26 07:10</a0:weak>)</pre><p><a0:anchor-end a0:anchor="10">[10]</a0:anchor-end>  ぐは。 <a0:anchor> ... </a0:anchor> が SuikaWiki に解釈されちまった。
例にし忘れましたが、最初の行にあるとおり、名前空間があります。
要素と属性の別がないので <a0:anchor>XML</a0:anchor> の名前空間みたいに変なことはありません。</p><p>名前空間宣言は parser が知ってる名前空間は省略可能にしようと思ってます。
可搬性はあれですが。だから上の例では暗黙の既定名前空間の指定がなされているとみなすってことで。
(例えば Wiki で使う時には Wiki で便利な語彙の空間を暗黙定義済みにしておく。)</p><p><code class="H2H">CODE</code> は多分別名前空間になりますね。 (9 <a0:weak>2003-01-26 07:15</a0:weak>)</p><p><a0:anchor-end a0:anchor="11">[11]</a0:anchor-end>  「次に」の節のように、要素の内容の最初の行の行頭に <code class="ABNF">1*WSP</code>
を入れておくと、2行目以降の同じ数の <a0:anchor>WSP</a0:anchor> は無視します。</p><p>indent がないと入れ子関係が見た目で分かりませんね... どうしようかなあ。 (<a0:anchor>9=10</a0:anchor>)</p><p><a0:anchor-end a0:anchor="12">[12]</a0:anchor-end>  <code class="H2H">P</code> が勝手に補われるよりは、 (今までの意味の) P 要素は廃止して、
DOM でいう <a0:form ref="text"></a0:form> にしてしまって、空行はその区切りにしてしまえばいいですね。
HTML なりなんなりに変換する時に、適切な文脈なら1個の #text を <a0:anchor>p</a0:anchor>
要素に変換するという方向で。 (<a0:anchor>9=10=11</a0:anchor> [sage])</p><p><a0:anchor-end a0:anchor="13">[13]</a0:anchor-end>  なお従来の版の H2H ではその元になった <a0:anchor>HNF</a0:anchor> に倣って行頭の <code class="H2H">FOO</code> を「命令」と呼んできましたが、今後はちょっと
SGML 風になって「開始タグ」と呼びます。 (12)</p><p><a0:anchor-end a0:anchor="14">[14]</a0:anchor-end>  属性=要素はしんどいだけであんまり利点がなさそうだし、字下げがないのもつらいよなあ。
てことで上のは撤回して再検討でしょう。</p><p>とりあえず既定名前空間は <code class="URN">urn:x-suika-fam-cx:ns:h2h:core</code>
に決定。これだけ決まってもどうしようもないんですが:-) (<a0:anchor>わかば</a0:anchor>)</p><a0:form input="%submit(label=&gt;書き込む); %text(label=&gt;&quot;名前 : &quot;,id=&gt;name,size=&gt;&quot;9.5&quot;); %text(label=&gt;&quot;メイル: &quot;,id=&gt;mail,size=&gt;9.5); %check(default,id=&gt;record-date,label=&gt;日付を記録);%n;%textarea(id=&gt;msg,size=&gt;35,lines=&gt;5);" template="[%index;]  %text(source=&gt;msg); (%name;%text(source=&gt;mail,prefix=&gt;&quot; [&quot;,suffix=&gt;&quot;]&quot;);%iif(source=&gt;record-date,true=&gt;&quot; [WEAK[%date;]]&quot;);)%n;" option="%require(msg);"></a0:form><p><a0:anchor-end a0:anchor="15">[15]</a0:anchor-end> 作りかけの試作品 (といえる域にも達していない段階) :<pre>
my $t = &lt;&lt;EOH;
H2H/2.0 (pre)
#A TENKI &amp;hare;
#A SP {time =&gt; &quot;00:00:00&quot;} 年の変わり目
STRONG {level =&gt; 10; title =&gt; &quot;toku ni nashi =&gt; aaa&quot;}
ooo
/STRONG
CITE* href source
/H

akakikukeko
/
SOURCE bar
/CITE
foo
CHEM:NANTOKA
foo bar -&gt; Cl-
/CHEM:NANTOKA
EOH

my $s = new T (element_type =&gt; {ABBR =&gt; &quot;ABBR&quot;,
  RUBY =&gt; &quot;RUBY&quot;});

for my $line (split /\x0D?\x0A/, $t) {
  if ($line =~ /^(NEW|SUB)(?:\*\s+([^\s]+))?\s+(.+)/) {
    my ($section_type, $text, $uri) = ($1, $3, $2);
    if ($s-&gt;{current_element}-&gt;{name} eq 'SEC' 
     &amp;&amp; $s-&gt;{current_element}-&gt;{_SEC_TYPE} eq $section_type) {
      $s-&gt;end_element (name =&gt; 'SEC');
    } elsif ($s-&gt;{current_element}-&gt;{name} eq 'P') {
      $s-&gt;end_element (name =&gt; 'P');
      if ($s-&gt;{current_element}-&gt;{name} eq 'SEC' 
       &amp;&amp; $s-&gt;{current_element}-&gt;{_SEC_TYPE} eq $section_type) {
        $s-&gt;end_element (name =&gt; 'SEC');
      }
    }
    my ($empty, $element) 
      = $s-&gt;start_element (name =&gt; 'SEC', text =&gt; $text, 
                           uri =&gt; $uri, _SEC_TYPE =&gt; $section_type);
      my %helement;
      for my $name (keys %$element) {
        $helement{&quot;PARAM_$1&quot;} = $element-&gt;{$name} if $name =~ /^PARAM_H_(.+)/;
      }
      $s-&gt;start_element (name =&gt; 'H', %helement);
        $s-&gt;element_content (text =&gt; $element-&gt;{text});
      $s-&gt;end_element (name =&gt; 'H');
  } elsif ($line =~ /^CITE(?:\*\s+([^\s]+))?\s+(.+)/) {
    my ($text) = ($2);
    $s-&gt;start_element (name =&gt; 'CITE', text =&gt; $text, PARAM_URI =&gt; $1);
    $text =  $s-&gt;{current_element}-&gt;{PARAM_SOURCE}
          || $s-&gt;{current_element}-&gt;{text};
    if ($text) {
      my %helement;
      for my $name (keys %$element) {
        $helement{&quot;PARAM_$1&quot;} = $element-&gt;{$name} if $name =~ /^PARAM_SOURCE_(.+)/;
      }
      $s-&gt;start_element (name =&gt; 'SOURCE', %helement);
        $s-&gt;element_content (text =&gt; $text);
        $s-&gt;{current_element}-&gt;{PARAM_URI} = $s-&gt;{current_element}-&gt;{parent}-&gt;{PARAM_URI};
      $s-&gt;end_element (name =&gt; 'SOURCE');
    }
  } elsif ($line =~ /^([A-Z]+(?::[A-Z]+)*)(?:\*\s+([^\s]+))?(?:\s+(.+))?$/) {
    my ($empty, $element)
      = $s-&gt;start_element (name =&gt; $1, text =&gt; $3, PARAM_URI =&gt; $2);
    if ($empty &amp;&amp; $s-&gt;{current_element}-&gt;{name} eq 'RUBY') {
      $s-&gt;start_element (name =&gt; 'RB');
        $s-&gt;element_content (text =&gt; $s-&gt;{current_element}-&gt;{parent}-&gt;{_RUBY_BASE});
      $s-&gt;end_element (name =&gt; 'RB');
      $s-&gt;start_element (name =&gt; 'RT');
        $s-&gt;element_content (text =&gt; $s-&gt;{current_element}-&gt;{parent}-&gt;{_RUBY_TEXT});
      $s-&gt;end_element (name =&gt; 'RT');
      $s-&gt;end_element (name =&gt; 'RUBY');
    } elsif ($empty) {
      $s-&gt;element_content (%$element);
      $s-&gt;end_element (%$element);
    }
  } elsif ($line =~ m#^/([A-Z]+(?::[A-Z]+)*)$#) {
    my $name = $1;
    if  ($name ne 'P' 
      &amp;&amp; $s-&gt;{current_element}-&gt;{name} eq 'P'
      &amp;&amp; $s-&gt;{current_element}-&gt;{parent}-&gt;{name} eq $name
    ) {
      $s-&gt;end_element (name =&gt; 'P');
    }
    $s-&gt;end_element (name =&gt; $1);
  } elsif ($line =~ m#^/$#) {
    $s-&gt;end_element (name =&gt; $s-&gt;{current_element}-&gt;{name});
  } elsif ($line) {
    $s-&gt;element_content (text =&gt; $line);
  } else {
    $s-&gt;end_element (name =&gt; &quot;P&quot;);
    $s-&gt;start_element (name =&gt; &quot;P&quot;);
  }
}

print_element ($s, 0);

sub print_element ($$) {
  my $element = shift;
  my $level = shift;
  print &quot;\t&quot; x $level, $element-&gt;{name}, &quot;\n&quot;;
  $level++;
  for my $el (@{$element-&gt;{elements}}) {
    if ($el-&gt;{type} eq &quot;text&quot;) {
      print &quot;\t&quot; x $level, $el-&gt;{text}, &quot;\n&quot;;
    } else {
      print_element ($el, $level);
      for my $param (sort grep {/^PARAM_/} keys %$el) {
        print &quot;\t&quot; x ($level+1), $param, &quot;\t&quot;, $el-&gt;{$param}, &quot;\n&quot;
          if length $el-&gt;{ $param };
      }
    }
  }
}

package T;
use strict;
use overload '@{}' =&gt; sub {shift -&gt;{elements}};

sub new ($;%) {
  my $class = shift;
  my $self = {name =&gt; &quot;H2H&quot;, @_};
  $self-&gt;{current_element} = $self;
  bless $self, $class;
}

sub start_element ($%) {
  my $self = shift;
  my $new_element = {@_};
  my $empty_element = 0;
  $new_element-&gt;{parent} = $self-&gt;{current_element};
  if ($new_element-&gt;{text} =~ /^\{/) {
    my $t = $new_element-&gt;{text};
    $t =~ s{(?:^\{\s*|\G[;,]\s*)([a-z0-9_-]+)
        \s*=&gt;\s*   (?:&quot;([^&quot;]+)&quot;
                     | ([^\s;,\}]+))\s*
    }{
      my ($name, $value) = ($1, $2 || $3); $name =~ tr/a-z-/A-Z_/;
      $new_element-&gt;{&quot;PARAM_&quot;.$name} = $value;
      <em>;
    }gex;
    $t =~ s/^\} *//;
    $new_element-&gt;{text} = $t;
  }
  my $element_type = $self-&gt;{element_type}-&gt;{$new_element-&gt;{name}};
  if ($element_type eq 'ABBR') {
    if ($new_element-&gt;{text}) {
      $new_element-&gt;{texts} = [split(/\s+/, $new_element-&gt;{text}, 2)];
      $new_element-&gt;{text} = $new_element-&gt;{texts}-&gt;[0];
      $new_element-&gt;{PARAM_TITLE} ||= $new_element-&gt;{texts}-&gt;[1];
      $empty_element = 1;
    }
  } elsif ($element_type eq 'RUBY') {
    if ($new_element-&gt;{text}) {
      $new_element-&gt;{texts} = [split(/\s+/, $new_element-&gt;{text}, 2)];
      $new_element-&gt;{_RUBY_BASE} = $new_element-&gt;{texts}-&gt;[0];
      $new_element-&gt;{_RUBY_TEXT} = $new_element-&gt;{texts}-&gt;[1];
      $empty_element = 1;
    }
  } elsif ($new_element-&gt;{text}) {
    my $count = $self-&gt;{param_count}-&gt;{$new_element-&gt;{name}} || 1;
    if (1 &lt; $count) {
      $new_element-&gt;{texts} = [split(/\s+/, $new_element-&gt;{text}, $count)];
      unless ($count &lt; $#{$new_element-&gt;{texts}}) {
        $empty_element = 1;
      }
    } else {$empty_element = 1}
  }
  push @{$self-&gt;{current_element}-&gt;{elements}}, $new_element;
  $self-&gt;{current_element} = $new_element;
  $empty_element, $new_element;
}

sub element_content ($%) {
  my $self = shift;
  my $content = {@_};
  $content-&gt;{type} = &quot;text&quot;;
  push @{$self-&gt;{current_element}-&gt;{elements}}, $content;
  $self;
}

sub end_element ($%) {
  my $self = shift;
  my $end_element = {@_};
  if ($end_element-&gt;{name} eq $self-&gt;{current_element}-&gt;{name}
    &amp;&amp; ref $self-&gt;{current_element}-&gt;{parent}) {
    $self-&gt;{current_element} = $self-&gt;{current_element}-&gt;{parent};
  }
  $self;
}

package T::Element;

use overload '@{}' =&gt; sub {shift -&gt;{elements}};

sub new ($) {
  bless {}, shift;
}

sub push ($%) {
  my $self = shift;
  my %prop = @_;
  push @{$self-&gt;{elements}}, \%prop;
  $self;
}</em></pre></p><p>ライセンスは例によって <a0:anchor>GPL</a0:anchor> ですが、
こんなの再利用もできないでしょう。。。</p><section><h1>License</h1><p><a0:anchor-end a0:anchor="16">[16]</a0:anchor-end> <a0:anchor-internal a0:anchor="15">&gt;&gt;15</a0:anchor-internal> の部分は <a0:anchor>GPL</a0:anchor> (任意の版)。</p></section><section><h1>メモ</h1></section></body></html>