|
- //
- // 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;
- }
|