1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#ifndef TABLE_H
#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_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
|