# KSP備忘録:見かけ以上に内部の処理は大変だった
###### tags: `ksp` `kontakt`
変数宣言、初期値代入。パッと見はシンプルそうに見えて、構文解析〜意味解析を実装してみると非常に複雑であると感じた。
## その1
~~~
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)