#include #include #include #include #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; }