Cコンパイラを作る-その3

以下のサイトを参考にCコンパイラを書いていきます.エラーが出たところとかをメモがわりに残していきながらやっていきます. www.sigbus.info

arato-make.hatenablog.com

僕の現状の実装 github.com

STEP12

if else while forなどの予約語が増えててきたので以下のように配列を用意してそこから一致するものがあれば予約語,なければ変数になるようにしました.

char *reserve_word[] = {
     "==",
     "!=",
     "<=",
     ">=",
     "if",
     "else",
     "while",
     "for"
 };

 int get_reserved_len(char *p) {
     for (int i = 0; i < 8; i++) {
         if (memcmp(p, reserve_word[i], strlen(reserve_word[i])) == 0) {
             return strlen(reserve_word[i]);
         }
     }
     return 0;
 }
 int len = get_reserved_len(p);
 if (len != 0) {
       cur = new_token(TK_RESERVED, cur, p, len);
        p += len;
       continue;
 }

パース部分に関しては正直ごちゃごちゃになってしまいましたが,一応動作はするような形になりました.構文木等を気にせずとりあえず動作すればいい精神で書いてしまった部分があるので後々リファクタリングしたいです.

github.com

STEP13

ブロックに関しては,ブロックが終了するまでステートメントノードをつなげるような形にしました.コード生成時に最初まで遡ってから順に出力していくことで順番が担保できると思ってます.ブロックに含まれる式のベクタとかが正直よくわからなかったのですが,現状それっぽく動いてるのでよしとします.

 Node *block() {
     Node *node = stmt();
     if (check("}")){
         consume("}");
         return node;
     }
     return new_node(ND_BLOCK, node, block());
 }

github.com

Cコンパイラを作る-その2

以下のサイトを参考にCコンパイラを書いていきます.エラーが出たところとかをメモがわりに残していきながらやっていきます. www.sigbus.info

arato-make.hatenablog.com

僕の現状の実装 github.com

STEP9

比較演算子の部分を考慮しながらサイトを参考に書いていきました.

サイトではconsume_ident()を作成して変数を読み進めるような形式を取っていましたが,僕は数値に寄せる形でnew_node_ident()を作成して変数を読み進めるような形を取りました.

「;」をつけないと今までのテストが動かないので注意です.  

github.com

STEP10

localsの初期化はprogram()内で,offsetが0のLVarを作成して行いました. tokenize部分では以下のように複数文字受け入れるように変数取得部分を変更しました.

if('a' <= *p && *p <= 'z') {
    cur = new_token(TK_IDENT, cur, p++, 1);
    int i = 0;
    while ('a' <= *p && *p <= 'z') {
        i++;
        p++;
    }
    p -= i;

    cur = new_token(TK_IDENT, cur, p, i);

    p += i;
    continue;
}

github.com

STEP11

consume(TokenKind)を実装しないで,数値や変数と同じように処理する場合にはnode->lhs=expr()する前にtoken = token->nextをしないとトークンがTK_RETURNのまま進んでしまうので注意です.

https://github.com/arato-make/9cc/commit/893c5fbdb01a3a0cb1e8d5298c9d7b03bdef5567

Cコンパイラを作る-その1

下記のサイトを参考にしながらCコンパイラを作っています. エラーが出たところとかをメモがわりに残していきながらやりたいと思います.

https://www.sigbus.info/compilerbook

僕の現状の実装経過

github.com

STEP4

error_at(token->str, "数ではありません")

にコードをアップデートするとあるが,tokenizeの中ではtokenに値が代入されていないため,token->strではなく以下のようにpを渡すようにする.そうしないとトークナイズできなかった際にSegmentation faultが起こってしまう.

error_at(p, "トークナイズできません");

user_inputを初期化し忘れると無限ループするので注意.

STEP6

リファレンス実装とサイト実装で単項を複数受け入れるかどうかで実装差が存在していた.リファレンス実装のほうのテストコードを参考にしてテストしようとすると通らないので注意.

リファレンス実装では単項を複数受け入れるような実装にしているため「- - 1」などが解釈できるようになっているが,サイト実装では解釈できない.

STEP7

token->strには該当トークン部分の文字列だけしか入っていないと思ってしまっており,new_tokenする際に二文字だけ渡すようなコードを書こうとしてしまった.token->strは該当トークン文字列が始まるポインタが入っているので,そこから何文字を解釈するかを表すlenだけで特に他の変更は必要なかった.

STEP8

今まで作成したtest.cとか残ってるとmainが複数あるよってエラー出る.