summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-08-04 13:05:47 +0100
committerubq323 <ubq323@ubq323.website>2024-08-04 13:05:47 +0100
commit000e8ca43f4968412ed5c8fc514bb6caa3e5c450 (patch)
treee82eddb3cb54f75f8468e9a80a17e8b14857aa45
parent1f257ac91ef3813c563203eacb5320b210fc1aa7 (diff)
new reader
-rw-r--r--Makefile6
-rw-r--r--com.c1
-rw-r--r--next5
-rw-r--r--read.c98
-rw-r--r--read.h8
-rw-r--r--util.h1
-rw-r--r--val.c14
-rw-r--r--val.h1
8 files changed, 131 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 9fbf2e7..4a0d3b9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
-CS=ast.c com.c dis.c ht.c lib.c mem.c prs.c state.c val.c vm.c
-HS=ast.h chunk.h com.h dis.h ht.h lib.h mem.h prs.h state.h util.h val.h vm.h
-CFLAGS=$(EXTRA_CFLAGS) -g -O3 -lm -Wall -Wpedantic -Werror=implicit-function-declaration
+CS=ast.c com.c dis.c ht.c lib.c mem.c prs.c read.c state.c val.c vm.c
+HS=ast.h chunk.h com.h dis.h ht.h lib.h mem.h prs.h read.h state.h util.h val.h vm.h
+CFLAGS=$(EXTRA_CFLAGS) -g -lm -Wall -Wpedantic -Werror=implicit-function-declaration
bth: $(CS) $(HS) Makefile
$(CC) $(CFLAGS) -o bth $(CS)
diff --git a/com.c b/com.c
index 0273866..10774c8 100644
--- a/com.c
+++ b/com.c
@@ -10,6 +10,7 @@
#include "util.h"
#include "prs.h"
#include "lib.h"
+#include "read.h"
#define BYTECODE(C) (C->ch->bc)
diff --git a/next b/next
new file mode 100644
index 0000000..1d2e86c
--- /dev/null
+++ b/next
@@ -0,0 +1,5 @@
+separate strings and symbols
+quoting
+ht literals
+new parser
+macros
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);
+}
+
diff --git a/read.h b/read.h
new file mode 100644
index 0000000..d4c54a2
--- /dev/null
+++ b/read.h
@@ -0,0 +1,8 @@
+#ifndef _read_h
+#define _read_h
+
+#include "state.h"
+#include "val.h"
+Val read_expr(State *S, char *str);
+
+#endif
diff --git a/util.h b/util.h
index 076393e..6b61b56 100644
--- a/util.h
+++ b/util.h
@@ -2,6 +2,7 @@
#define _util_h
#include <stdio.h>
+#include <stdlib.h>
#define CHECK(cond, ...) do { if (!(cond)) { fprintf(stderr, __VA_ARGS__); putchar('\n'); exit(1); } } while(0)
#define ERROR(...) CHECK(false, __VA_ARGS__)
diff --git a/val.c b/val.c
index 685c504..43e47d3 100644
--- a/val.c
+++ b/val.c
@@ -84,6 +84,20 @@ void objarr_put(State *S, ObjArr *arr, size_t ix, Val v) {
arr->d[ix] = v;
}
}
+void objarr_insert(State *S, ObjArr *arr, size_t ix, Val v) {
+ CHECK(ix <= arr->len, "array index out of bounds");
+ if (ix == arr->len) {
+ objarr_append(S, arr, v);
+ } else {
+ if (arr->len == arr->cap) {
+ size_t newsz = (arr->cap == 0 ? 8 : arr->cap * 2);
+ arr->d = RENEW_ARR(S, arr->d, Val, arr->cap, newsz);
+ arr->cap = newsz;
+ }
+ memmove(&arr->d[ix+1], &arr->d[ix], (arr->len-ix)*sizeof(Val));
+ arr->d[ix] = v;
+ }
+}
static void print_val_h(Val v, int depth);
void print_val(Val v) {
diff --git a/val.h b/val.h
index 4f77828..aa68d05 100644
--- a/val.h
+++ b/val.h
@@ -83,6 +83,7 @@ ObjArr *objarr_new(State *S);
Val objarr_get(State *S, ObjArr *arr, size_t ix);
void objarr_append(State *S, ObjArr *arr, Val v);
void objarr_put(State *S, ObjArr *arr, size_t ix, Val v);
+void objarr_insert(State *S, ObjArr *arr, size_t ix, Val v);
#define IS_NIL(x) (x.ty == TY_NIL)
#define IS_NUM(x) (x.ty == TY_NUM)