### States and the goto tables.
-For each state we record the goto table and the reducible production if
-there is one.
+For each state we record the goto table, the reducible production if
+there is one, or a symbol to shift for error recovery.
Some of the details of the reducible production are stored in the
`do_reduce` function to come later. Here we store the production number,
the body size (useful for stack management) and the resulting symbol (useful
short reduce_prod;
short reduce_size;
short reduce_sym;
+ short shift_sym;
};
fprintf(f, "static const struct state states[] = {\n");
for (i = 0; i < g->states; i++) {
struct itemset *is = g->statetab[i];
- int j, prod = -1;
+ int j, prod = -1, prod_len;
+ int shift_sym = -1;
+ int shift_len = 0, shift_remain = 0;
for (j = 0; j < is->items.cnt; j++) {
int itm = is->items.syms[j];
int p = item_prod(itm);
int bp = item_index(itm);
struct production *pr = g->productions[p];
- if (bp < pr->body_size)
+ if (bp < pr->body_size) {
+ if (shift_sym < 0 ||
+ (shift_len == bp && shift_remain > pr->body_size - bp)) {
+ shift_sym = pr->body[bp]->num;
+ shift_len = bp;
+ shift_remain = pr->body_size - bp;
+ }
continue;
+ }
/* This is what we reduce */
- prod = p;
- break;
+ if (prod < 0 || prod_len < pr->body_size) {
+ prod = p;
+ prod_len = pr->body_size;
+ }
}
- fprintf(f, "\t[%d] = { %d, goto_%d, %d, %d, %d },\n",
- i, is->go_to.cnt, i, prod,
- prod < 0 ? -1 : g->productions[prod]->body_size,
- prod < 0 ? -1 : g->productions[prod]->head->num);
+ if (prod >= 0)
+ fprintf(f, "\t[%d] = { %d, goto_%d, %d, %d, %d, 0 },\n",
+ i, is->go_to.cnt, i, prod,
+ g->productions[prod]->body_size,
+ g->productions[prod]->head->num);
+ else
+ fprintf(f, "\t[%d] = { %d, goto_%d, -1, -1, -1, %d },\n",
+ i, is->go_to.cnt, i, shift_sym);
}
fprintf(f, "};\n\n");
}