commit 750c673a3f58812925bb6e142712893dc083aa0c
parent 2ab08c12342839c5a7475c332802d37dfd66dda6
Author: rpa <rpa@laika>
Date: Sun, 23 Apr 2023 15:46:11 +0000
tablist: looks like it parses I guess
Diffstat:
4 files changed, 141 insertions(+), 58 deletions(-)
diff --git a/src/tablist/mktest b/src/tablist/mktest
@@ -1,7 +1,7 @@
</$objtype/mkfile
-test:V: $O.test
- $O.test
+test:V: $O.test example.tl
+ $O.test example.tl
$O.test: test.c tablist.h libtablist.a$O
diff --git a/src/tablist/tablist.c b/src/tablist/tablist.c
@@ -5,78 +5,127 @@
struct TLrow {
int indent;
+ TLnode *root;
+};
+
+struct TLparsecontext {
+ TLnode *root;
+ TLnode *stack[64];
int n;
- TLNode *nodes;
};
-struct TLrow
-_tlparseline(char *s)
+TLnode *
+allocTLnode(char *name, char *value)
+{
+ TLnode *node = mallocz(sizeof(TLnode), 1);
+ node->name = name;
+ node->value = value;
+ return node;
+}
+
+int
+freeTLnode(TLnode *node)
+{
+ int i;
+ free(node->name);
+ free(node->value);
+ for(i = 0; i< node->count; i++) {
+ freeTLnode(node->children[node->count - 1]);
+ }
+ free(node);
+ return 0;
+}
+
+int
+TLnodeappend(TLnode *parent, TLnode *child)
+{
+ parent->children =
+ realloc(parent->children, sizeof(TLnode *) * (parent->count + 1));
+ parent->children[parent->count] = child;
+ parent->count++;
+ return 0;
+}
+
+int
+_tlparseline(struct TLrow *row, char *s)
{
char *p;
- struct TLrow row = {0, 0, nil};
+ TLnode **np = &row->root;
while (*s == '\t') {
- row.indent++;
+ row->indent++;
s++;
};
-
- fprint(2, "indent %d\n", row.indent);
-
- if (*s == '\0') return 0;
-
+ if (*s == '\0') {
+ werrstr("empty line");
+ return -1;
+ }
for (;;) {
+ if (*s == ' ') {
+ werrstr("unexpected space");
+ return -1;
+ }
+ if (*np != nil) {
+ TLnodeappend(*np, nil);
+ np = &((*np)->children[(*np)->count - 1]);
+ }
if (*s == '\\') {
- s++;
- row.nodes = realloc(row.nodes, (row.n + 1) * sizeof(TLNode));
- memset(&row.nodes[row.n], 0, sizeof(TLNode));
- char *v = strdup(s);
- row.nodes[row.n].value = v;
- row.n++;
+ *np = allocTLnode(nil, strdup(s + 1));
break;
}
p = strchr(s, ' ');
- if (p == s) {
- sysfatal("tlparseline: unexpected space");
- } else if (p == nil) {
- row.nodes = realloc(row.nodes, (row.n + 1) * sizeof(TLNode));
- memset(&row.nodes[row.n], 0, sizeof(TLNode));
- char *n = strdup(s);
- row.nodes[row.n].name = n;
- row.n++;
- break;
- } else {
- *p = '\0';
- row.nodes = realloc(row.nodes, (row.n + 1) * sizeof(TLNode));
- memset(&row.nodes[row.n], 0, sizeof(TLNode));
- char *n = strdup(s);
- row.nodes[row.n].name = n;
- row.n++;
- s = p + 1;
- }
+ if (p != nil) *p = '\0';
+ *np = allocTLnode(strdup(s), nil);
+ if (p == nil) break;
+ else s = p + 1;
}
- return row;
+ return 0;
}
-int
+TLnode *
_tlparse(char *data, usize count)
{
+ struct TLparsecontext pc = {
+ .root = allocTLnode(nil, nil),
+ .n = 0,
+ };
+ pc.stack[0] = pc.root;
int rown = 0;
- struct TLrow row;
char *e, *p = data;
while (p < (data + count)) {
-
- fprint(2, "<%d>\n", rown);
-
+ struct TLrow row = {0, nil};
+ rown++;
+ if (*p == '\n') {
+ p++;
+ pc.n = 0;
+ continue;
+ }
e = memchr(p, '\n', count - (p - data));
if (e == nil) {
- werrstr("newline not found");
- return -1;
+ werrstr("%d, newline not found", rown);
+ free(pc.root);
+ return nil;
}
- if (p != e) {
- *e = '\0';
- row = _tlparseline(p);
+ *e = '\0';
+ if (_tlparseline(&row, p) < 0) {
+ werrstr("%d: %r", rown);
+ return nil;
}
p = e + 1;
- rown++;
+ if (row.indent == pc.n + 1) {
+ pc.n++;
+ }
+ if (pc.n >= row.indent) {
+ pc.n = row.indent;
+ TLnodeappend(pc.stack[pc.n], row.root);
+ pc.stack[pc.n + 1] = row.root;
+ while(pc.stack[pc.n + 1]->count != 0) {
+ pc.stack[pc.n + 1] = pc.stack[pc.n + 1]->children[0];
+ }
+ } else {
+ werrstr("%d: too much indent", rown);
+ // TODO: clean up
+ return nil;
+ }
}
- return 0;
+ return pc.root;
}
diff --git a/src/tablist/tablist.h b/src/tablist/tablist.h
@@ -1,9 +1,14 @@
#pragma lib "../tablist/libtablist.a$O"
-typedef struct TLNode TLNode;
-struct TLNode {
+typedef struct TLnode TLnode;
+struct TLnode {
char *name;
char *value;
- TLNode *children;
+ TLnode **children;
+ int count;
};
-int _tlparse(char *, usize);
+TLnode * allocTLnode(char *, char *);
+int freeTLnode(TLnode *);
+int TLnodeappend(TLnode *, TLnode *);
+
+TLnode * _tlparse(char *, usize);
diff --git a/src/tablist/test.c b/src/tablist/test.c
@@ -2,16 +2,45 @@
#include <libc.h>
#include "tablist.h"
+void tlprint(int, TLnode *);
+
+void
+tlprint(int indent, TLnode *node)
+{
+ int i;
+ for (i = 0; i < indent; i++) print("\t");
+
+ if (node->name) print("%s", node->name);
+ else if (node->value) {
+ print("\\%s", node->value);
+ }
+ else print("\\");
+
+ print("\n");
+
+ for (i = 0; i < node->count; i++) {
+ tlprint(indent + 1, node->children[i]);
+ }
+}
+
void
-main(void)
+test(char *path)
{
- print("~~~testing~~~\n");
+ TLnode *root;
int n, fd;
char buf[4096];
- fd = open("example.tl", OREAD);
+ fd = open(path, OREAD);
if (fd < 0) sysfatal("%r");
n = readn(fd, buf, 4096);
- _tlparse(buf, n);
- print("~~~done!~~~\n");
+ root = _tlparse(buf, n);
+ if (root == nil) sysfatal("%r");
+ tlprint(0, root);
exits(nil);
}
+
+void
+main(int argc, char **argv)
+{
+ int i;
+ for (i = 1; i < argc; i++) test(argv[i]);
+}