コンパイラ作成(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が未対応だって気付いたら、気になって気になってついついそっちを先にやっちゃったよ。