commit 18235b39b49c0dc17ab926563ee36369c7175e77
parent 8da9c91217364c94f60f36000c3b4eca3dc56b63
Author: Pavel Renev <an2qzavok@gmail.com>
Date: Sun, 28 Jul 2024 23:08:26 +0000
src/fltp: some code
Diffstat:
4 files changed, 199 insertions(+), 0 deletions(-)
diff --git a/src/fltp/example b/src/fltp/example
@@ -0,0 +1,10 @@
+[uuid] {
+names {
+.l Cool Story Bro
+.l Everyone Clapped
+}
+tags .l fantasy romance drama
+type .l novel
+status .l ch 76
+extra .l not real
+}
diff --git a/src/fltp/fltp.c b/src/fltp/fltp.c
@@ -6,3 +6,167 @@
#include <libc.h>
#include "fltp.h"
+
+enum {
+ StackSize = 64,
+ TokenBufSize = 4096,
+ WordSize = 16,
+};
+
+typedef struct _context _context;
+typedef struct _stack _stack;
+typedef struct Word Word;
+
+struct _stack {
+ int d;
+ int i;
+ FLTP * s[StackSize];
+};
+
+struct _context {
+ void (*fp)(void *);
+ char *buf;
+ char *tbuf;
+ _stack st;
+ FLTP *fltp;
+ long i;
+ long nbytes; // in ref to buf
+ int ti;
+ Word *wp;
+};
+
+struct Word {
+ void *prev;
+ char str[WordSize];
+ void (*fp)(void *);
+};
+
+Word * getword(Word *wp, char *buf, long nbytes);
+void _buildtoken(void *);
+void _buildline(void *);
+void _beginlist(void *);
+void _endlist(void *);
+
+Word dict[] = {
+ {nil, ".l", _buildline},
+ {&(dict[0]), "{", _beginlist},
+ {&(dict[1]), "}", _endlist},
+};
+
+Word *
+getword(Word *wp, char *buf, long nbytes)
+{
+ for (; wp != nil; wp = wp->prev) {
+ if (nbytes != strlen(wp->str)) continue;
+ if (memcmp(buf, wp->str, nbytes) == 0) break;
+ }
+ return wp;
+}
+
+void
+_buildtoken(void *v)
+{
+ char c;
+ _context *con;
+ Word *wp;
+
+ con = v;
+ if (con->i >= con->nbytes) {
+ con->fp = nil;
+ return;
+ }
+ c = con->buf[con->i];
+ con->i++;
+ if (strchr(" \t\n", c) == nil) {
+ con->tbuf[con->ti] = c;
+ con->ti++;
+ } else {
+ con->fltp = createfltp(con->fltp, con->st.s[con->st.i], con->tbuf, con->ti);
+ wp = getword(con->wp, con->tbuf, con->ti);
+ if ((wp != nil) && (wp->fp != nil)) {
+ con->fp = wp->fp;
+ }
+ con->ti = 0;
+ }
+}
+
+void
+_buildline(void *v)
+{
+ char c;
+ _context *con;
+
+ con = v;
+ if (con->i >= con->nbytes) {
+ con->fp = nil;
+ return;
+ }
+ c = con->buf[con->i];
+ con->i++;
+ if (c != '\n') {
+ con->tbuf[con->ti] = c;
+ con->ti++;
+ } else {
+ con->fltp = createfltp(con->fltp, con->fltp, con->tbuf, con->ti);
+ con->fp = _buildtoken;
+ con->ti = 0;
+ }
+}
+
+void
+_beginlist(void *v)
+{
+ _context *con;
+ con = v;
+ con->fp = _buildtoken;
+ con->st.i++;
+ con->st.s[con->st.i] = con->fltp->prev;
+ con->fltp->parent = con->fltp->prev;
+}
+
+void
+_endlist(void *v)
+{
+ _context *con;
+ con = v;
+ con->fp = _buildtoken;
+ con->st.i--;
+}
+
+FLTP *
+createfltp(void *prev, void *parent, char *buf, long nbytes)
+{
+ FLTP *new;
+ new = malloc(sizeof(FLTP) + nbytes);
+ *new = (FLTP){prev, parent, nbytes};
+ memcpy((char *)new + sizeof(FLTP), buf, nbytes);
+ return new;
+}
+
+FLTP *
+fltpparse(char *buf, long nbytes)
+{
+ _stack st;
+ _context con;
+ char *tbuf;
+ st.d = 1;
+ st.i = 0;
+ st.s[0] = nil;
+ tbuf = malloc(TokenBufSize);
+ memset(&con, 0, sizeof(con));
+ con.fp = _buildtoken;
+ con.buf = buf;
+ con.tbuf = tbuf;
+ con.st = st;
+ con.nbytes = nbytes;
+ con.wp = &(dict[2]);
+ while (con.fp != nil) {
+ if (con.ti >= TokenBufSize)
+ sysfatal("fltpparse: token buf overflow");
+ if (st.i >= StackSize)
+ sysfatal("fltpparse: stack overflow");
+ con.fp(&con);
+ }
+ free(tbuf);
+ return con.fltp;
+}
diff --git a/src/fltp/fltp.h b/src/fltp/fltp.h
@@ -0,0 +1,10 @@
+typedef struct FLTP FLTP;
+
+struct FLTP {
+ void *prev;
+ void *parent;
+ long nbytes;
+};
+
+FLTP * createfltp(void *prev, void *parent, char *buf, long nbytes);
+FLTP * fltpparse(char *buf, long nbytes);
diff --git a/src/fltp/test.c b/src/fltp/test.c
@@ -0,0 +1,15 @@
+#include <u.h>
+#include <libc.h>
+#include "fltp.h"
+
+void
+main(void)
+{
+ char *b = malloc(4096);
+ long n = read(0, b, 4096);
+ FLTP *f = fltpparse(b, n);
+ for (; f != nil; f = f->prev) {
+ fprint(2, "%.11p %.11p %.*s\n",
+ f, f->parent, f->nbytes, (char*)f + sizeof(FLTP));
+ }
+}