diff options
Diffstat (limited to 'src/parse.c')
-rw-r--r-- | src/parse.c | 74 |
1 files changed, 63 insertions, 11 deletions
diff --git a/src/parse.c b/src/parse.c index 18dfffe..2ef3817 100644 --- a/src/parse.c +++ b/src/parse.c @@ -3,33 +3,85 @@ #include <stdlib.h> +#include <lib/list.h> #include <parse.h> #include <log.h> +#include <map.h> -struct term *parse_blc(char **term) +static struct term_handle abs_blc(char **term) +{ + term_type_t res_type = ABS; + struct term_handle inner = parse_blc(term); + hash_t res = hash((uint8_t *)&res_type, sizeof(res_type), inner.hash); + + struct term *res_term; + if (!(res_term = map_get(res))) { + res_term = term_new(res_type, res); + res_term->u.abs.term = inner.term; + map_set(res_term, res); + } + + res_term->u.abs.term->parents = + list_add(res_term->u.abs.term->parents, res_term); + return (struct term_handle){ .term = res_term, .hash = res }; +} + +static struct term_handle app_blc(char **term) +{ + term_type_t res_type = APP; + struct term_handle lhs = parse_blc(term); + struct term_handle rhs = parse_blc(term); + + hash_t res = hash((uint8_t *)&res_type, sizeof(res_type), lhs.hash); + res = hash((uint8_t *)&res, sizeof(res), rhs.hash); + + struct term *res_term; + if (!(res_term = map_get(res))) { + res_term = term_new(res_type, res); + res_term->u.app.lhs = lhs.term; + res_term->u.app.rhs = rhs.term; + map_set(res_term, res); + } + + res_term->u.app.lhs->parents = + list_add(res_term->u.app.lhs->parents, res_term); + res_term->u.app.rhs->parents = + list_add(res_term->u.app.rhs->parents, res_term); + return (struct term_handle){ .term = res_term, .hash = res }; +} + +static struct term_handle var_blc(int index) +{ + term_type_t res_type = VAR; + hash_t res = hash((uint8_t *)&res_type, sizeof(res_type), index); + + struct term *res_term; + if (!(res_term = map_get(res))) { + res_term = term_new(res_type, res); + res_term->u.var.index = index; + map_set(res_term, res); + } + + return (struct term_handle){ .term = res_term, .hash = res }; +} + +struct term_handle parse_blc(char **term) { if (!**term) { fatal("invalid parsing state!\n"); } else if (**term == '0' && *(*term + 1) == '0') { (*term) += 2; - struct term *new = term_new(ABS); - new->u.abs.term = parse_blc(term); - return new; + return abs_blc(term); } else if (**term == '0' && *(*term + 1) == '1') { (*term) += 2; - struct term *new = term_new(APP); - new->u.app.lhs = parse_blc(term); - new->u.app.rhs = parse_blc(term); - return new; + return app_blc(term); } else if (**term == '1') { const char *cur = *term; while (**term == '1') (*term)++; int index = *term - cur - 1; (*term)++; - struct term *new = term_new(VAR); - new->u.var.index = index; - return new; + return var_blc(index); } else { (*term)++; return parse_blc(term); |