Exemplo n.º 1
0
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);
    }
}
Exemplo n.º 2
0
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;
}