行とブロック構造
Pasta の世界は、行が積み重なって「ブロック」を作りますの。 シーンという大きな器の中に、台詞や呼び出しがきちんと収まる――その仕組みを見ていきましょう。 構造を掴めば、辞書ファイル全体が手に取るように分かりますわよ。
Pasta は行指向文法であり、各行は改行で終わる。行頭のマーカーとインデントの有無により行の種類が決まり、それらが階層的なブロック構造を形成する。
行の種類
行はインデントの有無で大きく二分される。
インデント不要の行(行頭にインデントなし=グローバルレベル)
| 行種 | マーカー | 説明 |
|---|---|---|
| グローバルシーン | * / * | グローバルブロックを開始 |
| グローバル単語定義 | @ / @ | ファイル全体で参照可能な単語定義 |
| アクター辞書 | % / % | アクター単位の単語辞書を定義 |
| Lua ブロック | ``` / ```lua | 直前のグローバルシーンに属する複数行コード |
| コメント | # / # | 処理されない |
インデントが必要な行(行頭にインデントあり=下層レベル)
| 行種 | マーカー | 説明 |
|---|---|---|
| ローカルシーン | ・ / - | グローバルシーン配下のローカルブロック開始 |
| 属性定義 | & / & | シーンにメタデータを付与(処理は将来予定) |
| アクション行 | (なし) | キャラクターの発言 |
| Call | > / > | シーンを呼び出す |
| 選択肢行 | @? / @? | プレイヤー選択肢の定義 |
| 変数代入 | $ / $ | 変数を宣言・代入 |
| ローカル単語定義 | @ / @ | 親シーン内で参照可能な単語定義 |
Note: コメント行はインデントの有無にかかわらず、どの位置にも置ける(常に「コメント」として解釈される)。
ブロック構造
グローバルシーン
グローバルシーンは行頭が *(または *)で始まる。シーン本体はインデントした行で記述する。
*挨拶
ぱすた:こんにちは!
ラザニア:ごきげんよう!
同名のグローバルシーンを複数定義でき、呼び出し時に前方一致で候補が列挙され、そこからランダムに 1 つが選択される(詳細は Call / Jump)。
*挨拶
ぱすた:おはよう!
*挨拶
ぱすた:こんばんは!
グローバルシーンの内部構造
グローバルシーンブロックは、宣言行に続いて次の要素で構成される。
- グローバルシーン行:
*グローバル名 - 属性行: 0 個以上の
&key:value(シーン全体のメタデータ/処理は将来予定) - 暗黙ローカル開始ブロック(
__start__): ローカルシーン宣言なしで、Lua ブロック・アクション行・Call 行・変数代入行を格納できる暗黙のブロック - ローカルブロック: 0 個以上の明示的ローカルシーン(
・ローカル名)
グローバルシーンが Call の対象になると、まず暗黙の __start__ ブロックが実行される。
ローカルシーン
ローカルシーンは親シーン内でのみアクセス可能で、インデント+・(または -)で始まる。
*メインメニュー
ぱすた:何をしますか?
>選択肢1
・選択肢1
ぱすた:選択肢1が選ばれました
・選択肢2
ぱすた:選択肢2が選ばれました
ローカルシーンブロックは、宣言行・属性行(0 個以上)・コンテンツ行(変数代入/アクション行/Call 行/選択肢行)で構成される。
Lua ブロックの配置
Lua ブロックは暗黙ローカル開始ブロック(__start__)内に置かれる。インデント不要だが、構造上は直前のグローバルシーンに属する。
*会話
```lua
function SCENE.initialize(act)
local save, var = act:init_scene(SCENE)
save.talked = true
end
```
こんにちは
Lua ブロックには次の制約がある。
- 関数定義のみ許可:
function ...で始まる関数定義のみ記述できる。local x = 10のような変数宣言・トップレベルのステートメントは許可されない。 - パーサーは内部を解釈せず透過する。関数定義のみで成立するかはトランスパイラ層が検証し、誤りはトランスパイラ層以降でコンパイルエラーとなる。
詳細は Lua セクションを参照。
属性(将来変更あり)
属性は &属性名:値 の形式で、シーン定義の直後にのみ記述できる。
*会話
&author:Alice
&genre:comedy
ぱすた:こんにちは!
配置ルール:
- グローバルシーンの直後 → グローバルシーンに付与
- ローカルシーンの直後 → ローカルシーンに付与
- アクション行や変数代入行の後には配置できない
将来変更あり: 属性の構文は現在パーサーで受理されるが、トランスパイラ・ランタイムでの処理は将来予定である。現状では属性を指定しても処理には反映されない。仕様は将来変更され得る(権威は doc/spec/08-attributes.md)。
コメント
# または # から行末までがコメントとして扱われ、構造・セマンティクスに影響しない。どの位置にも置ける。
*テスト
# これはコメントです
ぱすた:これは実行されます
# 全角シャープでもOK
インデントの判定
インデントは「有るか・無いか」のバイナリ判定のみで扱われ、深さは判定されない。インデントレベルが一貫している必要もない。
*会話 ← インデントなし(グローバルレベル)
&author:Alice ← インデントあり(下層レベル)
・選択肢1 ← インデントあり(下層レベル)
Alice:こんにちは ← インデントあり(下層レベル)
構造が見えてくると、辞書ファイルがぐっと書きやすくなりますでしょう? 次は、シーンとシーンをつなぐ「Call / Jump」を覚えていきましょう。熱く参りますわよ!
権威的仕様: 行・ブロック構造の厳密な定義は doc/spec/03-block-structure.md を参照。