lisp but crispier
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
1.6KB

  1. //
  2. // Created by red on 05/12/19.
  3. //
  4. #include "eval.h"
  5. // create number type cval
  6. cval cval_num(long x) {
  7. cval v;
  8. v.type = CVAL_NUM;
  9. v.num = x;
  10. return v;
  11. }
  12. // create error type cval
  13. cval cval_err(int x){
  14. cval v;
  15. v.type = CVAL_ERR;
  16. v.err = x;
  17. return v;
  18. }
  19. void cval_print(cval v) {
  20. switch (v.type) {
  21. case CVAL_NUM: printf("%li", v.num); break;
  22. case CVAL_ERR: {
  23. switch (v.err) {
  24. case CERR_DIV_ZERO: printf("Error: Division by zero"); break;
  25. case CERR_BAD_OP: printf("Error: Invalid operator"); break;
  26. case CERR_BAD_NUM: printf("Error: Invalid number"); break;
  27. default: break;
  28. }
  29. }
  30. default: break;
  31. }
  32. }
  33. void cval_println(cval v) {
  34. cval_print(v);
  35. putchar('\n');
  36. }
  37. cval eval_op(cval x, char* op, cval y) {
  38. if (x.type == CVAL_ERR) {return x;}
  39. if (y.type == CVAL_ERR) {return y;}
  40. switch (*op) {
  41. case '+': return cval_num(x.num + y.num);
  42. case '-': return cval_num(x.num - y.num);
  43. case '*': return cval_num(x.num * y.num);
  44. //return error
  45. case '/': return y.num == 0 ? cval_err(CERR_DIV_ZERO) : cval_num(x.num / y.num);
  46. default: return cval_err(CERR_BAD_OP);
  47. }
  48. }
  49. cval eval(mpc_ast_t* t) {
  50. if (strstr(t->tag, "number")) {
  51. errno = 0;
  52. long x = strtol(t->contents, NULL, 10);
  53. return errno != ERANGE ? cval_num(x) : cval_err(CERR_BAD_NUM);
  54. }
  55. // the operator is always the second child
  56. char* op = t->children[1]->contents;
  57. cval x = eval(t->children[2]);
  58. // iterate over the remaining children and combine
  59. int i = 3;
  60. while (strstr(t->children[i]->tag, "expr")) {
  61. x = eval_op(x, op, eval(t->children[i]));
  62. i++;
  63. }
  64. return x;
  65. }