コンパイラ作成(105) 引数が配列の関数
今回の目標
コマンドライン引数を表示できるように対応するよ。
// コマンドライン int main(int argc, char *argv[]) { for(int i = 0; i < argc; i = i + 1) printf("argv[%d]=%s\n", i, argv[i]); }
関数定義の解析さえ頑張れば大丈夫かな。
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 var_name = str if kind != TK::ID then if type == "void" then perror "invalid type 'void'" else perror "wrong parameter name" end end kind, str = @lex.gettoken if kind == TK::SYMBOL && str == "[" then kind, str = @lex.gettoken if kind != TK::SYMBOL || str != "]" then perror end type += "*" end paratype << type print "para "+var_name+"\n" if $opt_d size = sizeof type @lvarsize += size parametersize << size if check_var var_name then perror "redefinition parameter \"" + var_name +"\"" end if type == "void" then perror "invalid type 'void'" end set_var var_name, [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
配列だったら*に変換してるよ。これで問題ないはず。
動作テスト
~/myc$ myc q11.myc ~/myc$ ./q11 abc zxc 123 argv[0]=./q11 argv[1]=abc argv[2]=zxc argv[3]=123 ~/myc$
大丈夫だね。大分配列の実装できてきたかな。次回は何やろうかな。エラー周りのテストかな。問題なければ配列の初期化に進みたいけど、結構難しいかな。