summaryrefslogtreecommitdiff
path: root/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'read.c')
-rw-r--r--read.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/read.c b/read.c
new file mode 100644
index 0000000..047dfb9
--- /dev/null
+++ b/read.c
@@ -0,0 +1,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);
+}
+