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); }
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); }
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_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); }
expr_t parse_multi_expr(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; expr_t e = parse_unary_expr(t); while((cur_tok(t).kind == TOK_MUL)|(cur_tok(t).kind == TOK_DIV)|(cur_tok(t).kind == TOK_REM)) { op_kind_t op = parse_multi_oper(t); expr_t e0 = parse_unary_expr(t); e = mk_expr_bin_op(filename, line, op, e, e0); } return e; }
expr_t parse_relat_expr(tokenizer_t t) { char * filename = cur_tok(t).filename; int line = cur_tok(t).line_num; expr_t e = parse_add_expr(t); while((cur_tok(t).kind==TOK_LT)|(cur_tok(t).kind==TOK_GT)|(cur_tok(t).kind==TOK_LE)|(cur_tok(t).kind==TOK_GE)) { op_kind_t op = parse_relat_oper(t); expr_t e0 = parse_add_expr(t); e = mk_expr_bin_op(filename, line, op, e, e0); } return e; }
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; } }
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_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); } }
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; }
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; }
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_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; }
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); }
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){ struct token tok = cur_tok(t); switch(tok.kind){ case TOK_SEMICOLON: return parse_stmt_empty(t); break; case TOK_CONTINUE: return parse_stmt_continue(t); break; case TOK_BREAK: return parse_stmt_break(t); break; case TOK_RETURN: return parse_stmt_return(t); break; case TOK_IF: return parse_stmt_if(t); break; case TOK_WHILE: return parse_stmt_while(t); break; case TOK_LBRACE: return parse_stmt_compound(t); break; default: return parse_stmt_expr(t); break; } return NULL; }
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); } }
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); } }
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); } }
void eat_it(tokenizer_t t, token_kind_t kind) { if(cur_tok(t).kind == kind) { next_tok(t); } else { //printf("exit\n"); exit(1); } }
program_t parse_program(tokenizer_t t) { fun_def_list_t list = mk_fun_def_list(); while(1){ if(cur_tok(t).kind == TOK_EOF) break; else fun_def_list_add(list, parse_fun_def(t)); } return mk_program(t->filename, list); }
program_t parse_program(tokenizer_t t) { char * filename = cur_tok(t).filename; fun_def_list_t l = mk_fun_def_list(); fun_def_t x; while(t->tok.kind != TOK_EOF) { x = parse_fun_difinition(t); fun_def_list_add(l, x); } return mk_program(filename, l); }
expr_list_t parse_arg_expr(tokenizer_t t){ expr_list_t list = mk_expr_list(t); while(1){ if(cur_tok(t).kind == TOK_RPAREN){ break; }else{ expr_list_add(list, parse_expr(t)); if(cur_tok(t).kind == TOK_COMMA){ eat_it(t, TOK_COMMA); continue; }else{ break; } } } return list; }
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); }
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); }
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; } }
void eat_it(tokenizer_t t, token_kind_t tok_kind){ struct token tok = cur_tok(t); if (tok_kind != TOK_ANY && tok.kind != tok_kind){ printf("expected "); output_token_kind(tok_kind); printf("unexpected "); output_token_kind(tok.kind); syntax_error(t, "eat_it error"); } output_token(t); next_tok(t); }
int main(int argc, char ** argv){ tokenizer_t t = mk_tokenizer(argv[1]); while(cur_tok(t).kind != tok_eof){ if(cur_tok(t).kind == tok_nl){ t->num = 0; next_tok(t); } else{ int x = eat_int(t); while(cur_tok(t).kind != tok_nl){ eat_plus(t); int y = eat_int(t); x = x + y; } t->num = 0; next_tok(t); printf("sum = %d\n", x); } } return 0; }