ChainCC開発中

　今回は自作DSLのChainCC (Chain type Compiler Creation script)のほとんどの処理が完成したので、紹介しようと思います。

# 開発経緯
　前に作った言語 ([ParserScript](https://github.com/MueLangDeveloper/ParserScript-Ver.3.0) (非推奨), [UCCScript](https://github.com/MueLangDeveloper/UCCScript)) と関係があるので、それらを踏まえて書きます。
## ParserScript
#### 強いところ
・コマンドベースだから簡単
・処理中に別の処理を書ける
#### 弱いところ
・コードを書く難易度が高め
・演算できない
・保守性低い
・時々、バグる
・読みづらい
## UCCScript
#### 強いところ
・BNF風に書ける
・制御構文がある
・演算ができる
・使いたい文字列を参照できる
#### 弱いところ
・実装が難しい
・仕様上のバグがある
・まだ読みづらい
#
　二つの言語には上のような長所と短所があります。なので、ChainCCの開発目標としては

・コマンドベースで簡単
・ある程度の制御構文なら簡単に再現できる
・演算ができる
・使いたい文字列を参照できる
・バグなし
・まあまあ読みやすい

です。
# どう解決したのか
　開発途中というのもあって、大体完成しています。
## ある程度の制御構文なら簡単に再現できる
ParserScript, UCCScript：「コードの先が分からない、、、」

　ParserScriptとUCCScriptは与えられた文字しかわかりません。「〜または〜」とか「〜に0回以上マッチ」の実装が複雑なのです。

ChainCC：「コマンドをまとめとけば良くね？（以下、このことを「グループ」と呼ぶ）」
```ccc
if not match
    .after match "\("
    .after call Expr
    .after match "\)"
```
```ccc
loop
    .after match "a"
```

　ChainCCは`.after`でコマンドをまとめられます。その間はコマンドは実行されずに読み込まれ、終端に来ると今まで読み込んだコマンドを実行します。
## 使いたい文字列を参照できる
UCCScript：「私は囲まれたパターンにマッチした文字列を参照できるのよ」

ParserScript：「そのせいで、処理は複雑になったし、仕様上のバグも発生したよね」

UCCScript：「...」

　実際、繰り返し中に配列の参照を二つ以上使うと、動作は問題ないが、バグることが確認されています。

ChainCC：「配列の参照はなくして、繰り返しの最後で削除すれば？」
```ccc
loop
    .after (
        ref R0
            .after match "a"
    )
    .after if <R0>
    .after push <R0>
    .after result last
    .after delete R0
```
　現在の仕様上、`R0`のパターンにマッチしなければ自動的に`R0`は消されるため、条件分岐が必要。
　
　ParserScriptの「処理中に別の処理を書ける」を利用したものです。UCCScriptとは違い、配列に保存しなくても、その場で処理できます。

## まあまあ読みやすい
　ParserScriptはとにかく分かりづらいコマンドが多すぎるので、作者 (私)自身もう忘れたので、UCCScriptとChainCCの比較をします。

　以下は文字を逆向きにするコード
UCCScript
```ucc:Grammar.ucc
First Sample End
$Sample In { <{ Char }> }
        Is (Load Index[$0+[0] 1 -])
           (ForB[0 \Index > !][
               @1[0 \Index]
               (Load Index[\Index 1 -])
            ]) 
        End
```
ChainCC
```ccc:Grammar.ccc
first Sample

label Sample
    loop
        .after (
            ref R0
                .after match "."
        )
        .after if <R0>
        .after push <R0>
        .after result first
        .after delete R0
end
```
圧倒的にChainCCの方が読みやすいですよね。
# lock, unlock (予定)
　グループの最初につけるタイプ。`lock`を使い、その後に続くグループを次回から、コマンド実行毎に実行する。`first`または`last`をつけて、いつ実行するのかを決める。
　`unlock`に`first`または`last`を付け、開放する
# 逆ポーランド記法に変換するコードを書いてみる
ChainCC
```ccc:Grammar.ccc
trim ' '
first Expression

label Factor
    ref R0
        .after match ""(-)?[0-9]+(\.[0-9]+)?""
    if not match
        .after if ""\(""
        .after match ""\(""
        .after (
            ref R0
                .after call Expression
                
        )
        .after match ""\)""
    if <R0>
        .after push <R0>
    if not <R0>
        .after push """"
    result last
end

label Term
    ref R0
        .after call Factor
    push ?<R0>
    ope rev
    gotob CCC_0001
    push <R0>
    result last
    #CCC_0000
    if not ""(\*|/)""
        .after goto CCC_0001
    ref R1
        .after match ""(\*|/)""
    ref R2
        .after call Factor
    if <R1>
        .after if <R2>
        .after push "" ""
        .after result last
        .after push <R2>
        .after result last
        .after push "" ""
        .after result last
        .after push <R1>
        .after result last
    if <R1>
        .after delete R1
    if <R2>
        .after delete R2
    goto CCC_0000
    #CCC_0001
end

label Expression
    ref R0
        .after call Term
    push ?<R0>
    ope rev
    gotob CCC_0001
    push <R0>
    result last
    #CCC_0000
    if not ""(\+|-)""
        .after goto CCC_0001
    ref R1
        .after match ""(\+|-)""
    ref R2
        .after call Term
    if <R1>
        .after if <R2>
        .after push "" ""
        .after result last
        .after push <R2>
        .after result last
        .after push "" ""
        .after result last
        .after push <R1>
        .after result last
    if <R1>
        .after delete R1
    if <R2>
        .after delete R2
    goto CCC_0000
    #CCC_0001
end
```

--追記
・`Factor`、`Expression`まではいいですが`Term`を使うとエラーが発生しました。呼び出しの深さにも対応させる予定です

--追記の追記
・オーバーフローしていたので、gotoコマンド、gotobコマンド（条件gotoコマンド）を導入して、呼ばれる関数の数を減らして、対応しました。
　
# 終わりに
　現在、ChainCCにはラベルの機能などがないので、そこを実装して完成です。

--追記
・バグがまだたくさんありますが、公開しました（[ChainCC-Ver.0.0](https://github.com/MueLangDeveloper/ChainCC-Ver.0.0)）。
・バグ修正とともに機能も追加して対応しています。

--追記の追記
・完成版を公開しました（[ChainCC-Ver.1.0](https://github.com/MueLangDeveloper/ChainCC-Ver.1.0)）。

--追記の追記の追記
・ChainCC 1.0の修正版：[ChainCC-Ver.2.0](https://github.com/MueLangDeveloper/ChainCC-Ver.2.0)