bool parse_number(const char*& c, const char* const end, float& x) { if(!number_p(*c)) return false; const auto begin = c; errno = 0; x = strtof(c, const_cast<char**>(&c)); throw_if(c == begin || errno, "expected number"); throw_if(c > end, "unexpected eof; strtof consumed too much"); return true; }
struct Token * scan(struct Scanner * scanner) { char * forword = scanner->forword; char * lexeme = scanner->lexeme; enum TYPE type; if(level_p(* forword)) { forword += 1; if(!number_p(* forword)) { raise_error(); } do { forword += 1; } while(number_p(* forword)); type = LEVEL; } else if(first_name_p(forword)) { } else if(last_name_p(forword)) { } else if(cid_p(forword)) { } else if(battle_p(forword)) { } else if(end_of_line_p(forword)) { } scanner->forword = forword; scanner->lexeme = forword; return new_token(type, lexeme, forword - lexeme); }
/* * ~~ a brief interlude about the executor ~~ * * The executor takes a function, which is a list of values, the * current stack, which it may modify, and a scope, which it will not modify. * * It uses the following algorithm to execute the function: * 1. Get the next value. if there are no more values, end. * a. if the value is a number, push it onto the stack * b. if the value is a function, call it with the current stack and scope * 1. if the function is a native, call it directly * 2. otherwise, call execute() on it * 2. Go to 1. */ void execute(cons_t *prog, cons_t **stack, dict_t **scope) { dict_t *symbol; value_t val; while (prog != NULL) { val = CAR(prog); if (number_p(val)) { list_push(stack, val); } else if (symbol_p(val)) { symbol = unwrap_symbol(val); val = value(symbol); if (null_p(val)) { fprintf(stderr, "%s? ", key(symbol)); break; } else { unwrap_native(val)(stack, scope); } } else { printf("OH DANG BRO %d:%ld\n", val.storage, val.value.literal); } prog = list_next(prog); } }