#ifndef TABLE_H #define TABLE_H #include // size_t #include "util/util.h" #define ACTION_TYPE(X) \ X(ACTION_NOT_SET) \ X(ACTION_SHIFT) \ X(ACTION_GOTO) \ X(ACTION_REDUCE) \ X(ACTION_ACCEPT) const char * const action_type_to_char[] = { ACTION_TYPE(X_TO_STR) }; extern struct action { enum action_type { ACTION_TYPE(X_TO_ENUM) } type; size_t arg; } **table; extern size_t table_states; extern int (*table_fill)(); // non-zero on fail extern void (*table_free)(); void table_print(); void table_print_cstyle(); int table_insert(size_t state, symbol sym, struct action a); // should it be here?? #include "symbol.h" void table_print() { printf(" "); for(size_t sym = 0; sym < total_symbols; sym++) printf("%2zu ", sym); printf("\n"); char action_to_char[] = {[ACTION_SHIFT] = 's', [ACTION_REDUCE] = 'r', [ACTION_GOTO] = 'g'}; for(size_t i = 0; i < table_states; i++) { printf("%2zu ", i); for(size_t sym = 0; sym < total_symbols; sym++) if(table[i][sym].type == ACTION_ACCEPT) printf(" a "); else if(table[i][sym].type) printf("%c%-2zu ", action_to_char[table[i][sym].type], table[i][sym].arg); else printf(" "); printf("\n"); } } void table_print_cstyle() { for(size_t i = 0; i < table_states; i++) { printf("(struct action[]){"); for(size_t sym = 0; sym < total_symbols; sym++) printf("{%d, %zu},", table[i][sym].type, table[i][sym].arg); printf("},\n"); } } #include "grammar.h" int table_insert(size_t state, symbol sym, struct action a) { struct action *tbl_a = &table[state][sym]; struct action *new_a = &a; if(tbl_a->type == new_a->type && tbl_a->arg == new_a->arg) return 0; if(tbl_a->type == ACTION_NOT_SET) { *tbl_a = *new_a; return 0; } int r = 0, report = 0, set_tbl_a = 0, reduce_reduce = 0, shift_reduce = 0; struct action *shift_a; if((tbl_a->type == ACTION_REDUCE && new_a->type == ACTION_REDUCE)) reduce_reduce = 1; else if((tbl_a->type == ACTION_REDUCE && new_a->type == ACTION_SHIFT)) { shift_reduce = 1; shift_a = new_a; } else if((tbl_a->type == ACTION_SHIFT && new_a->type == ACTION_REDUCE)) { shift_reduce = 1; shift_a = tbl_a; } #define prec_num(a) PRECEDENCE_NUM(grammar[(a)->arg].precedence) #define prec_flag(a) PRECEDENCE_FLAG(grammar[(a)->arg].precedence) if(reduce_reduce || shift_reduce) { if(prec_num(tbl_a) == 0 || prec_num(new_a) == 0) report = 1; if(prec_num(tbl_a) > prec_num(new_a)) set_tbl_a = 0; else if(prec_num(tbl_a) < prec_num(new_a)) set_tbl_a = 1; else if(reduce_reduce) { report = 1; if(new_a->arg > tbl_a->arg) set_tbl_a = 1; } else { if(prec_flag(tbl_a) == PRECEDENCE_NO_ASSOC && tbl_a->arg == new_a->arg) { report = 1; r = 2; } else if(prec_flag(shift_a) == PRECEDENCE_LEFT_ASSOC) { if(shift_a == tbl_a) set_tbl_a = 1; // favor reduce }else { if(shift_a == new_a) set_tbl_a = 1; // favor shift } } } else { r = 1; report = 1; } if(report) { struct action *a0 = (set_tbl_a) ? new_a: tbl_a; struct action *a1 = (set_tbl_a) ? tbl_a: new_a; fprintf(stderr, "REPORT: table collission on state '%zu' sym '%d'\n", state, sym); fprintf(stderr, "\t%s resolve: {%s %zu} %s {%s %zu}\n", (r == 0) ? "SUCCESSFULLY" : "COULD NOT", action_type_to_char[a0->type], a0->arg, (r == 0) ? "over" : "vs", action_type_to_char[a1->type], a1->arg); } if(!r && set_tbl_a) *tbl_a = *new_a; return r; } #endif