compile.c (10573B)
1 /* compile.c - de tokens a RPN, con las precedencias de la Casio: 2 * = < + - < × ÷ < nPr nCr < multiplicacion implicita < - unario 3 * < potencia y postfijos (x², x⁻¹, !, %) < funciones, plantillas, parentesis 4 * Asi -2² = -4 y 1÷2π = 1/(2π). La recursion esta acotada (MAX_NEST). */ 5 #include <string.h> 6 #include "eval.h" 7 8 #define MAX_NEST 24 9 10 static const Expr *E; 11 static const EvalCtx *CX; 12 static Prog *P; 13 static int I, END_, ERR, EPOS, DEPTH; 14 15 static int peek(void) 16 { 17 while (I < END_ && E->t[I] == ' ') I++; /* los espacios no cuentan */ 18 return I < END_ ? E->t[I] : 0; 19 } 20 21 static void fail(int code, int pos) 22 { 23 if (!ERR) { ERR = code; EPOS = pos; } 24 } 25 26 static void emit(int op, int arg, int pos, int nargs) 27 { 28 if (P->n >= PROG_MAX) { fail(CE_STACK, pos); return; } 29 Code *c = &P->c[P->n++]; 30 c->op = (uint8_t)op; c->arg = (uint8_t)arg; c->pos = (uint8_t)(pos < 255 ? pos : 255); c->nargs = (uint8_t)nargs; c->len = 0; 31 } 32 33 static void emit_num(Num v, int pos) 34 { 35 if (P->nk >= PROG_CONSTS) { fail(CE_STACK, pos); return; } 36 P->k[P->nk] = v; 37 emit(OP_NUM, P->nk++, pos, 0); 38 } 39 40 static void parse_expr(void); 41 42 /* fin del campo actual: SEP, END o el final */ 43 static bool at_field_end(void) { int t = peek(); return !t || t == T_SEP || t == T_END; } 44 45 /* parsea un campo de plantilla que empieza en I (hasta SEP/END) y lo consume */ 46 static void parse_field(void) 47 { 48 int save_end = END_; 49 if (at_field_end()) { fail(CE_SYNTAX, I); return; } /* casilla vacia */ 50 parse_expr(); 51 if (!at_field_end()) fail(CE_SYNTAX, I); 52 END_ = save_end; 53 if (I < END_ && (E->t[I] == T_SEP || E->t[I] == T_END)) I++; 54 } 55 56 static bool is_digit(int t) { return (t >= '0' && t <= '9') || t == '.'; } 57 static bool is_hex(int t) { return (t >= '0' && t <= '9') || (t >= 'A' && t <= 'F'); } 58 59 static void parse_number(void) 60 { 61 int pos = I; 62 char buf[48]; 63 int k = 0, exp10 = 0; 64 if (CX && CX->prog) { 65 /* entero en la base de entrada */ 66 int64_t v = 0; 67 bool any = false; 68 while (is_hex(peek())) { 69 int t = peek(), d = t <= '9' ? t - '0' : t - 'A' + 10; 70 if (d >= CX->base) { fail(CE_SYNTAX, I); return; } 71 v = (int64_t)((uint64_t)v * (uint64_t)CX->base + (uint64_t)d); 72 any = true; 73 I++; 74 } 75 if (!any) { fail(CE_SYNTAX, I); return; } 76 emit_num(num_int(v), pos); 77 return; 78 } 79 int dots = 0; 80 while (is_digit(peek()) && k < 40) { 81 if (peek() == '.' && ++dots > 1) { fail(CE_SYNTAX, I); return; } 82 buf[k++] = (char)E->t[I++]; 83 } 84 if (!k) buf[k++] = '1'; /* "×10^3" solo = 1×10^3 */ 85 buf[k] = 0; 86 if (k == 1 && buf[0] == '.') { fail(CE_SYNTAX, pos); return; } 87 if (peek() == T_E10) { 88 I++; 89 bool neg = false; 90 if (peek() == '-') { neg = true; I++; } 91 int nd = 0; 92 while (peek() >= '0' && peek() <= '9') { exp10 = exp10 * 10 + (E->t[I++] - '0'); if (++nd > 3) break; } 93 if (!nd) { fail(CE_SYNTAX, I); return; } 94 if (neg) exp10 = -exp10; 95 } 96 Num v = num_lit(buf, exp10); 97 if (num_bad(&v)) fail(CE_MATH, pos); 98 emit_num(v, pos); 99 } 100 101 static void parse_fn(void) 102 { 103 int pos = I, f = E->t[I++] - T_FN; 104 int args = 0; 105 if (!(peek() == ')' || at_field_end())) { 106 for (;;) { 107 parse_expr(); 108 args++; 109 if (peek() == ',') { I++; continue; } 110 break; 111 } 112 } 113 if (peek() == ')') I++; 114 else if (!at_field_end()) fail(CE_SYNTAX, I); 115 if (args != FN_INFO[f].args) { fail(CE_SYNTAX, pos); return; } 116 emit(OP_FN, f, pos, args); 117 } 118 119 static void parse_primary(void) 120 { 121 int t = peek(), pos = I; 122 if (!t || t == T_SEP || t == T_END) { fail(CE_SYNTAX, I); return; } 123 if (++DEPTH > MAX_NEST) { fail(CE_STACK, I); return; } 124 if (is_digit(t) || t == T_E10 || (CX && CX->prog && is_hex(t))) parse_number(); 125 else if (t == '(') { 126 I++; 127 parse_expr(); 128 if (peek() == ')') I++; 129 else if (!at_field_end()) fail(CE_SYNTAX, I); 130 } else if (t >= T_FN && t < T_FN + FN_COUNT) parse_fn(); 131 else if (t == T_PI) { I++; emit(OP_PI, 0, pos, 0); } 132 else if (t == T_E) { I++; emit(OP_E, 0, pos, 0); } 133 else if (t == T_ANS) { I++; emit(OP_ANS, 0, pos, 0); } 134 else if (t == T_PREANS) { I++; emit(OP_PREANS, 0, pos, 0); } 135 else if (t == T_RAN) { I++; emit(OP_RAN, 0, pos, 0); } 136 else if (t >= T_MAT && t <= T_MATANS) { I++; emit(OP_MAT, t - T_MAT, pos, 0); } 137 else if (t >= T_VCT && t <= T_VCTANS) { I++; emit(OP_VCT, t - T_VCT, pos, 0); } 138 else if (t >= T_VAR && t < T_VAR + NVARS) { I++; emit(OP_VAR, t - T_VAR, pos, 0); } 139 else if (t >= 'a' && t <= 'z') { 140 I++; 141 if (t == 'e') emit(OP_E, 0, pos, 0); 142 else if (t == 'i' && CX && CX->cplx) emit(OP_IMAG, 0, pos, 0); 143 else { 144 const char *v = strchr(VAR_NAMES, t - 'a' + 'A'); 145 if (v) emit(OP_VAR, (int)(v - VAR_NAMES), pos, 0); 146 else fail(CE_SYNTAX, pos); 147 } 148 } else if (tok_is_frac(t)) { 149 I++; 150 parse_field(); 151 parse_field(); 152 emit(OP_DIV, 0, pos, 2); 153 } else if (t == T_SQRT) { I++; parse_field(); emit(OP_SQRT, 0, pos, 1); } 154 else if (t == T_ROOT) { I++; parse_field(); parse_field(); emit(OP_ROOT, 0, pos, 2); } 155 else if (t == T_LOGB) { I++; parse_field(); parse_field(); emit(OP_LOGB, 0, pos, 2); } 156 else if (t == T_ABS) { I++; parse_field(); emit(OP_ABS, 0, pos, 1); } 157 else if (t == T_MIXED) { I++; parse_field(); parse_field(); parse_field(); emit(OP_MIXED, 0, pos, 3); } 158 else if (t == T_INTEG || t == T_SUM || t == T_PROD || t == T_DERIV) { 159 /* el cuerpo se compila en un tramo que la ejecucion normal saltea (OP_SKIP); 160 * la operacion lo corre con distintos valores de X */ 161 I++; 162 if (t != T_DERIV) { parse_field(); parse_field(); } 163 int skip = P->n; 164 emit(OP_SKIP, 0, pos, 0); 165 int start = P->n; 166 parse_field(); 167 int len = P->n - start; 168 if (!ERR) P->c[skip].len = (uint8_t)len; 169 if (t == T_DERIV) parse_field(); 170 int op = t == T_INTEG ? OP_INTEG : t == T_SUM ? OP_SUM : t == T_PROD ? OP_PROD : OP_DERIV; 171 emit(op, start, pos, t == T_DERIV ? 1 : 2); 172 if (!ERR) P->c[P->n - 1].len = (uint8_t)len; 173 } 174 else fail(CE_SYNTAX, pos); 175 DEPTH--; 176 } 177 178 static void parse_postfix(void) 179 { 180 parse_primary(); 181 for (;;) { 182 int t = peek(), pos = I; 183 if (tok_is_pow(t)) { I++; parse_field(); emit(OP_POW, 0, pos, 2); } 184 else if (t == T_INV) { I++; emit(OP_INV, 0, pos, 1); } 185 else if (t == '!') { I++; emit(OP_FACT, 0, pos, 1); } 186 else if (t == '%') { I++; emit(OP_PCT, 0, pos, 1); } 187 else if (t == T_DEGS) { 188 /* sexagesimal: a°b°c° = a + b/60 + c/3600 (exacto) */ 189 I++; 190 for (int k = 60; k <= 3600; k *= 60) { 191 int save = I; 192 if (!is_digit(peek())) break; 193 while (is_digit(peek())) I++; 194 bool more = peek() == T_DEGS; 195 I = save; 196 if (!more) break; 197 parse_number(); 198 I++; 199 emit_num(num_int(k), pos); 200 emit(OP_DIV, 0, pos, 2); 201 emit(OP_ADD, 0, pos, 2); 202 } 203 } 204 else break; 205 } 206 } 207 208 static void parse_unary(void) 209 { 210 int t = peek(), pos = I; 211 if (t == '-') { I++; parse_unary(); emit(OP_NEG, 0, pos, 1); return; } 212 if (t == '+') { I++; parse_unary(); return; } 213 if (t == T_FN + FN_NOT || t == T_FN + FN_NEG) { parse_postfix(); return; } 214 parse_postfix(); 215 } 216 217 /* un atomo puede empezar aca (para la multiplicacion implicita) */ 218 static bool starts_atom(int t) 219 { 220 if (!t || t == T_SEP || t == T_END) return false; 221 if (CX && CX->prog) return false; /* en programador no hay implicita */ 222 return is_digit(t) || t == '(' || t == T_PI || t == T_E || t == T_ANS || t == T_PREANS || 223 t == T_RAN || t == T_E10 || (t >= T_MAT && t <= T_VCTANS) || (t >= T_VAR && t < T_VAR + NVARS) || (t >= T_FN && t < T_FN + FN_COUNT) || 224 (t >= 'a' && t <= 'z') || (tok_is_tpl(t) && !tok_is_pow(t)); 225 } 226 227 static void parse_implicit(void) 228 { 229 parse_unary(); 230 while (!ERR && starts_atom(peek())) { 231 int pos = I; 232 parse_postfix(); 233 emit(OP_MUL, 0, pos, 2); 234 } 235 } 236 237 static void parse_comb(void) 238 { 239 parse_implicit(); 240 for (;;) { 241 int t = peek(), pos = I; 242 if (t != T_NPR && t != T_NCR && t != T_ANGLE) break; 243 I++; 244 parse_implicit(); 245 emit(t == T_NPR ? OP_NPR : t == T_NCR ? OP_NCR : OP_POLAR, 0, pos, 2); 246 } 247 } 248 249 static void parse_prod(void) 250 { 251 parse_comb(); 252 for (;;) { 253 int t = peek(), pos = I; 254 if (t != T_MUL && t != T_DIV) break; 255 I++; 256 parse_comb(); 257 emit(t == T_MUL ? OP_MUL : OP_DIV, 0, pos, 2); 258 } 259 } 260 261 static void parse_sum(void) 262 { 263 parse_prod(); 264 for (;;) { 265 int t = peek(), pos = I; 266 if (t != '+' && t != '-') break; 267 I++; 268 parse_prod(); 269 emit(t == '+' ? OP_ADD : OP_SUB, 0, pos, 2); 270 } 271 } 272 273 /* programador: and/or/xor/xnor escritos como palabras, mas bajos que + - */ 274 static int word_op(void) 275 { 276 static const char *const W[] = { "xnor", "and", "xor", "or" }; 277 static const int OPS[] = { OP_XNOR, OP_AND, OP_XOR, OP_OR }; 278 for (int w = 0; w < 4; w++) { 279 int l = (int)strlen(W[w]); 280 if (I + l > END_) continue; 281 int k = 0; 282 while (k < l && E->t[I + k] == (uint8_t)W[w][k]) k++; 283 if (k == l) { I += l; return OPS[w]; } 284 } 285 return -1; 286 } 287 288 static void parse_logic(void) 289 { 290 parse_sum(); 291 while (CX && CX->prog && !ERR) { 292 peek(); 293 int pos = I, op = word_op(); 294 if (op < 0) break; 295 parse_sum(); 296 emit(op, 0, pos, 2); 297 } 298 } 299 300 static void parse_expr(void) 301 { 302 if (++DEPTH > MAX_NEST) { fail(CE_STACK, I); return; } 303 parse_logic(); 304 if (peek() == '=') { 305 int pos = I; 306 I++; 307 parse_logic(); 308 emit(OP_EQ, 0, pos, 2); 309 P->has_eq = true; 310 } 311 DEPTH--; 312 } 313 314 int compile(const Expr *e, const EvalCtx *cx, Prog *p, int *pos) 315 { 316 E = e; CX = cx; P = p; 317 I = 0; END_ = e->n; ERR = 0; EPOS = 0; DEPTH = 0; 318 p->n = p->nk = 0; 319 p->has_eq = false; 320 if (!e->n) { if (pos) *pos = 0; return CE_SYNTAX; } 321 parse_expr(); 322 if (!ERR && I < e->n) fail(CE_SYNTAX, I); 323 if (pos) *pos = EPOS; 324 return ERR; 325 }