void parse_stmt() { switch(next_token.type) { case TT_TYPE_DOUBLE: case TT_TYPE_INT: case TT_TYPE_STRING: case TT_TYPE_AUTO: parse_varDef(); match(TT_SEMICOLON); break; case TT_IDENTIFICATOR: parse_asgn(); match(TT_SEMICOLON); break; case TT_KW_RETURN: match(TT_KW_RETURN); expression_t expr = parse_expr(); switch (expr.type) { case DOUBLE_DT: case DOUBLE_LIT_DT: if (func_get_return_type() != DOUBLE_DT && func_get_return_type() != INT_DT) error("Variable with bad type in a return statement", ERROR_TYPE_COMPAT); break; case INT_DT: case INT_LIT_DT: if (func_get_return_type() != DOUBLE_DT && func_get_return_type() != INT_DT) error("Variable with bad type in a return statement", ERROR_TYPE_COMPAT); break; case STRING_DT: case STRING_LIT_DT: if (func_get_return_type() != STRING_DT) error("Variable with bad type in a return statement", ERROR_TYPE_COMPAT); break; default: ; } match(TT_SEMICOLON); if (str_equal(func_get_name(), "main")) generate_halt(); else { switch (expr.type) { case DOUBLE_DT: if(func_get_return_type() == DOUBLE_DT) { generate_return(expr.addr, func_get_param_count()); } else { size_t conv_expr = generate_double_to_int(expr.addr); generate_return(conv_expr, func_get_param_count()); } break; case INT_DT: if(func_get_return_type() == INT_DT) { generate_return(expr.addr, func_get_param_count()); } else { size_t conv_expr = generate_int_to_double(expr.addr); generate_return(conv_expr, func_get_param_count()); } break; case STRING_DT: generate_return(expr.addr, func_get_param_count()); break; case DOUBLE_LIT_DT: if(func_get_return_type() == DOUBLE_DT) generate_return_double(expr.double_val, func_get_param_count()); else generate_return_double((int)expr.double_val, func_get_param_count()); break; case INT_LIT_DT: if(func_get_return_type() == INT_DT) generate_return_int(expr.int_val, func_get_param_count()); else generate_return_int((double)expr.int_val, func_get_param_count()); break; case STRING_LIT_DT: generate_return_string(expr.str_val, func_get_param_count()); break; default: ; } } break; case TT_KW_COUT: parse_coutStmt(); match(TT_SEMICOLON); break; case TT_KW_CIN: parse_cinStmt(); match(TT_SEMICOLON); break; case TT_BLOCK_START: parse_block(true); break; case TT_KW_IF: parse_ifClause(); break; case TT_KW_FOR: parse_forClause(); break; default: error("Syntactic error: Failed to parse the program", ERROR_SYN); } }
static code_block *generate_block(code_block *parent, block_statement *block, block_iter iter, void *iter_data) { for (symbol_entry *c = block->class_head; c; c = c->next) { generate_class_stub(parent->system, c->classtype); } for (symbol_entry *f = block->function_head; f; f = f->next) { generate_function_stub(parent->system, f->function); } for (symbol_entry *c = block->class_head; c; c = c->next) { generate_class(parent->system, c->classtype); } for (symbol_entry *f = block->function_head; f; f = f->next) { generate_function(parent->system, f->function); } for (statement *node = block->body; node; node = node->next) { switch (node->type) { case S_BLOCK: { code_block *body = fork_block(parent); body = generate_block(body, (block_statement*) node, NULL, NULL); parent = rejoin_block(parent, body); } break; case S_BREAK: case S_CONTINUE: generate_control(parent, (control_statement*) node); parent = NULL; break; case S_DEFINE: parent = generate_define(parent, (define_statement*) node); break; case S_LET: parent = generate_let(parent, (let_statement*) node); break; case S_DO_WHILE: case S_WHILE: parent = generate_loop(parent, (loop_statement*) node); break; case S_EXPRESSION: { expression_statement *express = (expression_statement*) node; parent = generate_expression(parent, express->value); } break; case S_IF: parent = generate_if(parent, (if_statement*) node); break; case S_RETURN: generate_return(parent, (return_statement*) node); parent = NULL; break; // already processed case S_CLASS: case S_FUNCTION: case S_TYPEDEF: break; } // most recently processed statement terminates abruptly if (parent == NULL) { if (node->next) { fprintf(stderr, "not reachable\n"); } return NULL; } if (iter != NULL) { iter(parent, iter_data); } } return parent; }