summaryrefslogtreecommitdiff
path: root/sys/src/games/linden.c
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2019-11-03 13:49:23 +0000
committeraiju <devnull@localhost>2019-11-03 13:49:23 +0000
commitae61eb9381f6b0c70e1c52bf2c2b7f4cd0b5bb6f (patch)
treec62b500d4d8714e56cdb7153fcbc3ab328aa0e76 /sys/src/games/linden.c
parent37827f533bcfe73d8aff7088fbeee1eaa42e8094 (diff)
add games/linden and games/turtle
Diffstat (limited to 'sys/src/games/linden.c')
-rw-r--r--sys/src/games/linden.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/sys/src/games/linden.c b/sys/src/games/linden.c
new file mode 100644
index 000000000..dd013c85f
--- /dev/null
+++ b/sys/src/games/linden.c
@@ -0,0 +1,198 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+
+Biobuf *Bin;
+
+typedef struct Symbol Symbol;
+typedef struct SString SString;
+
+enum { TSTRING = -2 };
+
+struct Symbol {
+ Rune name;
+ SString *rule;
+ char *output;
+ Symbol *next;
+};
+
+struct SString {
+ int n;
+ Symbol **d;
+};
+#pragma varargck type "σ" SString*
+
+Symbol *syms;
+SString *sstring;
+char strbuf[1024];
+
+void *
+emalloc(ulong n)
+{
+ void *v;
+
+ v = malloc(n);
+ if(v == nil) sysfatal("malloc: %r");
+ memset(v, 0, n);
+ setmalloctag(v, getcallerpc(&n));
+ return v;
+}
+
+void
+sstringaddsym(SString *a, Symbol *b)
+{
+ a->d = realloc(a->d, (a->n + 1) * sizeof(Symbol *));
+ a->d[a->n++] = b;
+}
+
+void
+sstringappend(SString *a, SString *b)
+{
+ a->d = realloc(a->d, (a->n + b->n) * sizeof(Symbol *));
+ memcpy(a->d + a->n, b->d, b->n * sizeof(Symbol *));
+ a->n += b->n;
+}
+
+Symbol *
+getsym(Rune name)
+{
+ Symbol **sp;
+
+ for(sp = &syms; *sp != nil; sp = &(*sp)->next)
+ if(name == (*sp)->name)
+ return *sp;
+ *sp = emalloc(sizeof(Symbol));
+ (*sp)->name = name;
+ return *sp;
+}
+
+int peektok = -1;
+
+int
+lex(void)
+{
+ int c;
+ char *p;
+
+ if(peektok >= 0){
+ c = peektok;
+ peektok = -1;
+ return c;
+ }
+ do
+ c = Bgetrune(Bin);
+ while(c >= 0 && c < 0x80 && isspace(c) && c != '\n');
+ if(c == '\''){
+ p = strbuf;
+ for(;;){
+ c = Bgetc(Bin);
+ if(c == '\'') break;
+ if(p < strbuf + sizeof(strbuf) - 1)
+ *p++ = c;
+ }
+ *p = 0;
+ return TSTRING;
+ }
+ return c;
+}
+
+int
+peek(void)
+{
+ if(peektok >= 0) return peektok;
+ return peektok = lex();
+}
+
+SString *
+symstring(void)
+{
+ int c;
+ SString *r;
+
+ r = emalloc(sizeof(SString));
+ for(;;){
+ c = peek();
+ if(c == '\n' || c == ':')
+ break;
+ lex();
+ r->d = realloc(r->d, (r->n + 1) * sizeof(Symbol *));
+ r->d[r->n++] = getsym(c);
+ }
+ return r;
+}
+
+int
+fmtsstring(Fmt *f)
+{
+ SString *s;
+ int i;
+
+ s = va_arg(f->args, SString *);
+ for(i = 0; i < s->n; i++)
+ fmtprint(f, "%C", s->d[i]->name);
+ return 0;
+}
+
+void
+syntax(void)
+{
+ sysfatal("syntax error");
+}
+
+void
+parse(void)
+{
+ Symbol *s;
+ int c;
+
+ sstring = symstring();
+ while(peek() > 0){
+ if(peek() == '\n') {lex(); continue;}
+ if(peek() == ':') syntax();
+ s = getsym(lex());
+ c = lex();
+ if(c == ':')
+ s->rule = symstring();
+ else if(c == '='){
+ if(lex() != TSTRING) syntax();
+ s->output = strdup(strbuf);
+ }else
+ syntax();
+ c = lex();
+ if(c != -1 && c != '\n') syntax();
+ }
+}
+
+SString *
+iterate(SString *in)
+{
+ SString *r;
+ int i;
+
+ r = emalloc(sizeof(SString));
+ for(i = 0; i < in->n; i++)
+ if(in->d[i]->rule == nil)
+ sstringaddsym(r, in->d[i]);
+ else
+ sstringappend(r, in->d[i]->rule);
+ return r;
+}
+
+void
+main()
+{
+ int i, j;
+
+ fmtinstall(L'σ', fmtsstring);
+ Bin = Bfdopen(0, OREAD);
+ if(Bin == nil) sysfatal("Bfdopen: %r");
+ parse();
+ for(j = 0; j < 9; j++){
+ for(i = 0; i < sstring->n; i++)
+ if(sstring->d[i]->output != nil)
+ print("%s\n", sstring->d[i]->output);
+ print("end\n");
+ sstring = iterate(sstring);
+ }
+}