diff options
Diffstat (limited to 'symtab.c')
-rw-r--r-- | symtab.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/symtab.c b/symtab.c new file mode 100644 index 0000000..4229a63 --- /dev/null +++ b/symtab.c @@ -0,0 +1,60 @@ +#include <stdlib.h> +#include <string.h> +#include "symtab.h" + + +struct symtab* symtab_make() { + struct symtab *symtab = malloc(sizeof(struct symtab)); + symtab->parent = NULL; + symtab->cap = 16; + symtab->len = 0; + symtab->syms = malloc(symtab->cap * sizeof(struct symbol*)); + return symtab; +} + +void symtab_delete_recursive(struct symtab *symtab) { + free(symtab->syms); + struct symtab *parent = symtab->parent; + free(symtab); + if (parent) symtab_delete_recursive(parent); +} + +struct symbol* symtab_find(const struct symtab *symtab, const char *name) { + struct symbol *sym = symtab_find_local(symtab, name); + if (sym) return sym; + else if (symtab->parent) return symtab_find(symtab->parent, name); + else return NULL; +} + +struct symbol* symtab_find_local(const struct symtab *symtab, const char *name) { + for (int i = 0; i < symtab->len; i++) { + if (strcmp(symtab->syms[i]->name, name) == 0) return symtab->syms[i]; + } + return NULL; +} + +void symtab_insert(struct symtab *symtab, struct symbol *sym) { + if (symtab->len == symtab->cap) { + symtab->cap *= 2; + symtab->syms = realloc(symtab->syms, symtab->cap * sizeof(struct symbol*)); + } + symtab->syms[symtab->len++] = sym; +} + +struct symtab* symtab_root(struct symtab *symtab) { + if (symtab->parent) return symtab_root(symtab->parent); + else return symtab; +} + +struct symtab* symtab_sub(struct symtab *symtab) { + struct symtab *sub = symtab_make(); + sub->parent = symtab; + return sub; +} + +struct symtab* symtab_delete_get_parent(struct symtab *symtab) { + struct symtab *parent = symtab->parent; + symtab->parent = NULL; + symtab_delete_recursive(symtab); + return parent; +} |