Smart Game Formatの文字列を解析します。
SGFは、ボードゲームのファイル、とくに囲碁の棋譜を保存するための標準フォーマットです。
SGFは比較的シンプルなフォーマットです。SGFファイルには通常、ノードの木構造が1つだけ含まれており、各ノードはプロパティリストです。プロパティリストにはキーと値のペアが含まれ、各キーは1回しか登場しませんが、複数の値を持つことができます。
この演習では、SGFの文字列を解析し、プロパティの木構造を返します。
SGFファイルは次のようになっています。
(;FF[4]C[root]SZ[19];B[aa];W[ab])
これは3つのノードを持つ木構造です。
ご想像のとおり、SGFファイルには子を1つだけ持つノードがたくさんあります。だからこそ、そのための省略記法が用意されています。
SGFは、手順のバリエーションを表現できます。囲碁を打つ人は検討の中で何度も手を戻します(これを試してみよう、うまくいかない、ではあれを試そう)し、SGFはそうした手順のバリエーションを扱えます。たとえば、次のようになります。
(;FF[4](;B[aa];W[ab])(;B[dd];W[ee]))
ここでは、ルートノードに2つのバリエーションがあります。1つ目(慣例により、実際に打たれた手を示します)は、黒が1-1に打つものです。黒は先生からこのファイルを受け取りました。先生は、ルートノードの2つ目の子にある、より理にかなった手を指摘しました。それがB[dd]です(4-4の点で、隅を取るごく標準的な布石です)。
1つのキーに複数の値を関連付けることができます。たとえば、次のとおりです。
(;FF[4];AB[aa][ab][ba])
ここでは、AB(黒を追加)を使って、盤面に黒石を3つ追加しています。
プロパティの値はすべてSGF Text型です。他の値の型を実装する必要はありません。Text型の完全なドキュメントも読めますが、重要な点のまとめを以下に示します。
\の直後にある場合は削除され、それ以外の場合は改行のまま残ります。\はエスケープ文字です。\の後にある空白以外の文字は、そのまま挿入されます。\の後にある空白文字は、上記のルールに従います。SGFには、\tや\nのような空白文字のためのエスケープシーケンスはありません。次の2つを混同しないよう注意してください。
文字列リテラル内のエスケープシーケンスは、SGFパーサーに渡される前に、そのプログラミング言語のパーサーによってすでに処理されている場合があります。
SGFには(そして一般に解析には)、もう少し複雑な点がいくつかありますが、ほとんどは無視してかまいません。入力はUTF-8でエンコードされているものと想定してください。テストにはcharsetプロパティが含まれないので、そこは気にしなくて大丈夫です。さらに、改行はすべてunixスタイル(\nで、テストに\rや\r\nは含まれません)であり、プロパティやノードなどの間の省略可能な空白もテストには含まれないものと想定してかまいません。