Skip to content

Instantly share code, notes, and snippets.

@Mon-Ouie
Created April 21, 2014 10:37
Show Gist options
  • Save Mon-Ouie/11138971 to your computer and use it in GitHub Desktop.
Save Mon-Ouie/11138971 to your computer and use it in GitHub Desktop.
static bool read_token(const char **src, const char *str) {
const char *start = *src;
while (**src && *str && **src == *str) {
str++;
(*src)++;
}
if (*str) {
*src = start;
return false;
}
else
return true;
}
static void skip_whitespace(const char **str) {
while (isblank(**str)) (*str)++;
}
bool read_list(const char **string, stack *stack, object **ret) {
const char *init = *string;
skip_whitespace(string);
if (!read_token(string, "(")) goto error;
object *i = Nil;
if (!stack_push(stack, i)) goto error;
while (skip_whitespace(string), **string != ')' && **string) {
object *element;
if (!read_object(string, stack, &element)) goto error;
if (!stack_push(stack, element)) goto error;
if (!(i = cons(element, i))) {
stack_pop(stack); stack_pop(stack);
goto error;
}
stack_pop(stack);
stack_pop(stack);
if (!stack_push(stack, i)) goto error;
}
if (**string == ')') {
(*string)++;
}
else
goto error;
stack_pop(stack);
if (!reverse_list(i, ret)) goto error;
return true;
error:
*string = init;
return false;
}
bool read_atom(const char **string, object **ret) {
const char *init = *string;
skip_whitespace(string);
const char *begin = *string;
bool all_digits = true;
while (!isblank(**string) && **string != '('
&& **string != ')') {
if (!isdigit(**string)) all_digits = false;
(*string)++;
}
const char *end = *string;
if (all_digits) goto error;
if (begin == end) goto error;
bool success;
*ret = intern_buffer(current_symbol_table, begin,
end - begin, &success);
return true;
error:
*string = init;
return false;
}
static int read_sign(const char **src);
static bool read_integer(const char **src, int *out);
static int read_sign(const char **src) {
switch (**src){
case '+':
(*src)++;
return 1;
case '-':
(*src)++;
return -1;
default: return 1;
}
}
static bool read_integer(const char **src, int *out) {
const char *initial_pos = *src;
int sign = read_sign(src);
if (!isdigit(**src)) {
*src = initial_pos;
return false;
}
const char *start = *src;
while (isdigit(**src)) (*src)++;
const char *end = *src;
*out = 0;
int power = 1;
for (const char *i = end-1; i >= start; i--, power *= 10)
*out += (*i - '0') * power;
*out *= sign;
return true;
}
bool read_int(const char **string, object **ret) {
int num;
if (read_integer(string, &num)) {
*ret = int_to_fixnum(num);
return true;
}
else
return false;
}
bool read_object(const char **string, stack *stack, object **ret) {
skip_whitespace(string);
return read_list(string, stack, ret)
|| read_atom(string, ret)
|| read_int(string, ret);
}
bool read(const char **string, object **obj) {
stack *s = (stack*)make_stack(4);
gc_add_root(&global_gc, &s->as_object);
bool res = read_object(string, s, obj);
gc_del_root(&global_gc, &s->as_object);
return res;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment