aboutsummaryrefslogtreecommitdiff
path: root/demos/sample-files/lbp-skeleton.c
diff options
context:
space:
mode:
Diffstat (limited to 'demos/sample-files/lbp-skeleton.c')
-rw-r--r--demos/sample-files/lbp-skeleton.c267
1 files changed, 223 insertions, 44 deletions
diff --git a/demos/sample-files/lbp-skeleton.c b/demos/sample-files/lbp-skeleton.c
index ae0a17f..bf7bdca 100644
--- a/demos/sample-files/lbp-skeleton.c
+++ b/demos/sample-files/lbp-skeleton.c
@@ -4,34 +4,84 @@
#include <stdint.h>
#include <ctype.h>
-// TODO: lr parser is bad for debugging
+// TODO: - lr parser is bad for debugging
+// - deal with errors
#define INPUT_CAP 4096
-#define ARENA_CAP 4096
+#define ARENA_CAP 8192 //4096
#define ARENA_IMPLEMENTATION
#include "util/arena.h"
static char buf[ARENA_CAP];
static struct arena_ctx global_arena;
-static void *xalloc(size_t sz) {
- void *addr = arena_allocate(&global_arena, sz);
+static void *xalloc(size_t size) {
+ void *addr = arena_allocate(&global_arena, size);
if(!addr) {
fprintf(stderr, "ERROR: Arena empty\n"); exit(1);
}
return addr;
}
+static void *xcalloc(size_t nmemb, size_t size) { return xalloc(nmemb * size); }
+static void xfree(void *ptr) { (void)ptr; return; }
+
+// macros to create the g_ variant of the function
+// where everything is cast to and from intptr_t
+// so it plays nicely with the lr parser
+// #define EMPTY()
+// #define DEFER(m) m EMPTY()
+// #define EVAL3(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
+// #define EVAL2(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
+// #define EVAL1(...) __VA_ARGS__
+
+// #define A1(type, name) type name
+// #define A2(type, name) intptr_t name
+// #define A3(type, name) (type)name
+
+// #define _map2() map2
+// #define map2(F, type, name, ...) F(type, name) __VA_OPT__(, DEFER(_map2)()(F, __VA_ARGS__))
+// #define map(a, ...) DEFER(_map2)()(a, EVAL1 __VA_ARGS__)
+
+// #define g(ret, name, args) EVAL3( \
+ ret name(map(A1, args)); \
+ intptr_t g_##name(map(A2, args)) \
+ { return (intptr_t)name(map(A3, args)); } \
+ ret name(map(A1, args)))
-// other things here
#include "util/list.h"
-static inline struct list_head *list_new_head(struct list_head *head, struct list_head *new)
-{
- if(head) list_add(new, head);
- return new;
-}
-#define list_new_head(head, new) (intptr_t)list_new_head((struct list_head *)head, (struct list_head *)new)
+struct ast_strlist { char *str; struct list_head list; };
+
+struct ast_expr {
+ enum { AST_NUMBER, AST_VARIABLE, AST_FIELDLIST, AST_DECLARATION, AST_DEFINITION, AST_OPERATION, AST_PARENLIST } type;
+ union {
+ int number;
+ struct ast_vrbl { int is_atom; char *iden; } variable;
+ struct ast_fiel { struct ast_vrbl variable; struct list_head *fields_strlist; } fieldlist;
+ struct ast_decl { struct ast_vrbl variable; int typed; } declaration;
+ struct ast_defn { struct ast_decl declartion; struct list_head *block_exprlist; } definition;
+ struct ast_oprn { enum { AST_OP_AND, AST_OP_OR } optype; struct list_head *left_exprlist; struct list_head *right_exprlist; } operation;
+ struct list_head *paren_exprlist;
+ };
+ struct list_head list;
+};
+
+#define NEW(t, ...) ((struct ast_##t){__VA_ARGS__})
+#define g_NEW(t, ...) ((stack_item){.t = (struct ast_##t){__VA_ARGS__}})
+
+#define LST(v) ({ typeof(v) *r = xalloc(sizeof(v)); *r = v; LIST_EMPTY(&r->list); &r->list; })
+#define g_LST(v) ((stack_item){.list = LST(v)})
+
+void ast_vrbl_print(struct ast_vrbl *vrbl);
+void ast_fiel_print(struct ast_fiel *fiel);
+void ast_decl_print(struct ast_decl *decl);
+void ast_defn_print(struct ast_defn *defn);
+void ast_oprn_print(struct ast_oprn *oprn);
+void ast_expr_print(struct ast_expr *expr);
+void ast_exprlist_print(struct list_head *list);
+
+void ast_exprlist_free(struct list_head *list);
// generated
#include "bin/lbp.h"
@@ -57,23 +107,31 @@ static uint8_t dict_lowercase_char_to_bit[256] = {
['y'] = 26, ['z'] = 27, [ 0 ] = 1, [' '] = 1
};
-
#include "parts/toklist.h"
struct token {
symbol s;
- intptr_t v;
+ stack_item v;
};
-
-#include "util/queue.h"
-QUEUE_GENERATE(tokbuf, struct token, 16)
+#define TOKEN_INIT(sym, val) (struct token){ .s = sym, .v = val }
+static void print_token(struct token *t);
symbol token_sym(struct token *t) { return t->s; }
-intptr_t token_val(struct token *t) { return t->v; }
+intptr_t token_val(struct token *t) { return (intptr_t)&t->v; }
-static void print_token(struct token *t);
+static char *input;
+static size_t line = 1;
+static size_t active_region;
static char *next_token(char *str);
-static char *input;
+static inline char *substring(char *str, size_t sub_end);
+static inline char *linestart(char *strstart, char *pos);
+static inline size_t tillch(char *str, size_t len, char ch);
+#define strdup(...) _strdup(__VA_ARGS__)
+static inline char *_strdup(char *str);
+
+
+#include "util/queue.h"
+QUEUE_GENERATE(tokbuf, struct token, 16)
struct token *toklist_eat()
{
@@ -85,7 +143,7 @@ struct token *toklist_eat()
struct token *toklist_peek() {
static struct token t;
- tokbuf_peek(&t); // err not checked
+ tokbuf_peek(&t); // err not checked
return &t;
}
@@ -94,6 +152,8 @@ struct token *toklist_peek() {
int main(void)
{
+ char *filename = "stdin";
+
static char input_buf[INPUT_CAP];
if(fread(input_buf, INPUT_CAP, 1, stdin) == INPUT_CAP) {
fprintf(stderr, "INPUT_CAP reached\n");
@@ -103,6 +163,7 @@ int main(void)
global_arena = ARENA_CTX_INIT(buf, ARENA_CAP);
types_dict = DICT_INIT(types_strings, ntypes_strings, dict_lowercase_char_to_bit);
+ // DICT_SET_ALLOCATOR(&types_dict, xcalloc, xfree);
dict_compile(&types_dict);
input = next_token(input_buf);
@@ -113,22 +174,43 @@ int main(void)
// if(token_sym(tok) == END_INPUT) break;
// } return 0;
- intptr_t value;
- if(lr_parser(&value)) {
- fprintf(stderr, input);
- return 1;
+ stack_item value;
+ struct lr_errinfo *errinfo;
+ if((errinfo = lr_parser(&value))) {
+ char *l = linestart(input_buf, input);
+
+ fprintf(stderr, "%s:%zu:%zu: ERROR: %s\n", filename, line, input - l - active_region+1, lr_err_str(errinfo));
+
+ size_t indent = fprintf(stderr, " %zu ", line);
+ fprintf(stderr, "| %s\n", substring(l, tillch(l, strlen(l), '\n')));
+
+ fprintf(stderr, "%*s| %*s", indent, "", input - l - active_region, "");
+ if(active_region == 0) active_region = 1;
+ fprintf(stderr, "^"); for(size_t i = 0; i < active_region-1; i++) fprintf(stderr, "~");
+
+ fprintf(stderr, "\n\n");
+ goto cleanup;
}
- fprintf(stderr, "OUTPUT: %jd\n", value);
+ ast_exprlist_print(value.list);
+ // ast_exprlist_free(value.list);
+cleanup:
dict_free(&types_dict);
return 0;
}
static void print_token(struct token *tok)
{
+ // TODO: unfinished function
printf("%s\n", symbol_to_str[token_sym(tok)]);
- if(token_sym(tok) == IDEN || token_sym(tok) == ATOM) printf(" %s\n", (char *)token_val(tok));
+ switch(token_sym(tok)) {
+ case IDEN:
+ case ATOM:
+ printf(" %s\n", (char *)token_val(tok));
+ break;
+ default: break;
+ }
}
// STR UTIL
@@ -150,6 +232,12 @@ static inline char *substring(char *str, size_t sub_end)
return memcpy(sub, str, sub_end);
}
+static inline char *linestart(char *strstart, char *pos)
+{
+ while(pos-- > strstart) if(*pos == '\n') return pos+1;
+ return strstart;
+}
+
static inline size_t tillch(char *str, size_t len, char ch)
{
for(size_t i = 0; i < len; i++) if(str[i] == ch) return i;
@@ -160,8 +248,10 @@ static inline size_t tillch(char *str, size_t len, char ch)
static inline int issep(char c)
{
- return isspace(c) || c == '\0' || c == '/' || c == ',' || c == ';' ||
- c == '.' || c == '(' || c == ')' || c == '{' || c == '}';
+ return isspace(c) ||
+ c == '\0' || c == '/' || c == ',' || c == ';' ||
+ c == '.' || c == '(' || c == ')' || c == '{' ||
+ c == '}';
}
static inline int tillsep(char *str)
@@ -180,10 +270,9 @@ static char *typelist_tokenize(char *str)
int s = dict_check(&types_dict, substring(str, off));
if(s < 0) {
fprintf(stderr, "ERROR: Unknown type or subtype %s\n", substring(NULL, 0));
- return NULL;
+ } else {
+ tokbuf_enqueue(&TOKEN_INIT(s, { .num = s }));
}
-
- tokbuf_enqueue(&(struct token){.s = s, .v = s});
}
str += off;
@@ -191,9 +280,12 @@ static char *typelist_tokenize(char *str)
switch(str[0]) {
case '-': return typelist_tokenize(str+1);
case '(':
+ size_t depth = 0;
while((str = next_token(str)))
- if(*(str-1)== ')') { // not really
- if(str[0] == '-') return typelist_tokenize(str+1);
+ if(str[0] == '(') depth++;
+ else if(*(str-1) == ')') {
+ if(depth > 0) depth--;
+ else if(str[0] == '-') return typelist_tokenize(str+1);
else return str;
}
return NULL;
@@ -209,8 +301,10 @@ static char *next_token(char *str)
size_t off = 0;
char c0 = str[0];
- if(c0 == '\0') tok.s = END_INPUT;
+ if(c0 == '\n') line++;
if(isspace(c0)) return next_token(str+1);
+
+ if(c0 == '\0') tok.s = END_INPUT;
else {
off = tillsep(str);
if(off == 0) { // sep
@@ -223,26 +317,28 @@ static char *next_token(char *str)
case '{': tok.s = LBRACE; break;
case '}': tok.s = RBRACE; break;
case '/':
+ char *s2 = str;
tok.s = TYPELIST_START; tokbuf_enqueue(&tok);
- if(!(str = typelist_tokenize(str+off))) goto fail;
+ if(!(s2 = typelist_tokenize(s2+off))) goto fail;
tok.s = TYPELIST_END; tokbuf_enqueue(&tok);
- return str;
- default: break;
+ active_region = s2 - str; return s2;
+ default: fprintf(stderr, "ERROR: Unknown sep '%c'\n", c0); break;
}
} else if(c0 >= '0' && c0 <= '9') { // num
tok.s = NUM;
- tok.v = (intptr_t)atoi(substring(str, off)); // not really
+ tok.v = (stack_item){ .num = atoi(substring(str, off)) }; // not really
} else { // iden or atom (possibly with fields)
+ active_region = off;
int hasfield = 0;
size_t sub_off;
do {
sub_off = tillch(str + 1, off - 1, ':') + 1;
- if(hasfield)
- tokbuf_enqueue(&(struct token){.s = COLON, .v = 0});
+ if(hasfield) tokbuf_enqueue(&TOKEN_INIT(COLON, { .num=0 }));
- tokbuf_enqueue(&(struct token){.s = (!hasfield && str[0] == ':') ? ATOM : IDEN,
- .v = (intptr_t)strdup(substring(str+hasfield, sub_off-hasfield))});
+ tokbuf_enqueue(
+ &TOKEN_INIT((!hasfield && str[0] == ':') ? ATOM : IDEN,
+ { .str = strdup(substring(str+hasfield, sub_off-hasfield))}));
} while(hasfield = 1, str += sub_off, off -= sub_off, off > 0);
return str;
@@ -250,9 +346,92 @@ static char *next_token(char *str)
}
tokbuf_enqueue(&tok);
+ active_region = off;
return str+off;
fail:
- tokbuf_enqueue(&(struct token){.s = END_INPUT});
- return NULL;
+ exit(14);
+ // tok.s = END_INPUT; tokbuf_enqueue(&tok);
+ // return NULL;
+}
+
+// ast printing
+
+void ast_vrbl_print(struct ast_vrbl *vrbl)
+{
+ printf("%s%s", vrbl->is_atom ? ":" : "", vrbl->iden);
+}
+
+void ast_fiel_print(struct ast_fiel *fiel)
+{
+ ast_vrbl_print(&fiel->variable);
+ list_for_each_entry(struct ast_strlist, entry, list, fiel->fields_strlist) {
+ printf(":%s", entry->str);
+ }
+}
+
+void ast_decl_print(struct ast_decl *decl)
+{
+ // TODO: implement
+}
+
+void ast_defn_print(struct ast_defn *defn)
+{
+ // TODO: implement
+}
+
+void ast_oprn_print(struct ast_oprn *oprn)
+{
+ ast_exprlist_print(oprn->left_exprlist);
+ if(oprn->optype == AST_OP_AND) printf(",\n"); else printf(";\n");
+ ast_exprlist_print(oprn->right_exprlist);
+}
+
+void ast_expr_print(struct ast_expr *expr) { ast_exprlist_print(&expr->list); }
+void ast_exprlist_print(struct list_head *list)
+{
+ list_for_each_entry(struct ast_expr, entry, list, list)
+ {
+ switch(entry->type) {
+ case AST_NUMBER: printf("%d", entry->number); break;
+ case AST_VARIABLE: ast_vrbl_print(&entry->variable); break;
+ case AST_FIELDLIST: ast_fiel_print(&entry->fieldlist); break;
+ case AST_DECLARATION: ast_decl_print(&entry->declaration); break;
+ case AST_OPERATION: ast_oprn_print(&entry->operation); break;
+ case AST_PARENLIST:
+ printf("(");
+ ast_exprlist_print(entry->paren_exprlist);
+ printf(")");
+ break;
+ default: fprintf(stderr, "UNKNOWN TYPE: %d\n", entry->type);
+ }
+ printf(" ");
+ }
+ printf("\n");
+}
+
+void ast_exprlist_free(struct list_head *list)
+{
+ list_for_each_safe(l, list) {
+ struct ast_expr *entry = list_entry(l, typeof(*entry), list);
+
+ switch(entry->type) {
+ case AST_NUMBER: break;
+ case AST_VARIABLE: break;
+ case AST_FIELDLIST:
+ list_for_each_safe(l, entry->fieldlist.fields_strlist)
+ free(list_entry(l, struct ast_strlist, list));
+ break;
+ case AST_DECLARATION: break;
+ case AST_DEFINITION: break;
+ case AST_OPERATION:
+ ast_exprlist_free(entry->operation.left_exprlist);
+ ast_exprlist_free(entry->operation.right_exprlist);
+ break;
+ case AST_PARENLIST: ast_exprlist_free(entry->paren_exprlist); break;
+ default: fprintf(stderr, "UNKNOWN TYPE: %d\n", entry->type);
+ }
+
+ free(entry);
+ }
}