コンパイラ作成(92) 引数の無い関数の定義でのvoid

今回の目標

いくつかテストしてる時に気が付いたんだけど、voidを使って関数に引数が無いことを明示する記述の仕方、まだ対応してなかったよ。

// 関数の呼び出し
int answer(void)
{
    //  Answer to the Ultimate Question of Life, the Universe, and Everything
    return 42;
}

int main()
{
    printf("%d\n",answer());
}

簡単にできそうなんでやってみるよ。

function

引数の処理のところを修正するよ。

    # 引数の処理
    kind, str = @lex.gettoken
    loop do
      if kind == TK::SYMBOL && str == ")" then break end
      if kind == TK::TYPE then
        if str == "extern" then perror "invalid 'extern'" end
        type = str
        kind, str = @lex.gettoken
        loop do
          if kind != TK::SYMBOL || str != "*" then break end
          type += str
          kind, str = @lex.gettoken
        end
        if type == "void" \
           && kind == TK::SYMBOL && str == ")" \
           && paratype == []
        then
          break
        end
        paratype << type
        if kind != TK::ID then
          if type == "void" then
            perror "invalid type 'void'"
          else
            perror "wrong parameter name"
          end
        end
        print "para "+str+"\n" if $opt_d
        size = sizeof type
        @lvarsize += size
        parametersize << size
        if check_var str then perror "redefinition parameter \"" + str +"\"" end
        if type == "void" then
          perror "invalid type 'void'"
        end
        set_var str, [type,@lvarsize]
      else
        perror
      end
      if kind != TK::SYMBOL || str != ")" then
        kind, str = @lex.gettoken
      end
      if kind == TK::SYMBOL && str == "," then
        kind, str = @lex.gettoken
      end
    end

voidが一個だけの場合は受け付けるようにして、それ以外の時はエラーになるように修正。初めは単純な処理だったのが、こんがらがった処理になっちゃったなあ。

動作テスト
~/myc$ myc l6.myc
~/myc$ ./l6
42
~/myc$

コンパイル通るようになったよ。もういっちょ行ってみる。

// 関数の呼び出し
int answer(int a,void)
{
    //  Answer to the Ultimate Question of Life, the Universe, and Everything
    return 42;
}

int main()
{
    printf("%d\n",answer());
}

今度はエラーにしなきゃいけないパターン。

~/myc$ myc err44.myc
err44.myc:2:22 error: invalid type 'void'
~/myc$

ちゃんとエラーになったよ。次回はint型からdouble型への変換をやりたいなあ。今回それをやろうと思ってたんだけど、voidが未対応だって気付いたら、気になって気になってついついそっちを先にやっちゃったよ。