expr.c (3618B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <ctype.h> 4 #include <math.h> 5 #include <string.h> 6 7 #include "sheets.h" 8 9 /* 10 EXPR := VALUE 11 | VALUE POSTFIX 12 | '(' EXPR ')' 13 14 VALUE := NUM 15 | LOC 16 17 POSTFIX := OP EXPR 18 OP := '+' | '-' | '*' | '/' | '^' 19 lOC := '[' NUM ',' NUM ']' 20 */ 21 22 #define TODO(s) fprintf(stderr, "TODO:%d: %s\n", __LINE__, s); exit(1); 23 24 typedef struct expr expr; 25 typedef struct value value; /* for recursive case */ 26 typedef struct postfix postfix; 27 28 typedef enum exprType { 29 VALUE, 30 POSTFIX, 31 NESTED, 32 } exprType; 33 34 typedef enum valueType { 35 NUM, 36 LOC, 37 } valueType; 38 39 typedef struct loc { 40 int x, y; 41 } loc; 42 43 typedef struct expr { 44 char *expr; 45 exprType t; 46 union { 47 expr *nested; 48 struct { 49 value *value; 50 postfix *postfix; 51 }; 52 }; 53 } expr; 54 55 typedef struct postfix { 56 char op; 57 expr *expr; 58 } postfix; 59 60 typedef struct value { 61 valueType t; 62 union { 63 int num; 64 loc *loc; 65 }; 66 } value; 67 68 char isop(char c) { 69 switch (c) { 70 case '+': 71 case '-': 72 case '*': 73 case '/': 74 case '^': 75 return c; 76 } 77 return 0; 78 } 79 80 char *in; 81 char *Pin; 82 83 void consumeleading(char c) { 84 loop: 85 if (*in == c) { 86 in++; 87 goto loop; 88 } 89 } 90 91 expr *parseExpr(); 92 93 loc *parseLoc() { 94 consumeleading(' '); 95 loc *l = malloc(sizeof(loc)); 96 if (*in == '[') { 97 int i; 98 sscanf(in, "[%d,%d]%n", &l->x, &l->y, &i); 99 if (i != 0) { 100 in += i; 101 return l; 102 } 103 TODO("ERROR"); 104 } 105 return NULL; 106 } 107 108 postfix *parsePostfix() { 109 consumeleading(' '); 110 postfix *p = malloc(sizeof(postfix)); 111 if (p->op = isop(*in)) { 112 in++; 113 if (p->expr = parseExpr()) 114 return p; 115 } 116 return NULL; 117 } 118 119 value *parseValue() { 120 consumeleading(' '); 121 value *v = malloc(sizeof(value)); 122 if (v->loc = parseLoc()) { 123 v->t = LOC; 124 return v; 125 } 126 else if (isdigit(*in)) { 127 int i; 128 sscanf(in, "%d%n", &v->num, &i); 129 if (i != 0) { 130 in += i; 131 v->t = NUM; 132 return v; 133 } 134 TODO("ERROR"); 135 } 136 return NULL; 137 } 138 139 expr *parseExpr() { 140 consumeleading(' '); 141 expr *e = malloc(sizeof(expr)); 142 if (e->value = parseValue()) { 143 e->t = VALUE; 144 if (e->postfix = parsePostfix()) 145 e->t = POSTFIX; 146 147 return e; 148 } 149 150 else if (*in == '(') { 151 in++; 152 if (e->nested = parseExpr()) 153 if (*in == ')') { 154 e->t = NESTED; 155 return e; 156 } 157 TODO("ERROR"); 158 } 159 160 return NULL; 161 } 162 163 double evalExpr(expr *e, sheet *s); 164 165 double evalValue(value *v, sheet *s) { 166 if (v->t == NUM) return v->num; 167 return evalExpr(s->cells[v->loc->y][v->loc->x], s); 168 } 169 170 double evalPostfix(value *v, postfix *p, sheet *s) { 171 switch (p->op) { 172 case '+': return evalValue(v, s) + evalExpr(p->expr, s); 173 case '-': return evalValue(v, s) - evalExpr(p->expr, s); 174 case '*': return evalValue(v, s) * evalExpr(p->expr, s); 175 case '/': return evalValue(v, s) / evalExpr(p->expr, s); 176 case '^': return pow(evalValue(v, s), evalExpr(p->expr, s)); 177 } 178 } 179 180 double evalExpr(expr *e, sheet *s) { 181 switch (e->t) { 182 case VALUE: return evalValue(e->value, s); break; 183 case POSTFIX: return evalPostfix(e->value, e->postfix, s); break; 184 case NESTED: return evalExpr(e->nested, s); 185 } 186 } 187 188 expr *makeNumber(int n) { 189 in = Pin; 190 memset(in, 0, 255); 191 snprintf(in, 16, "%d", n); 192 expr *e = parseExpr(); 193 e->expr = strdup(Pin); 194 return e; 195 } 196 197 void freeValue(value *v) { 198 if (v->t == LOC) free(v->loc); 199 free(v); 200 } 201 202 void freePostfix(value *v, postfix *p) { 203 freeValue(v); 204 freeExpr(p->expr); 205 free(p); 206 } 207 208 void freeExpr(expr *e) { 209 switch (e->t) { 210 case VALUE: freeValue(e->value); break; 211 case POSTFIX: freePostfix(e->value, e->postfix); break; 212 case NESTED: freeExpr(e->nested); break; 213 } 214 free(e); 215 }