| 263 | |
| 264 | |
| 265 | void next_token(state *s) { |
| 266 | s->type = TOK_NULL; |
| 267 | |
| 268 | do { |
| 269 | |
| 270 | if (!*s->next){ |
| 271 | s->type = TOK_END; |
| 272 | return; |
| 273 | } |
| 274 | |
| 275 | /* Try reading a number. */ |
| 276 | if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') { |
| 277 | s->value = strtod(s->next, (char**)&s->next); |
| 278 | s->type = TOK_NUMBER; |
| 279 | } else { |
| 280 | /* Look for a variable or builtin function call. */ |
| 281 | if (isalpha(s->next[0])) { |
| 282 | const char *start; |
| 283 | start = s->next; |
| 284 | while (isalpha(s->next[0]) || isdigit(s->next[0]) || (s->next[0] == '_')) s->next++; |
| 285 | |
| 286 | const te_variable *var = find_lookup(s, start, s->next - start); |
| 287 | if (!var) var = find_builtin(start, s->next - start); |
| 288 | |
| 289 | if (!var) { |
| 290 | s->type = TOK_ERROR; |
| 291 | } else { |
| 292 | switch(TYPE_MASK(var->type)) |
| 293 | { |
| 294 | case TE_VARIABLE: |
| 295 | s->type = TOK_VARIABLE; |
| 296 | s->bound = var->address; |
| 297 | break; |
| 298 | |
| 299 | case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: /* Falls through. */ |
| 300 | case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: /* Falls through. */ |
| 301 | s->context = var->context; /* Falls through. */ |
| 302 | |
| 303 | case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3: /* Falls through. */ |
| 304 | case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: /* Falls through. */ |
| 305 | s->type = var->type; |
| 306 | s->function = var->address; |
| 307 | break; |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | } else { |
| 312 | /* Look for an operator or special character. */ |
| 313 | switch (s->next++[0]) { |
| 314 | case '+': s->type = TOK_INFIX; s->function = add; break; |
| 315 | case '-': s->type = TOK_INFIX; s->function = sub; break; |
| 316 | case '*': s->type = TOK_INFIX; s->function = mul; break; |
| 317 | case '/': s->type = TOK_INFIX; s->function = divide; break; |
| 318 | case '^': s->type = TOK_INFIX; s->function = pow; break; |
| 319 | case '%': s->type = TOK_INFIX; s->function = fmod; break; |
| 320 | case '(': s->type = TOK_OPEN; break; |
| 321 | case ')': s->type = TOK_CLOSE; break; |
| 322 | case ',': s->type = TOK_SEP; break; |