# 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)