| 237 | |
| 238 | |
| 239 | void next_token(state *s) { |
| 240 | s->type = TOK_NULL; |
| 241 | |
| 242 | do { |
| 243 | |
| 244 | if (!*s->next){ |
| 245 | s->type = TOK_END; |
| 246 | return; |
| 247 | } |
| 248 | |
| 249 | /* Try reading a number. */ |
| 250 | if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') { |
| 251 | s->value = strtod(s->next, (char**)&s->next); |
| 252 | s->type = TOK_NUMBER; |
| 253 | } else { |
| 254 | /* Look for a variable or builtin function call. */ |
| 255 | if (isalpha(s->next[0])) { |
| 256 | const char *start; |
| 257 | start = s->next; |
| 258 | while (isalpha(s->next[0]) || isdigit(s->next[0]) || (s->next[0] == '_')) s->next++; |
| 259 | |
| 260 | const te_variable *var = find_lookup(s, start, s->next - start); |
| 261 | if (!var) var = find_builtin(start, s->next - start); |
| 262 | |
| 263 | if (!var) { |
| 264 | s->type = TOK_ERROR; |
| 265 | } else { |
| 266 | switch(TYPE_MASK(var->type)) |
| 267 | { |
| 268 | case TE_VARIABLE: |
| 269 | s->type = TOK_VARIABLE; |
| 270 | s->bound = var->address; |
| 271 | break; |
| 272 | |
| 273 | case TE_CLOSURE0: case TE_CLOSURE1: case TE_CLOSURE2: case TE_CLOSURE3: /* Falls through. */ |
| 274 | case TE_CLOSURE4: case TE_CLOSURE5: case TE_CLOSURE6: case TE_CLOSURE7: /* Falls through. */ |
| 275 | s->context = var->context; /* Falls through. */ |
| 276 | |
| 277 | case TE_FUNCTION0: case TE_FUNCTION1: case TE_FUNCTION2: case TE_FUNCTION3: /* Falls through. */ |
| 278 | case TE_FUNCTION4: case TE_FUNCTION5: case TE_FUNCTION6: case TE_FUNCTION7: /* Falls through. */ |
| 279 | s->type = var->type; |
| 280 | s->function = var->address; |
| 281 | break; |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | } else { |
| 286 | /* Look for an operator or special character. */ |
| 287 | switch (s->next++[0]) { |
| 288 | case '+': s->type = TOK_INFIX; s->function = add; break; |
| 289 | case '-': s->type = TOK_INFIX; s->function = sub; break; |
| 290 | case '*': s->type = TOK_INFIX; s->function = mul; break; |
| 291 | case '/': s->type = TOK_INFIX; s->function = divide; break; |
| 292 | case '^': s->type = TOK_INFIX; s->function = pow; break; |
| 293 | case '%': s->type = TOK_INFIX; s->function = fmod; break; |
| 294 | case '(': s->type = TOK_OPEN; break; |
| 295 | case ')': s->type = TOK_CLOSE; break; |
| 296 | case ',': s->type = TOK_SEP; break; |