---
# System prepended metadata

title: KSP備忘録：見かけ以上に内部の処理は大変だった
tags: [ksp, kontakt]

---

# KSP備忘録：見かけ以上に内部の処理は大変だった

###### tags: `ksp` `kontakt`

変数宣言、初期値代入。パッと見はシンプルそうに見えて、構文解析〜意味解析を実装してみると非常に複雑であると感じた。

## その１

~~~
declare %a[ 3 ] := ( 1, 2, 3 ) {1}
declare ui_table %a[3]( 1, 1 ) {2}
~~~

パッと見はどちらも配列、似たような初期化ぶ記述に見えるが、内部的には全く別物。

1の方は配列初期化子。 2はコンストラクタ相当。例としてJava言語で書くなら

~~~
int[] a = { 1, 2, 3 };
UITable a = new UITable( 3, 1, 1, 1 );
~~~

に相当する。ui_#### データ型宣言で括弧の有無、括弧の意味、括弧内の引数の数が異なる。

引数動的に対応するにあたり、外部ファイルにテーブル化して動的にシンボルテーブルを構築している。

~~~
ui_button	N	N	I	I
ui_knob	N	Y	I	I	I	I
ui_file_selector	N	N	I
ui_label	N	Y	I	I	I
ui_level_meter	N	N	I
ui_menu	N	N	I
ui_slider	N	Y	I	I	I
ui_switch	N	N	I
ui_table	N	Y	I[]	I	I	I
ui_text_edit	N	N	S
ui_value_edit	N	Y	I	I	I	I
ui_waveform	N	Y	I	I	I	I
ui_xy	N	N	R[]
~~~



話を戻すと、

~~~
declare %a[ 3 ] := ( 1, 2, 3 ) {1}
declare ui_table %a[3]( 1, 1 ) {2}
~~~

今回取った対応は、構文解析フェーズでは

- プリミティブ型
- 配列型

に留め、意味解析フェーズで解決を図った。色々考えたがUI変数宣言のBNF、という記述は矛盾が出て断念した。

1. 構文解析フェーズで、ui_#### が含まれていたらフラグだけ立てる
2. 意味解析フェーズでフラグを見る
3. もしUI型なら初期化子が必要かどうかをシンボルテーブルから問い合わせ
    1. 配列要素数の論理解析 
    2. 初期化が宣言時に必須なら、シンボルテーブルとデータ型の照らし合わせる
    2. もし初期化子に := の記述がされていたら、文法エラーとして扱う
4. もし配列型なら
    1. 配列要素数の論理解析 
    2. 初期化子（ `:= (0,1,2,....)` ）のノードが続くならトラバース

書いててもどかしいが、

- := の有無
- ui_#### の有無
- 配列の定義の有無
- 初期値代入不要か否か

などのパターンの総当り戦で成り立っている。

[コードで表現するとこうなる](https://github.com/r-koubou/KSPSyntaxParser/blob/feature/obfuscator/src/java/net/rkoubou/kspparser/analyzer/SemanticAnalyzer.java)