HeartScript は、Heart のデータファイルを記述するためのスクリプト言語です。
HeartScript では、中括弧「{」「}」で囲まれた文字列を、特別な意味で用います。中括弧で囲まれた文字列は、最終的に画面上に出力されることはありません。中括弧で囲まれた文字列のうち、特別な意味を持つものを タグ(Tag) と呼びます。定義されているタグについては、 タグ一覧 を参照してください。また、タグ以外の中括弧で囲まれた文字列を コメント と呼びます。それらの中括弧で囲まれた文字列は、実行時に解釈(評価)されます。
タグはそれぞれ、何かの動作を起こしたり、他の文字列と置換されたりします。この時置換された文字列を、そのタグの 返り値 と呼びます。また、そのタグがその文字列を返す、とも表現します。空文字列(長さ0の文字列)を返すタグも存在します。
また、タグによってはいくつかのパラメータを渡す必要があるものがあります。このパラメータのことを、引数(ひきすう) と呼びます。引数を持つタグは、渡された引数によって違う動作をしたり、違う文字列を返したりします。通常、引数の区切りには「|」が使われます。
タグやコメントは、以下のように入れ子(ネスト構造)にすることができます。
{And{Eq{OperateMessage}|HCCalled}|{IsSameD{BirthDay}|{Date}}}
HeartScript の評価は、2段階に分かれます。ExpandTags と呼んでいる基本的な処理と、実行環境(Winodws版Heart であれば Heart.exe)独自の処理です。ExpandTags で評価されるタグを 基本タグ と呼び、実行環境が独自に評価するタグを 拡張タグ と呼んでいます。基本的に画面表示に依存するタグなどは拡張タグに含まれますが、正確な区分については タグ一覧 を参照してください。
タグがネストした時に問題となるのは解釈の順序ですが、ExpandTags の原則は以下のとおりです。ExpandTags では、基本タグ以外のタグは認識されず、拡張タグもコメントであると判断されます。
具体的に評価の過程を挙げると、以下のようになります。(aaa〜iii は全て空文字列を返すタグとします)
aaa{bbb{ccc{ddd}{eee}}{fff}}{ggg{hhh}}{iii}
aaa{bbb{ccc{eee}}{fff}}{ggg{hhh}}{iii}
aaa{bbb{ccc}{fff}}{ggg{hhh}}{iii}
aaa{bbb{fff}}{ggg{hhh}}{iii}
aaa{bbb}{ggg{hhh}}{iii}
aaa{ggg{hhh}}{iii}
aaa{ggg}{iii}
aaa{iii}
aaa
原則の最後、「ただし、2階層目以下のコメントは、それ自身を返す」は、拡張タグを有効にするためです。本来は最浅層(1階層目)だけを残せばいいのですが、{If} 基本タグによる分岐などの便宜上2階層目まで残しています。さらに複雑なネスト中で拡張タグを有効にしたい場合は、{Scriptize} 基本タグを使います。また、意図的に展開の順序に変更を加えたい場合にも {Scriptize} 基本タグを使います。
HeartScriptでは、データは全て文字列として評価されます。論理(Boolean)型の True(真) は文字列「True」、False(偽) は文字列「False」として評価され、整数(Integer)や実数(8または10バイト)値も全て一旦文字列として評価されます。また、文字列の比較の際には一旦半角大文字化してから比較します。半角大文字化する対象の文字は「abcdefghijklmnopqrstuvwxyz0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!”#$%&’()*+,−./:;<=>?@[¥]^_`{|} ̄'」です。これらの文字はそれぞれ一旦「ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&''()*+,-./:;<=>?@[\]^_`{|}~'」に変換されてから比較されます。
通常の会話ではない、特殊な状況下では {OperateMessage} 基本タグが返す制御メッセージを元に動作を決定します。通常の場合、制御メッセージは空文字列です。必要な時に、実行環境独自のメッセージがセットされます。
HeartScript における正規表現は、プログラミング言語 awk 及び egrep にてサポートされている拡張正規表現をベースにし、さらに少しの拡張を加えたものです。
実装は、bmonkey さんが http://homepage1.nifty.com/bmonkey/ においてフリーウェアとして公開されている「(仮)AWK言語 正規表現関数群 version 0.30alpha」に少し手を加えたものによって行っています。有益な関数群を公開して下さっている bmonkey さんに感謝するとともに、今後のご活躍を期待いたします。
正規表現(RE: Regular Expression)とは、幾つかの文字列を一つの形式で表現するための表現方法です。通常、文字列を表現するというのはその文字列そのものを挙げることを指しますが、普通の文字列では表現するのが難しいものを表現するための方法が正規表現です。その観点から見ると、俗にワイルドカードと呼ばれているものも正規表現の一種だと言えます。
例えば、正規表現を用いると「aで始まりyで終わる文字列」のことを「a.*y」のように表現することができます。Heart では、ユーザーの入力に対する人格の返答を絞り込む際に正規表現を利用しています。
正規表現の解説によく用いられる言い回しについて。
通常、文字列は1文字以上の連続する文字によって構成されます。しかし、集合論の観点から見ると非常に便利で綺麗な概念なので、0文字もまた文字列とみなします。この0個の文字によって構成される文字列を、空文字列と呼びます。実際に正規表現を使う際に空文字列のことを意識することは少ないと思いますが、よく出てくる言葉です。
ある正規表現がある文字列と合致した時、その正規表現がその文字列に「マッチした」と言います。
例えば「a.*y」という正規表現は、「angry」にも「accessory」にも合致する、つまりそれらの文字列を表現することができる正規表現ですが、このとき「a.*y」は「angry」にも「accessory」にもマッチする、と言います。逆に「a.*y」がマッチする文字列の例としては、「angry」や「accessory」が挙げられます。
一見すると普通の文字に見えるのに、特別な意味が割り振られている文字のことを言います。このおかげで、正規表現は普通の文字列のみの表現とは異なる意味を持つようになります。同じメタキャラクタであっても、文脈(コンテキスト)によって意味が異なることがあるので注意が必要です。
HeartScriptで有効なメタキャラクタは、以下の13文字です(ASCII 文字コード順)。
# | $ | ( | ) | * | + | . | ? | [ | \ | ] | ^ | | |
正規表現の構成要素は、次の3つに分けられます。
演算子の優先順位 | ||
---|---|---|
高 | 1 | 繰り返し演算子「*」「+」「?」 |
2 | 連結演算子 | |
低 | 3 | 選択演算子「|」 |
(以下、RE、RE1、RE2は任意の正規表現を表す)