diff options
Diffstat (limited to 'parts')
-rw-r--r-- | parts/grammar.h | 12 | ||||
-rw-r--r-- | parts/symbol.h | 6 | ||||
-rw-r--r-- | parts/table.h | 82 |
3 files changed, 89 insertions, 11 deletions
diff --git a/parts/grammar.h b/parts/grammar.h index d1bf176..4505b1a 100644 --- a/parts/grammar.h +++ b/parts/grammar.h @@ -3,10 +3,20 @@ #include <stddef.h> // size_t +enum precedence_flag { + PRECEDENCE_NO_ASSOC, + PRECEDENCE_RIGHT_ASSOC, + PRECEDENCE_LEFT_ASSOC, +}; + +#define PRECEDENCE_NUM(prec) ((prec) >> 2) +#define PRECEDENCE_FLAG(prec) ((prec) & 0x3) + extern struct production { symbol LHS; symbol *RHS; size_t nRHS; + unsigned int precedence; } *grammar; extern size_t total_productions; @@ -29,7 +39,7 @@ void grammar_print_cstyle() printf("{%d, (symbol[]){", grammar[i].LHS); for(size_t j = 0; j < grammar[i].nRHS; j++) printf("%d, ", grammar[i].RHS[j]); - printf("}, %zu},\n", grammar[i].nRHS); + printf("}, %zu, %d},\n", grammar[i].nRHS, grammar[i].precedence); } } diff --git a/parts/symbol.h b/parts/symbol.h index 2190eca..c7314f4 100644 --- a/parts/symbol.h +++ b/parts/symbol.h @@ -11,10 +11,6 @@ extern int (*symbol_is_terminal)(symbol s); extern int (*symbol_is_input_end)(symbol s); extern int (*symbol_is_valid)(symbol s); -// helper macro -#define IMPLEMENT_FUNCPTR(type, name, args) \ - type __##name args; \ - type (*name) args = __##name; \ - type __##name args +#include "util/util.h" //temp #endif 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 |