aboutsummaryrefslogtreecommitdiff
path: root/demos/sample-files/gram-skeleton.c
diff options
context:
space:
mode:
authorkartofen <kartofen.mail.0@protonmail.com>2025-07-20 01:32:24 +0300
committerkartofen <kartofen.mail.0@protonmail.com>2025-07-20 01:32:24 +0300
commit34357640c0676f33ad13aac1fe28effc6f6e47c7 (patch)
treed656ee61da7d7a0b133aa57311266653ef100569 /demos/sample-files/gram-skeleton.c
parent174e9b35ce3b6e99e500907f1bb24c6f31f481bf (diff)
start of grammar parsing
Diffstat (limited to 'demos/sample-files/gram-skeleton.c')
-rw-r--r--demos/sample-files/gram-skeleton.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/demos/sample-files/gram-skeleton.c b/demos/sample-files/gram-skeleton.c
new file mode 100644
index 0000000..89ef6b4
--- /dev/null
+++ b/demos/sample-files/gram-skeleton.c
@@ -0,0 +1,149 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define ARENA_IMPLEMENTATION
+#include "util/arena.h"
+
+static char buf[1024];
+static struct arena_ctx global_arena = ARENA_CTX_INIT(buf, sizeof(buf));
+static void *xalloc(size_t sz) {
+ void *addr = arena_allocate(&global_arena, sz);
+ if(!addr) {
+ fprintf(stderr, "ERROR: Arena empty\n"); exit(1);
+ }
+
+ return addr;
+}
+
+// generated
+#include "bin/gram.h"
+#include "bin/gram.c"
+
+#include "parts/toklist.h"
+struct token {
+ symbol s;
+ intptr_t v;
+} tok;
+
+static char *next_token(char *str);
+
+symbol token_sym(struct token *t) { return t->s; }
+intptr_t token_val(struct token *t) { return t->v; }
+
+static char *input = (char []){
+ "-left B;"
+ "-right C;"
+ "-left D;"
+ ""
+ "A: B {a}"
+ " | C N {d}."
+};
+
+struct token *toklist_eat()
+{
+ static struct token t;
+ t = tok;
+ input = next_token(input);
+ return &t;
+}
+
+struct token *toklist_peek() { return &tok; }
+
+#include "lr-parser.c"
+
+int main(void)
+{
+ input = next_token(input);
+
+ intptr_t value;
+ if(lr_parser(&value)) {
+ return 1;
+ }
+
+ printf("OUTPUT: %jd\n", value);
+ return 0;
+}
+
+// STR UTIL
+
+#define strdup(...) _strdup(__VA_ARGS__)
+static inline char *_strdup(char *str)
+{
+ return memcpy(xalloc(strlen(str) + 1), str, strlen(str)+1);
+}
+
+static inline char *substring(char *str, size_t sub_end)
+{
+ static char sub[128];
+ if(sub_end+1 > sizeof(sub)) return NULL;
+
+ sub[sub_end] = '\0';
+ return memcpy(sub, str, sub_end);
+}
+
+// LEXER
+
+static inline int issep(char c)
+{
+ return isspace(c) || c == '\0' || c == ':' || c == '|' || c == ';' || c == '.' || c == '-' || c == '{';
+}
+
+static inline int tillsep(char *str)
+{
+ size_t i = 0;
+ while(!issep(str[i++]));
+ return i-1;
+}
+
+static char *next_token(char *str)
+{
+ if(!str) return str;
+
+ size_t off = 0;
+ char c0 = str[0];
+
+ if(c0 == '\0') tok.s = END_INPUT;
+ if(isspace(c0)) return next_token(str+1);
+ else {
+ off = tillsep(str);
+ if(off == 0) { // sep
+ switch(str[off++]) {
+ case ':': tok.s = COLON; break;
+ case '|': tok.s = PIPE; break;
+ case ';': tok.s = SEMICOL; break;
+ case '.': tok.s = DOT; break;
+ case '-':
+ off = tillsep(++str);
+ char *s = substring(str, off);
+ if(strcmp(s, "left") == 0) tok.s = D_LEFT;
+ else if(strcmp(s, "right") == 0) tok.s = D_RIGHT;
+ else if(strcmp(s, "terminal") == 0) tok.s = D_TERMINAL;
+ else if(strcmp(s, "nonterminal") == 0) tok.s = D_NONTERM;
+ else { fprintf(stderr, "ERROR: Unknown directive '-%s'\n", s); goto fail; }
+ break;
+ case '{':
+ for(int c = 1; c != 0; off++)
+ if(str[off] == '\0') { fprintf(stderr, "ERROR: No closing '{'\n"); goto fail; }
+ else if(str[off] == '{') c++;
+ else if(str[off] == '}') c--;
+ tok.s = ACTION;
+ tok.v = (intptr_t)strdup(substring(str, off));
+ break;
+ }
+ } else if(isalpha(c0)) { // iden or named symbol
+ tok.s = IDEN;
+ tok.v = (intptr_t)strdup(substring(str, off));
+ } else if(c0 >= '0' && c0 <= '9') { // num
+ tok.s = NUM;
+ tok.v = (intptr_t)atoi(substring(str, off));
+ }
+ }
+
+ return str+off;
+
+fail:
+ tok.s = END_INPUT;
+ return NULL;
+}