187 lines
4.2 KiB
C
187 lines
4.2 KiB
C
|
|
#include <assert.h>
|
|
#include <inttypes.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include <debug.h>
|
|
|
|
#include <string/new.h>
|
|
#include <string/free.h>
|
|
|
|
#include <value/struct.h>
|
|
#include <value/identifier/new.h>
|
|
#include <value/boolean/new.h>
|
|
#include <value/integer/new.h>
|
|
#include <value/list/new.h>
|
|
#include <value/quote/new.h>
|
|
#include <value/null/new.h>
|
|
|
|
#include <gc/inc_external_refcount.h>
|
|
#include <gc/dec_external_refcount.h>
|
|
|
|
#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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|