diff options
author | kartofen <mladenovnasko0@gmail.com> | 2025-07-10 00:28:22 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2025-07-10 00:28:22 +0300 |
commit | 8ea8bd7e41c48be9635c29fb928fe9decc4eb112 (patch) | |
tree | c11bdd01040ddcc9e761baa17d7c903205120fba /parts | |
parent | d69d2e7a7e09c4f08cd416241e2f2d9dc7d7d05f (diff) |
shift-reduce did not work, not works (not very good) with no nonassoc
Diffstat (limited to 'parts')
-rw-r--r-- | parts/grammar.h | 4 | ||||
-rw-r--r-- | parts/table.h | 52 |
2 files changed, 38 insertions, 18 deletions
diff --git a/parts/grammar.h b/parts/grammar.h index 4505b1a..594e61e 100644 --- a/parts/grammar.h +++ b/parts/grammar.h @@ -4,9 +4,9 @@ #include <stddef.h> // size_t enum precedence_flag { - PRECEDENCE_NO_ASSOC, - PRECEDENCE_RIGHT_ASSOC, PRECEDENCE_LEFT_ASSOC, + PRECEDENCE_RIGHT_ASSOC, + PRECEDENCE_NO_ASSOC, }; #define PRECEDENCE_NUM(prec) ((prec) >> 2) diff --git a/parts/table.h b/parts/table.h index ff4601f..01a6bbf 100644 --- a/parts/table.h +++ b/parts/table.h @@ -9,7 +9,8 @@ X(ACTION_SHIFT) \ X(ACTION_GOTO) \ X(ACTION_REDUCE) \ - X(ACTION_ACCEPT) + X(ACTION_ACCEPT) \ + X(ACTION_ERROR) const char * const action_type_to_char[] = { ACTION_TYPE(X_TO_STR) @@ -37,7 +38,7 @@ void table_print() 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'}; + char action_to_char[] = {[ACTION_SHIFT] = 's', [ACTION_REDUCE] = 'r', [ACTION_GOTO] = 'g', [ACTION_ERROR] = 'e'}; for(size_t i = 0; i < table_states; i++) { printf("%2zu ", i); for(size_t sym = 0; sym < total_symbols; sym++) @@ -73,36 +74,55 @@ int table_insert(size_t state, symbol sym, struct action a) } int r = 0, report = 0, set_tbl_a = 0, - reduce_reduce = 0, shift_reduce = 0; - struct action *shift_a; + reduce_reduce = 0, shift_reduce = 0, + shift_p, reduce_p, tbl_is_reduce; 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; + tbl_is_reduce = 1; } else if((tbl_a->type == ACTION_SHIFT && new_a->type == ACTION_REDUCE)) { shift_reduce = 1; - shift_a = tbl_a; + tbl_is_reduce = 0; + } + + // bad hack to get precedence of the symbol + if(shift_reduce) { + for(size_t i = 0; i < total_productions; i++) + for(size_t j = 0; j < grammar[i].nRHS; j++) + if(grammar[i].RHS[j] == sym) { + shift_p = grammar[i].precedence; + goto out; + } + out: + if(tbl_is_reduce) reduce_p = grammar[tbl_a->arg].precedence; + else reduce_p = grammar[new_a->arg].precedence; } #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(reduce_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) { + else { 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 if(shift_reduce) { + int favor_shift = 0; + if(shift_p == 0 || reduce_p == 0) { favor_shift = 1; report = 1; } + else if(PRECEDENCE_NUM(shift_p) > PRECEDENCE_NUM(reduce_p)) favor_shift = 1; + else if(PRECEDENCE_NUM(reduce_p) > PRECEDENCE_NUM(shift_p)) favor_shift = 1; + else { + if(PRECEDENCE_FLAG(shift_p) == PRECEDENCE_LEFT_ASSOC) favor_shift = 1; + else if(PRECEDENCE_FLAG(shift_p) == PRECEDENCE_RIGHT_ASSOC) favor_shift = 0; + // else if(PRECEDENCE_FLAG(shift_p) == PRECEDENCE_NO_ASSOC && + // PRECEDENCE_FLAG(reduce_p) == PRECEDENCE_NO_ASSOC) { set_tbl_a = 1; a.type = ACTION_ERROR; a.arg = 0; } + else { favor_shift = 1, report = 1; } + } + + if(favor_shift && tbl_is_reduce || !favor_shift && !tbl_is_reduce) set_tbl_a = 1; } else { r = 1; report = 1; } |