// // Created by red on 05/12/19. // #include "eval.h" // create number type cval cval cval_num(long x) { cval v; v.type = CVAL_NUM; v.num = x; return v; } // create error type cval cval cval_err(int x){ cval v; v.type = CVAL_ERR; v.err = x; return v; } void cval_print(cval v) { switch (v.type) { case CVAL_NUM: printf("%li", v.num); break; case CVAL_ERR: { switch (v.err) { case CERR_DIV_ZERO: printf("Error: Division by zero"); break; case CERR_BAD_OP: printf("Error: Invalid operator"); break; case CERR_BAD_NUM: printf("Error: Invalid number"); break; default: break; } } default: break; } } void cval_println(cval v) { cval_print(v); putchar('\n'); } cval eval_op(cval x, char* op, cval y) { if (x.type == CVAL_ERR) {return x;} if (y.type == CVAL_ERR) {return y;} switch (*op) { case '+': return cval_num(x.num + y.num); case '-': return cval_num(x.num - y.num); case '*': return cval_num(x.num * y.num); //return error case '/': return y.num == 0 ? cval_err(CERR_DIV_ZERO) : cval_num(x.num / y.num); default: return cval_err(CERR_BAD_OP); } } cval eval(mpc_ast_t* t) { if (strstr(t->tag, "number")) { errno = 0; long x = strtol(t->contents, NULL, 10); return errno != ERANGE ? cval_num(x) : cval_err(CERR_BAD_NUM); } // the operator is always the second child char* op = t->children[1]->contents; cval x = eval(t->children[2]); // iterate over the remaining children and combine int i = 3; while (strstr(t->children[i]->tag, "expr")) { x = eval_op(x, op, eval(t->children[i])); i++; } return x; }