expr_t parse_paren_expr(tokenizer_t t) { eat_it(t, TOK_LPAREN); expr_t expr = parse_expr(t); eat_it(t, TOK_RPAREN); return mk_expr_paren(t->filename, t->line, expr); }
stmt_t parse_stmt_return(tokenizer_t t) { eat_it(t, TOK_RETURN); expr_t e = parse_expr(t); eat_it(t, TOK_SEMICOLON); return mk_stmt_return(t->filename, t->line, e); }
fun_def_t parse_fun_def(tokenizer_t t) { // 型宣言を食べる (int 以外に増やすなら変える) eat_it(t, TOK_INT); struct token tok = cur_tok(t); char *f = strdup(tok.name); eat_it(t, TOK_ID); // { eat_it(t, TOK_LPAREN); var_decl_list_t params = mk_var_decl_list(t); while(1){ if(cur_tok(t).kind == TOK_RPAREN){ break; }else{ var_decl_list_add(params, parse_param(t)); if(cur_tok(t).kind == TOK_COMMA){ eat_it(t, TOK_COMMA); continue; }else{ break; } } } eat_it(t, TOK_RPAREN); // } stmt_t body = parse_stmt_compound(t); return mk_fun_def(t->filename, t->line, f, params, body); }
stmt_t parse_stmt_while(tokenizer_t t) { char *filename = cur_tok(t).filename; int line_num = cur_tok(t).line_num; eat_it(t, TOK_WHILE); eat_it(t, TOK_LPAREN); expr_t e = parse_expr(t); eat_it(t, TOK_RPAREN); stmt_t body = parse_stmt(t); return mk_stmt_while(filename, line_num, e, body); }
var_decl_t parse_decl(tokenizer_t t) { eat_it(t, TOK_INT); char* v; v = strdup(cur_tok(t).name); eat_it(t, TOK_ID); eat_it(t, TOK_SEMICOLON); return mk_var_decl(t->filename, t->line, v); }
var_decl_t parse_param(tokenizer_t t) { eat_it(t, TOK_INT); struct token tok = cur_tok(t); char *v = (char *) malloc (sizeof(char) * strlen(tok.name)); strcpy(v, tok.name); eat_it(t, TOK_ID); return mk_var_decl(t->filename, t->line, v); }
stmt_t parse_stmt_while(tokenizer_t t) { /** while(1) */ eat_it(t, TOK_WHILE); eat_it(t, TOK_LPAREN); expr_t e = parse_expr(t); eat_it(t, TOK_RPAREN); /** { ; ; ; } */ stmt_t body = parse_stmt(t); return mk_stmt_while(t->filename, t->line, e, body); }
stmt_t parse_comp_stmt(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; eat_it(t, TOK_LBRACE); stmt_list_t c = mk_stmt_list(); var_decl_list_t d = parse_var_decl(t); stmt_t x; while(cur_tok(t).kind != TOK_RBRACE) { x = parse_stmt(t); stmt_list_add(c, x); } eat_it(t, TOK_RBRACE); return mk_stmt_compound(filename, line, d, c); }
op_kind_t parse_add_oper(tokenizer_t t) { if(cur_tok(t).kind == TOK_PLUS) { eat_it(t, TOK_PLUS); return op_kind_bin_plus; } else if(cur_tok(t).kind == TOK_MINUS) { eat_it(t, TOK_MINUS); return op_kind_bin_minus; } else { printf("exit_3\n"); exit(1); } }
op_kind_t parse_equal_oper(tokenizer_t t) { if(cur_tok(t).kind == TOK_EQ) { eat_it(t, TOK_EQ); return op_kind_eq; } else if(cur_tok(t).kind == TOK_NEQ) { eat_it(t, TOK_NEQ); return op_kind_neq; } else { printf("exit_1\n"); exit(1); } }
stmt_t parse_stmt_if(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; eat_it(t, TOK_IF); eat_it(t, TOK_LPAREN); expr_t e = parse_expr(t); eat_it(t, TOK_RPAREN); stmt_t th = parse_stmt(t); stmt_t el = NULL; if(cur_tok(t).kind == TOK_ELSE) { eat_it(t, TOK_ELSE); el = parse_stmt(t); } return mk_stmt_if(filename, line, e, th, el); }
fun_def_t parse_fun_difinition(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; parse_type_expr(t); char *f0; char *f; f0 = parse_identifier(t); f = (char *)malloc(sizeof(char) * strlen(f0) + 1); strcpy(f, f0); eat_it(t, TOK_LPAREN); var_decl_list_t param = parse_para_list(t); eat_it(t, TOK_RPAREN); stmt_t body = parse_comp_stmt(t); return mk_fun_def(filename, line, f, param, body); }
expr_t parse_id_expr(tokenizer_t t){ char* v = strdup(cur_tok(t).name); eat_it(t, TOK_ID); // printf("parse_id_expr: %s\n", v); if(cur_tok(t).kind == TOK_LPAREN) { // 関数呼び出し eat_it(t, TOK_LPAREN); expr_list_t list = parse_arg_expr(t); eat_it(t, TOK_RPAREN); return mk_expr_call(t->filename, t->line, v, list); } else { // 変数名 return mk_expr_id(t->filename, t->line, v); } }
expr_t parse_intlit_expr(tokenizer_t t){ sprintf(cur_tok(t).name, "%d", cur_tok(t).ival); char* v = strdup(cur_tok(t).name); // printf("name: %s\n", cur_tok(t).name); eat_it(t, TOK_INT_LITERAL); return mk_expr_int_literal(t->filename, t->line, v); }
op_kind_t parse_unary_oper(tokenizer_t t) { if(cur_tok(t).kind == TOK_PLUS) { eat_it(t, TOK_PLUS); return op_kind_un_plus; } else if(cur_tok(t).kind == TOK_MINUS) { eat_it(t, TOK_MINUS); return op_kind_un_minus; } else if(cur_tok(t).kind == TOK_BANG) { eat_it(t, TOK_BANG); return op_kind_logneg; } else { printf("exit_6\n"); exit(1); } }
op_kind_t parse_multi_oper(tokenizer_t t) { if(cur_tok(t).kind == TOK_MUL) { eat_it(t, TOK_MUL); return op_kind_mult; } else if(cur_tok(t).kind == TOK_DIV) { eat_it(t, TOK_DIV); return op_kind_div; } else if(cur_tok(t).kind == TOK_REM) { eat_it(t, TOK_REM); return op_kind_rem; } else { printf("exit_4\n"); exit(1); } }
var_decl_t parse_para(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; eat_it(t, TOK_INT); char * f0 = parse_identifier(t); char *f = (char *)malloc(sizeof(char) * strlen(f0) + 1); strcpy(f, f0); return mk_var_decl(filename, line, f); }
stmt_t parse_stmt_if(tokenizer_t t) { eat_it(t, TOK_IF); eat_it(t, TOK_LPAREN); expr_t e = parse_expr(t); eat_it(t, TOK_RPAREN); stmt_t body = parse_stmt(t); stmt_t else_body = NULL; if(cur_tok(t).kind == TOK_ELSE){ eat_it(t, TOK_ELSE); else_body = parse_stmt(t); }else{ // else はまだ空文 else_body = NULL; } return mk_stmt_if(t->filename, t->line, e, body, else_body); }
expr_t parse_expr(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; expr_t e0 = parse_equal_expr(t); if(cur_tok(t).kind == TOK_ASSIGN) { eat_it(t, TOK_ASSIGN); expr_t e1 = parse_equal_expr(t); return mk_expr_bin_op(filename, line, op_kind_assign, e0, e1); } else { return e0; } }
op_kind_t parse_relat_oper(tokenizer_t t) { if(cur_tok(t).kind == TOK_LT) { eat_it(t, TOK_LT); return op_kind_lt; } else if(cur_tok(t).kind == TOK_GT) { eat_it(t, TOK_GT); return op_kind_gt; } else if(cur_tok(t).kind == TOK_LE) { eat_it(t, TOK_LE); return op_kind_le; } else if(cur_tok(t).kind == TOK_GE) { eat_it(t, TOK_GE); return op_kind_ge; } else { printf("exit_2\n"); exit(1); } }
expr_t parse_unary_expr(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; char * f =(char *)safe_malloc(sizeof(char) * 50) ; if(cur_tok(t).kind == TOK_INT_LITERAL) { strcpy(f, cur_tok(t).num); f = (char *)realloc(f, sizeof(char) * strlen(f) + 1); eat_it(t, TOK_INT_LITERAL); return mk_expr_int_literal(filename, line, f); } else if(cur_tok(t).kind == TOK_ID) { strcpy(f, parse_identifier(t)); f = (char *)realloc(f, sizeof(char) * strlen(f) + 1); if(cur_tok(t).kind == TOK_LPAREN) { eat_it(t, TOK_LPAREN); expr_list_t args = parse_arg_expr_list(t); eat_it(t, TOK_RPAREN); return mk_expr_call(filename, line, f, args); } else { return mk_expr_id(filename, line, f); } } else if(cur_tok(t).kind == TOK_LPAREN) { eat_it(t, TOK_LPAREN); expr_t e = parse_expr(t); eat_it(t, TOK_RPAREN); return mk_expr_paren(filename, line, e); } else if((cur_tok(t).kind == TOK_PLUS)|(cur_tok(t).kind == TOK_MINUS)|(cur_tok(t).kind == TOK_BANG)) { op_kind_t op = parse_unary_oper(t); expr_t exp = parse_unary_expr(t); return mk_expr_un_op(filename, line, op, exp); } else { printf("exit_5\n"); exit(1); } }
var_decl_list_t parse_var_decl(tokenizer_t t) { var_decl_list_t d = mk_var_decl_list(); char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; while(cur_tok(t).kind == TOK_INT) { parse_type_expr(t); char * f =(char *)malloc(sizeof(char) * 100); strcpy(f, parse_identifier(t)); var_decl_t x = mk_var_decl(filename, line, f); var_decl_list_add(d, x); eat_it(t, TOK_SEMICOLON); } return d; }
expr_list_t parse_arg_expr_list(tokenizer_t t) { expr_list_t l = mk_expr_list(); expr_t x; if(cur_tok(t).kind != TOK_RPAREN) { x = parse_expr(t); expr_list_add(l, x); while(cur_tok(t).kind != TOK_RPAREN) { eat_it(t, TOK_COMMA); x = parse_expr(t); expr_list_add(l, x); } } return l; }
stmt_t parse_stmt_compound(tokenizer_t t){ stmt_list_t list = mk_stmt_list(); var_decl_list_t decls = mk_var_decl_list(); eat_it(t, TOK_LBRACE); // printf("var_decl_list_add begin\n"); // printf("call: parse_stmt_compound\n"); while(1){ // 型宣言じゃなかったら修了 if(cur_tok(t).kind != TOK_INT){ break; }else{ // printf("var_decl_list_add\n"); var_decl_list_add(decls, parse_decl(t)); } } while(1){ if(cur_tok(t).kind != TOK_RBRACE){ // printf("stmt_list_add\n"); stmt_t s = parse_stmt(t); stmt_list_add(list, s); // printf("s->kind: %d\n", s->kind); }else{ // } でリスト終了 break; } } eat_it(t, TOK_RBRACE); stmt_t comp = mk_stmt_compound(t->filename, t->line, decls, list); return comp; }
/** * parse expression */ expr_t parse_expr(tokenizer_t t){ expr_t expr_left, expr_right; expr_left = parse_eq_expr(t); struct token tok = cur_tok(t); if(tok.kind == TOK_ASSIGN){ eat_it(t, TOK_ASSIGN); expr_right = parse_expr(t); expr_t assign_expr = mk_expr_bin_op(t->filename, t->line, op_kind_assign, expr_left, expr_right); return assign_expr; }else{ // これは式文 return expr_left; } }
expr_t parse_op_expr(tokenizer_t t) { // struct token tok = cur_tok(t); expr_t expr; if(cur_tok(t).kind == TOK_BANG){ eat_it(t, TOK_BANG); expr = parse_unary_expr(t); return mk_expr_un_op(t->filename, t->line, op_kind_logneg, expr); }else if(cur_tok(t).kind == TOK_PLUS){ eat_it(t, TOK_PLUS); expr = parse_unary_expr(t); return mk_expr_un_op(t->filename, t->line, op_kind_un_plus, expr); }else if(cur_tok(t).kind == TOK_MINUS){ eat_it(t, TOK_MINUS); expr = parse_unary_expr(t); return mk_expr_un_op(t->filename, t->line, op_kind_un_minus, expr); }else{ syntax_error(t, "error: parse_op_expr (expected TOK_BANG, TOK_PLUS, TOK_MINUS)"); return NULL; // exit } // } }
var_decl_list_t parse_para_list(tokenizer_t t) { var_decl_list_t param = mk_var_decl_list(); if(cur_tok(t).kind == TOK_RPAREN) { } else if(cur_tok(t).kind == TOK_INT) { var_decl_t x = parse_para(t); var_decl_list_add(param, x); while(cur_tok(t).kind == TOK_COMMA) { eat_it(t, TOK_COMMA); x = parse_para(t); var_decl_list_add(param, x); } } return param; }
expr_t parse_add_expr(tokenizer_t t){ expr_t expr_left, expr_right; expr_left = parse_mult_expr(t); struct token tok = cur_tok(t); while(tok.kind == TOK_PLUS || tok.kind == TOK_MINUS){ eat_it(t, TOK_ANY); // なんでも食べる expr_right = parse_mult_expr(t); expr_left = mk_expr_bin_op(t->filename, t->line, (tok.kind == TOK_PLUS) ? op_kind_bin_plus : op_kind_bin_minus // +, - のどちらかしかない , expr_left, expr_right); // left にたたんでいく tok = cur_tok(t); } return expr_left; }
expr_t parse_eq_expr(tokenizer_t t){ expr_t expr_left, expr_right; expr_left = parse_relat_expr(t); struct token tok = cur_tok(t); while(tok.kind == TOK_EQ || tok.kind == TOK_NEQ){ eat_it(t, TOK_ANY); // なんでも食べる expr_right = parse_relat_expr(t); expr_left = mk_expr_bin_op(t->filename, t->line, (tok.kind == TOK_EQ) ? op_kind_eq : op_kind_neq // == , != のどちらかしかない , expr_left, expr_right); // left にたたんでいく tok = cur_tok(t); } return expr_left; }
stmt_t parse_stmt(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; expr_t e; switch(cur_tok(t).kind) { case TOK_SEMICOLON: eat_it(t, TOK_SEMICOLON); return mk_stmt_empty(filename, line); break; case TOK_CONTINUE: eat_it(t, TOK_CONTINUE); eat_it(t, TOK_SEMICOLON); return mk_stmt_continue(filename, line); break; case TOK_BREAK: eat_it(t, TOK_BREAK); eat_it(t, TOK_SEMICOLON); return mk_stmt_break(filename, line); break; case TOK_RETURN: eat_it(t, TOK_RETURN); e = parse_expr(t); eat_it(t, TOK_SEMICOLON); return mk_stmt_return(filename, line, e); break; case TOK_IF: return parse_stmt_if(t); break; case TOK_WHILE: return parse_stmt_while(t); break; case TOK_LBRACE: return parse_comp_stmt(t); break; default: e = parse_expr(t); eat_it(t, TOK_SEMICOLON); return mk_stmt_expr(filename, line, e); break; } }