summaryrefslogtreecommitdiff
path: root/read.c
blob: 047dfb994f59ed8422b8805eeb30d43695636559 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "val.h"
#include "util.h"

#include <string.h>

typedef struct _reader {
	char *c;
	State *S;
} Reader;


static void next(Reader *R) { CHECK(*R->c != '\0',"end of string reached"); R->c++; }
static bool is_ws(char x) {	return x == ' ' || x == '\t' || x == '\n';}
static bool is_num(char x) { return '0' <= x && x <= '9'; }
static bool is_special(char x) {
	switch(x) {
	case '(': case ')': case '[': case ']': case '\'': case '"':
	return true; break;
	default: return false; break;
	}
}
static bool is_normal(char x) {
	return !(is_ws(x) || is_special(x));
}
static void skipws(Reader *R) {	while (is_ws(*R->c)) next(R); }

static Val symbol(Reader *R);
static Val string(Reader *R);
static Val list(Reader *R, char closer);

#define STR(S, s) (VAL_OBJ(objstring_copy_cstr(S, s)))

static Val expr(Reader *R) {
	skipws(R);
	switch (*R->c) {
	case '"':
		next(R); return string(R);
		break;
	case '(':
		next(R); return list(R, ')');
		break;
	case '[':
		next(R); 
		ObjArr *a = AS_ARR(list(R, ']'));
		objarr_insert(R->S, a, 0, STR(R->S, "arr"));
		return VAL_OBJ(a);
		break;
	default: return symbol(R); break;
	}
}
static Val symbol(Reader *R) {
	char *start = R->c;
	int len = 0;
	bool num = true;
	while (is_normal(*R->c)) { num &= is_num(*R->c); len += 1; next(R); }
	if (num) {
		// c moment
		char *tmp = malloc(len+1);
		memcpy(tmp, start, len);
		tmp[len] = 0;
		int x = atoi(tmp);
		free(tmp);
		return VAL_NUM((double)x);
	} else {
		ObjString *o = objstring_copy(R->S, start, len);
		return VAL_OBJ(o);
	}
}
static Val string(Reader *R) {
	char *start = R->c;
	int len = 0;
	// todo, escape sequences
	while (*R->c != '"') { len += 1; next(R); }
	next(R);
	ObjString *s = objstring_copy(R->S, start, len);
	ObjArr *a = objarr_new(R->S);
	objarr_append(R->S, a, STR(R->S, "quote"));
	objarr_append(R->S, a, VAL_OBJ(s));
	return VAL_OBJ(a);
}
static Val list(Reader *R, char closer) {
	ObjArr *a = objarr_new(R->S);
	while (true) {
		skipws(R);
		if (*R->c == closer) {
			next(R);
			return VAL_OBJ(a);
		}
		objarr_append(R->S, a, expr(R));
	}
}


Val read_expr(State *S, char *str) {
	Reader r = (Reader){.S=S, .c=str};
	return expr(&r);
}