diff options
Diffstat (limited to 'slr-table.c')
-rw-r--r-- | slr-table.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/slr-table.c b/slr-table.c index fde8e78..4e12efd 100644 --- a/slr-table.c +++ b/slr-table.c @@ -1,8 +1,8 @@ #include <stdio.h> #include <stdlib.h> +#include <setjmp.h> -// TODO: idk but a good parser shouldn't just exit(1) -// like in itemset_handle() +// TODO: handle conflicts (itemset_insert returns 2 on table problem) #ifndef XCALLOC_IMPLEMENTED #define XCALLOC_IMPLEMENTED @@ -24,8 +24,7 @@ static struct action *__table[TABLE_CAP]; struct action **table = __table; size_t table_states = 0; -int table_fill(); -void table_free(); +static jmp_buf fail_jmpbuf; static void table_allocate() { for(size_t i = 0; i < TABLE_CAP; i++) table[i] = xcalloc(total_symbols, sizeof(*table[i])); } static void table_deallocate() { for(size_t i = 0; i < TABLE_CAP; i++) free(table[i]); } @@ -78,7 +77,7 @@ static size_t itemset_handle(struct item *set, size_t nset) // 2. add set to seen_sets if(nseen_sets >= SEEN_SETS_CAP) { fprintf(stderr, "ERROR: SEEN_SET_CAP exceeded\n"); - exit(1); + longjmp(fail_jmpbuf, 1); } seen_sets[nseen_sets].items = xcalloc(nset, sizeof(*set)); @@ -90,12 +89,12 @@ static size_t itemset_handle(struct item *set, size_t nset) size_t new_state = seen_sets[nseen_sets++].state = table_states++; if(new_state >= TABLE_CAP) { fprintf(stderr, "ERROR: TABLE_CAP exceeded\n"); - exit(1); + longjmp(fail_jmpbuf, 1); } if(itemset_insert(new_state, set, nset)) { fprintf(stderr, "ERROR: itemset_insert failed\n"); - exit(1); + longjmp(fail_jmpbuf, 1); } return new_state; @@ -125,7 +124,7 @@ static int itemset_insert(size_t state, struct item *initial_set, size_t ninitia if(!follow[p->LHS][sym]) continue; if(table_insert(state, sym, (struct action){ ACTION_REDUCE, closure_set[j].prod_idx})) - return 1; + return 2; continue; } @@ -143,7 +142,7 @@ static int itemset_insert(size_t state, struct item *initial_set, size_t ninitia if(symbol_is_input_end(sym)) { if(table_insert(state, sym, (struct action){ACTION_ACCEPT, 0})) - return 1; + return 2; continue; } @@ -151,7 +150,7 @@ static int itemset_insert(size_t state, struct item *initial_set, size_t ninitia if(table_insert(state, sym, (struct action){ symbol_is_terminal(sym) ? ACTION_SHIFT : ACTION_GOTO, - new_state})) return 1; + new_state})) return 2; } return 0; @@ -200,14 +199,16 @@ static int table_insert(size_t state, symbol sym, struct action a) return 0; } -int table_fill() +IMPLEMENT_FUNCPTR(int, table_fill, ()) { table_allocate(); - itemset_handle((struct item[]){{0, 0}}, 1); - return 0; + + int r = setjmp(fail_jmpbuf); + if(r == 0) itemset_handle((struct item[]){{0, 0}}, 1); + return r; } -void table_free() +IMPLEMENT_FUNCPTR(void, table_free, ()) { seen_sets_free(); table_deallocate(); @@ -230,8 +231,8 @@ enum symbol { size_t total_symbols = SYMBOLS_END; -IMPLEMENT_FUNCPTR(int, symbol_is_terminal, (symbol s), { return s < EP; }) -IMPLEMENT_FUNCPTR(int, symbol_is_input_end, (symbol s), { return s == END_INPUT; }) +IMPLEMENT_FUNCPTR(int, symbol_is_terminal, (symbol s)) { return s < EP; } +IMPLEMENT_FUNCPTR(int, symbol_is_input_end, (symbol s)) { return s == END_INPUT; } // implement grammar.h #define PROD(LHS, _, ...) {LHS, (symbol[]){__VA_ARGS__}, sizeof((symbol[]){__VA_ARGS__})/sizeof(symbol)} @@ -254,13 +255,17 @@ size_t total_productions = sizeof(_grammar)/sizeof(*_grammar); int main(void) { + int r = 0; + util_tables_fill(); - table_fill(); + if((r = table_fill())) goto cleanup; table_print(); +cleanup: table_free(); util_tables_free(); + return r; } #endif |