aboutsummaryrefslogtreecommitdiff
path: root/slr-table.c
diff options
context:
space:
mode:
Diffstat (limited to 'slr-table.c')
-rw-r--r--slr-table.c39
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