Bracketeer™という、古くからありながら強力なメインフレーム用のソフトウェアを書く機会が与えられました。 その上で動くソフトウェアは、独自の言語で書かれています。 構文の多くは見慣れたものですが、角括弧、波括弧、丸括弧が_たくさん_あることに気づきます。 Bracketeer™は強力ですが、柔軟性に欠けています。 ソースコードの中に、対応の取れていない角括弧、波括弧、丸括弧が1つでもあると、Bracketeer™はクラッシュし、再起動しなければなりません。 そうならないために、Bracketeer™で実行する前に、角括弧、波括弧、丸括弧の対応が取れているかを確認するコードを書き始めます。
角括弧([])、波括弧({})、丸括弧(())、またはこれらの組み合わせを含む文字列が与えられます。
すべてのペアが正しく対応し、入れ子になっていることを確認してください。
それ以外の文字は無視します。
たとえば、"{what is (42)}?"はバランスが取れていますが、"[text}"はバランスが取れていません。
Tclはとてもシンプルな言語ですが、インタプリターがコードを解析する方法には、厄介なエッジケースがいくつかあります。
Tclの波括弧({})は、テキストのまとまりをクォートするための仕組みにすぎません。そのテキストはコードとしてもデータとしても解釈されます。波括弧の中には、入れ子になった波括弧を書くこともできますが、それらの波括弧の対応は取れていなければなりません。Tclのマニュアルページには、次のように書かれています。
波括弧は単語の中で入れ子になります。開き波括弧が1つ増えるごとに、対応する閉じ波括弧も1つ必要です(ただし、単語の中の開き波括弧または閉じ波括弧が_バックスラッシュでエスケープされている_場合は、対応する閉じ波括弧を探すときに数えられません)。
ここの表現は非常に厳密です。対応の取れていない開き波括弧や閉じ波括弧の文字を使いたい場合は、バックスラッシュでエスケープしなければなりません。なので、次のようにしてはいけません。
proc isOpenBrace {char} {
return [expr {$char eq "{"}]
# ......................^ will not work
}
次のようにする必要があります
proc isOpenBrace {char} {
return [expr {$char eq "\{"}]
# ......................^^ will work
}
これは、Tclのコメントの解析方法がほとんどの言語と異なるため、問題になることがあります。詳しい議論はTcl wikiにあります。
同様に、Tclでは角括弧([])をコマンド置換に使うため、二重引用符で囲んだ文字列の中であっても、開き角括弧のエスケープには注意が必要です。
連想配列の変数を除けば、丸括弧(())は単なる普通の文字です。