aboutsummaryrefslogtreecommitdiff
path: root/parts/table.h
diff options
context:
space:
mode:
Diffstat (limited to 'parts/table.h')
-rw-r--r--parts/table.h82
1 files changed, 77 insertions, 5 deletions
diff --git a/parts/table.h b/parts/table.h
index f3099fe..ff4601f 100644
--- a/parts/table.h
+++ b/parts/table.h
@@ -2,13 +2,21 @@
#define TABLE_H
#include <stddef.h> // 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_NOT_SET = 0, ACTION_SHIFT,
- ACTION_GOTO, ACTION_REDUCE,
- ACTION_ACCEPT
- } type;
+ enum action_type { ACTION_TYPE(X_TO_ENUM) } type;
size_t arg;
} **table;
@@ -19,6 +27,7 @@ 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"
@@ -51,4 +60,67 @@ void table_print_cstyle()
}
}
+#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