入力文字列自身でマーク付けに使う文字を指定する #1

考えてみると、解析する側がこの入力のメタ文字はこれ、というように指定するよりも、
入力する文字列自体が自分自身用のメタ文字を指定する方がずっと自然だろう。
適切なメタ文字を指定する責任は入力データを用意する側にあるべきである。
何をメタ文字とするかでダブルミーニングな入力になるような面白データとかなら、
解析器側でメタ文字を変更してみるというのもありかもしれないが一般的ではないと思う。

問題はどのような形式で入力文字列にメタ文字の指定を含めるかという点である。
今まで受理してきた文字列集合を変えることなく、
新たに追加情報を与えられるようにしなければならない。
正当な文字列の集合を変えてはならないということは、
逆に言えば、不正入力になるような文字列に新たな意味を持たせるのはいいということになる。

幸いなことにスマートかどうかは別にして統一感のある形式を見つけた。
受理する文字列パターンの範囲を広げる試みをした時を除けば、
マーク外の文脈において、

<start-mark> <start-mark>
<start-mark> <end-mark>
<start-mark> <start-annotation>

の3種類のパターンのどれが現れても不正入力と判断するようにしていた。
デフォルトのメタ文字ならそれぞれ、

((
()
(:

である。
3種類のメタ文字を後続に持つ<start-mark>という形式で揃っている。
そこで、この二文字のシーケンスにもう一文字追加して、

<start-mark> <current-meta-character> <new-meta-character>

という3文字シーケンスを正当な入力として許すことにし、
2文字目にある現在のメタ文字の機能を3文字目にある文字に移す意味を持たせる。

マーク内の文脈においても、この三種のシーケンスに以上のような意味を新たに持たせることはほぼ問題ないと思う。
「ほぼ」というのは、マーク付けの開始という本来の役割を行う<start-mark>の直後に、
このシーケンスが置かれた場合、二つの<start-mark>の並びの意味が曖昧で解釈できない。
それ以外の場所ではマーク外と同じにできそうだと思う。

このシーケンスの例としては、

$ echo -n '<html lang="ja"><body><img src="foo.jpg" alt="description"></body></html>' | ./parser -s"<" -e">" -a" "

のような入力の解析と、

$ echo -n '()>(: ((<<html lang="ja"><body><img src="foo.jpg" alt="description"></body></html>' | ./parser

のように先頭に()>(: ((<を付けることで、
入力自身がメタ文字を指定する形式の解析が等価になるようにする。
この3文字シーケンスが解析器で認識されるごとにメタ文字の変更が即座に行われるようにすることで、
例示したような先頭で指定する使い方だけでなく、入力の途中での変更も行えるようにできるだろう。
そのような場合、上の例では最後だった<start-mark>の変更を先に指定するなら、

$ echo -n '((<<)><: <html lang="ja"><body><img src="foo.jpg" alt="description"></body></html>' | ./parser

のようなものになるであろう。