#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tokenizer/struct.h" #include "tokenizer/next.h" #include "parse.h" struct value* parse( struct tokenizer* tokenizer, struct gc* gc) { struct value* retval; ENTER; switch (tokenizer->token) { case t_null: { retval = new_null_value(gc); tokenizer_next_token(tokenizer); break; } case t_true: { retval = new_boolean_value(gc, true); tokenizer_next_token(tokenizer); break; } case t_false: { retval = new_boolean_value(gc, false); tokenizer_next_token(tokenizer); break; } case t_integer: { intmax_t val; const char* s = (char*) tokenizer->rawtoken.data; char *m; errno = 0; val = strtoimax(s, &m, 0); if (errno || *m) { TODO; } retval = new_integer_value(gc, val); tokenizer_next_token(tokenizer); break; } case t_identifier: { dpvs(tokenizer->rawtoken.data); struct string* string = new_string( /* data: */ tokenizer->rawtoken.data, /* len: */ tokenizer->rawtoken.n); retval = new_identifier_value(gc, string); tokenizer_next_token(tokenizer); free_string(string); break; } case t_gravemark: { tokenizer_next_token(tokenizer); struct value* subexpression = parse( /* tokenizer: */ tokenizer, /* garbage collector: */ gc); retval = new_quote_value(gc, subexpression); gc_dec_external_refcount(gc, subexpression); break; } case t_oparen: { tokenizer_next_token(tokenizer); struct value *head = NULL, *tail = NULL; while (tokenizer->token != t_cparen) { struct value* element = parse(tokenizer, gc); struct value* link = new_list_value(gc, element); if (tail) { tail->subclass.list.rest = link; gc_dec_external_refcount(gc, tail); tail = gc_inc_external_refcount(gc, link); } else { retval = gc_inc_external_refcount(gc, link); head = gc_inc_external_refcount(gc, link); tail = gc_inc_external_refcount(gc, link); } gc_dec_external_refcount(gc, link); gc_dec_external_refcount(gc, element); } struct value* null = new_null_value(gc); // append null sentiental: if (tail) { tail->subclass.list.rest = null; } else { retval = gc_inc_external_refcount(gc, null); } gc_dec_external_refcount(gc, head); gc_dec_external_refcount(gc, tail); gc_dec_external_refcount(gc, null); tokenizer_next_token(tokenizer); break; } default: TODO; break; } EXIT; return retval; }