aboutsummaryrefslogtreecommitdiff
path: root/parts
diff options
context:
space:
mode:
Diffstat (limited to 'parts')
-rw-r--r--parts/grammar.h4
-rw-r--r--parts/table.h52
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;
}