summaryrefslogtreecommitdiff
path: root/yacc/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'yacc/output.c')
-rw-r--r--yacc/output.c900
1 files changed, 900 insertions, 0 deletions
diff --git a/yacc/output.c b/yacc/output.c
new file mode 100644
index 0000000000..5ebc5b26ba
--- /dev/null
+++ b/yacc/output.c
@@ -0,0 +1,900 @@
+#include "defs.h"
+
+static int nvectors;
+static int nentries;
+static short **froms;
+static short **tos;
+static short *tally;
+static short *width;
+static short *state_count;
+static short *order;
+static short *base;
+static short *pos;
+static int maxtable;
+static short *table;
+static short *check;
+static int lowzero;
+static int high;
+
+
+output()
+{
+ extern char *header[], *define_tables[];
+
+ free_itemsets();
+ free_shifts();
+ free_reductions();
+ write_section(header);
+ output_stored_text();
+ output_transl();
+ output_rule_data();
+ output_yydefred();
+ output_actions();
+ free_parser();
+ output_debug();
+ output_trailing_text();
+ if (sflag)
+ fprintf(output_file,
+ "let yyact = Array.new %d (fun () -> (failwith \"parser\" : Obj.t))\n",
+ ntotalrules);
+ else
+ fprintf(output_file,
+ "let yyact = [|\n (fun () -> failwith \"parser\")\n");
+ output_semantic_actions();
+ if (!sflag)
+ fprintf(output_file, "|]\n");
+ write_section(define_tables);
+ output_entries();
+}
+
+
+static void output_char(n)
+ unsigned n;
+{
+ n = n & 0xFF;
+ putc('\\', output_file);
+ putc('0' + n / 100, output_file);
+ putc('0' + (n / 10) % 10, output_file);
+ putc('0' + n % 10, output_file);
+}
+
+static void output_short(n)
+ int n;
+{
+ output_char(n);
+ output_char(n >> 8);
+}
+
+output_rule_data()
+{
+ register int i;
+ register int j;
+
+
+ fprintf(output_file, "let yylhs = \"");
+ output_short(symbol_value[start_symbol]);
+
+ j = 8;
+ for (i = 3; i < nrules; i++)
+ {
+ if (j >= 8)
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+ else
+ ++j;
+
+ output_short(symbol_value[rlhs[i]]);
+ }
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+
+ fprintf(output_file, "let yylen = \"");
+ output_short(2);
+
+ j = 8;
+ for (i = 3; i < nrules; i++)
+ {
+ if (j >= 8)
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+ else
+ j++;
+
+ output_short(rrhs[i + 1] - rrhs[i] - 1);
+ }
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+}
+
+
+output_yydefred()
+{
+ register int i, j;
+
+ fprintf(output_file, "let yydefred = \"");
+ output_short(defred[0] ? defred[0] - 2 : 0);
+
+ j = 8;
+ for (i = 1; i < nstates; i++)
+ {
+ if (j < 8)
+ ++j;
+ else
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+
+ output_short(defred[i] ? defred[i] - 2 : 0);
+ }
+
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+}
+
+
+output_actions()
+{
+ nvectors = 2*nstates + nvars;
+
+ froms = NEW2(nvectors, short *);
+ tos = NEW2(nvectors, short *);
+ tally = NEW2(nvectors, short);
+ width = NEW2(nvectors, short);
+
+ token_actions();
+ FREE(lookaheads);
+ FREE(LA);
+ FREE(LAruleno);
+ FREE(accessing_symbol);
+
+ goto_actions();
+ FREE(goto_map + ntokens);
+ FREE(from_state);
+ FREE(to_state);
+
+ sort_actions();
+ pack_table();
+ output_base();
+ output_table();
+ output_check();
+}
+
+
+token_actions()
+{
+ register int i, j;
+ register int shiftcount, reducecount;
+ register int max, min;
+ register short *actionrow, *r, *s;
+ register action *p;
+
+ actionrow = NEW2(2*ntokens, short);
+ for (i = 0; i < nstates; ++i)
+ {
+ if (parser[i])
+ {
+ for (j = 0; j < 2*ntokens; ++j)
+ actionrow[j] = 0;
+
+ shiftcount = 0;
+ reducecount = 0;
+ for (p = parser[i]; p; p = p->next)
+ {
+ if (p->suppressed == 0)
+ {
+ if (p->action_code == SHIFT)
+ {
+ ++shiftcount;
+ actionrow[p->symbol] = p->number;
+ }
+ else if (p->action_code == REDUCE && p->number != defred[i])
+ {
+ ++reducecount;
+ actionrow[p->symbol + ntokens] = p->number;
+ }
+ }
+ }
+
+ tally[i] = shiftcount;
+ tally[nstates+i] = reducecount;
+ width[i] = 0;
+ width[nstates+i] = 0;
+ if (shiftcount > 0)
+ {
+ froms[i] = r = NEW2(shiftcount, short);
+ tos[i] = s = NEW2(shiftcount, short);
+ min = MAXSHORT;
+ max = 0;
+ for (j = 0; j < ntokens; ++j)
+ {
+ if (actionrow[j])
+ {
+ if (min > symbol_value[j])
+ min = symbol_value[j];
+ if (max < symbol_value[j])
+ max = symbol_value[j];
+ *r++ = symbol_value[j];
+ *s++ = actionrow[j];
+ }
+ }
+ width[i] = max - min + 1;
+ }
+ if (reducecount > 0)
+ {
+ froms[nstates+i] = r = NEW2(reducecount, short);
+ tos[nstates+i] = s = NEW2(reducecount, short);
+ min = MAXSHORT;
+ max = 0;
+ for (j = 0; j < ntokens; ++j)
+ {
+ if (actionrow[ntokens+j])
+ {
+ if (min > symbol_value[j])
+ min = symbol_value[j];
+ if (max < symbol_value[j])
+ max = symbol_value[j];
+ *r++ = symbol_value[j];
+ *s++ = actionrow[ntokens+j] - 2;
+ }
+ }
+ width[nstates+i] = max - min + 1;
+ }
+ }
+ }
+ FREE(actionrow);
+}
+
+goto_actions()
+{
+ register int i, j, k;
+
+ state_count = NEW2(nstates, short);
+
+ k = default_goto(start_symbol + 1);
+ fprintf(output_file, "let yydgoto = \"");
+ output_short(k);
+
+ save_column(start_symbol + 1, k);
+
+ j = 8;
+ for (i = start_symbol + 2; i < nsyms; i++)
+ {
+ if (j >= 8)
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+ else
+ ++j;
+
+ k = default_goto(i);
+ output_short(k);
+ save_column(i, k);
+ }
+
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+ FREE(state_count);
+}
+
+int
+default_goto(symbol)
+int symbol;
+{
+ register int i;
+ register int m;
+ register int n;
+ register int default_state;
+ register int max;
+
+ m = goto_map[symbol];
+ n = goto_map[symbol + 1];
+
+ if (m == n) return (0);
+
+ for (i = 0; i < nstates; i++)
+ state_count[i] = 0;
+
+ for (i = m; i < n; i++)
+ state_count[to_state[i]]++;
+
+ max = 0;
+ default_state = 0;
+ for (i = 0; i < nstates; i++)
+ {
+ if (state_count[i] > max)
+ {
+ max = state_count[i];
+ default_state = i;
+ }
+ }
+
+ return (default_state);
+}
+
+
+
+save_column(symbol, default_state)
+int symbol;
+int default_state;
+{
+ register int i;
+ register int m;
+ register int n;
+ register short *sp;
+ register short *sp1;
+ register short *sp2;
+ register int count;
+ register int symno;
+
+ m = goto_map[symbol];
+ n = goto_map[symbol + 1];
+
+ count = 0;
+ for (i = m; i < n; i++)
+ {
+ if (to_state[i] != default_state)
+ ++count;
+ }
+ if (count == 0) return;
+
+ symno = symbol_value[symbol] + 2*nstates;
+
+ froms[symno] = sp1 = sp = NEW2(count, short);
+ tos[symno] = sp2 = NEW2(count, short);
+
+ for (i = m; i < n; i++)
+ {
+ if (to_state[i] != default_state)
+ {
+ *sp1++ = from_state[i];
+ *sp2++ = to_state[i];
+ }
+ }
+
+ tally[symno] = count;
+ width[symno] = sp1[-1] - sp[0] + 1;
+}
+
+sort_actions()
+{
+ register int i;
+ register int j;
+ register int k;
+ register int t;
+ register int w;
+
+ order = NEW2(nvectors, short);
+ nentries = 0;
+
+ for (i = 0; i < nvectors; i++)
+ {
+ if (tally[i] > 0)
+ {
+ t = tally[i];
+ w = width[i];
+ j = nentries - 1;
+
+ while (j >= 0 && (width[order[j]] < w))
+ j--;
+
+ while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
+ j--;
+
+ for (k = nentries - 1; k > j; k--)
+ order[k + 1] = order[k];
+
+ order[j + 1] = i;
+ nentries++;
+ }
+ }
+}
+
+
+pack_table()
+{
+ register int i;
+ register int place;
+ register int state;
+
+ base = NEW2(nvectors, short);
+ pos = NEW2(nentries, short);
+
+ maxtable = 1000;
+ table = NEW2(maxtable, short);
+ check = NEW2(maxtable, short);
+
+ lowzero = 0;
+ high = 0;
+
+ for (i = 0; i < maxtable; i++)
+ check[i] = -1;
+
+ for (i = 0; i < nentries; i++)
+ {
+ state = matching_vector(i);
+
+ if (state < 0)
+ place = pack_vector(i);
+ else
+ place = base[state];
+
+ pos[i] = place;
+ base[order[i]] = place;
+ }
+
+ for (i = 0; i < nvectors; i++)
+ {
+ if (froms[i])
+ FREE(froms[i]);
+ if (tos[i])
+ FREE(tos[i]);
+ }
+
+ FREE(froms);
+ FREE(tos);
+ FREE(pos);
+}
+
+
+/* The function matching_vector determines if the vector specified by */
+/* the input parameter matches a previously considered vector. The */
+/* test at the start of the function checks if the vector represents */
+/* a row of shifts over terminal symbols or a row of reductions, or a */
+/* column of shifts over a nonterminal symbol. Berkeley Yacc does not */
+/* check if a column of shifts over a nonterminal symbols matches a */
+/* previously considered vector. Because of the nature of LR parsing */
+/* tables, no two columns can match. Therefore, the only possible */
+/* match would be between a row and a column. Such matches are */
+/* unlikely. Therefore, to save time, no attempt is made to see if a */
+/* column matches a previously considered vector. */
+/* */
+/* Matching_vector is poorly designed. The test could easily be made */
+/* faster. Also, it depends on the vectors being in a specific */
+/* order. */
+
+int
+matching_vector(vector)
+int vector;
+{
+ register int i;
+ register int j;
+ register int k;
+ register int t;
+ register int w;
+ register int match;
+ register int prev;
+
+ i = order[vector];
+ if (i >= 2*nstates)
+ return (-1);
+
+ t = tally[i];
+ w = width[i];
+
+ for (prev = vector - 1; prev >= 0; prev--)
+ {
+ j = order[prev];
+ if (width[j] != w || tally[j] != t)
+ return (-1);
+
+ match = 1;
+ for (k = 0; match && k < t; k++)
+ {
+ if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
+ match = 0;
+ }
+
+ if (match)
+ return (j);
+ }
+
+ return (-1);
+}
+
+
+
+int
+pack_vector(vector)
+int vector;
+{
+ register int i, j, k, l;
+ register int t;
+ register int loc;
+ register int ok;
+ register short *from;
+ register short *to;
+ int newmax;
+
+ i = order[vector];
+ t = tally[i];
+ assert(t);
+
+ from = froms[i];
+ to = tos[i];
+
+ j = lowzero - from[0];
+ for (k = 1; k < t; ++k)
+ if (lowzero - from[k] > j)
+ j = lowzero - from[k];
+ for (;; ++j)
+ {
+ if (j == 0)
+ continue;
+ ok = 1;
+ for (k = 0; ok && k < t; k++)
+ {
+ loc = j + from[k];
+ if (loc >= maxtable)
+ {
+ if (loc >= MAXTABLE)
+ fatal("maximum table size exceeded");
+
+ newmax = maxtable;
+ do { newmax += 200; } while (newmax <= loc);
+ table = (short *) REALLOC(table, newmax*sizeof(short));
+ if (table == 0) no_space();
+ check = (short *) REALLOC(check, newmax*sizeof(short));
+ if (check == 0) no_space();
+ for (l = maxtable; l < newmax; ++l)
+ {
+ table[l] = 0;
+ check[l] = -1;
+ }
+ maxtable = newmax;
+ }
+
+ if (check[loc] != -1)
+ ok = 0;
+ }
+ for (k = 0; ok && k < vector; k++)
+ {
+ if (pos[k] == j)
+ ok = 0;
+ }
+ if (ok)
+ {
+ for (k = 0; k < t; k++)
+ {
+ loc = j + from[k];
+ table[loc] = to[k];
+ check[loc] = from[k];
+ if (loc > high) high = loc;
+ }
+
+ while (check[lowzero] != -1)
+ ++lowzero;
+
+ return (j);
+ }
+ }
+}
+
+
+
+output_base()
+{
+ register int i, j;
+
+ fprintf(output_file, "let yysindex = \"");
+ output_short(base[0]);
+
+ j = 8;
+ for (i = 1; i < nstates; i++)
+ {
+ if (j >= 8)
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+ else
+ ++j;
+
+ output_short(base[i]);
+ }
+
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+
+ fprintf(output_file, "let yyrindex = \"");
+ output_short(base[nstates]);
+
+ j = 8;
+ for (i = nstates + 1; i < 2*nstates; i++)
+ {
+ if (j >= 8)
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+ else
+ ++j;
+
+ output_short(base[i]);
+ }
+
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+
+ fprintf(output_file, "let yygindex = \"");
+ output_short(base[2*nstates]);
+
+ j = 8;
+ for (i = 2*nstates + 1; i < nvectors - 1; i++)
+ {
+ if (j >= 8)
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+ else
+ ++j;
+
+ output_short(base[i]);
+ }
+
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+ FREE(base);
+}
+
+
+
+output_table()
+{
+ register int i;
+ register int j;
+
+ ++outline;
+ fprintf(code_file, "let yytablesize = %d\n", high);
+ fprintf(output_file, "let yytable = \"");
+ output_short(table[0]);
+
+ j = 8;
+ for (i = 1; i <= high; i++)
+ {
+ if (j >= 8)
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+ else
+ ++j;
+
+ output_short(table[i]);
+ }
+
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+ FREE(table);
+}
+
+
+
+output_check()
+{
+ register int i;
+ register int j;
+
+ fprintf(output_file, "let yycheck = \"");
+ output_short(check[0]);
+
+ j = 8;
+ for (i = 1; i <= high; i++)
+ {
+ if (j >= 8)
+ {
+ if (!rflag) ++outline;
+ fprintf(output_file, "\\\n");
+ j = 1;
+ }
+ else
+ ++j;
+
+ output_short(check[i]);
+ }
+
+ if (!rflag) outline += 2;
+ fprintf(output_file, "\"\n\n");
+ FREE(check);
+}
+
+
+output_transl()
+{
+ int i;
+
+ fprintf(code_file, "let yytransl = [|\n");
+ for (i = 0; i < ntokens; i++) {
+ if (symbol_true_token[i]) {
+ fprintf(code_file, " %3d (* %s *);\n", symbol_value[i], symbol_name[i]);
+ }
+ }
+ fprintf(code_file, " 0|]\n\n");
+}
+
+output_stored_text()
+{
+ register int c;
+ register FILE *in, *out;
+
+ fclose(text_file);
+ text_file = fopen(text_file_name, "r");
+ if (text_file == NULL)
+ open_error(text_file_name);
+ in = text_file;
+ if ((c = getc(in)) == EOF)
+ return;
+ out = code_file;
+ if (c == '\n')
+ ++outline;
+ putc(c, out);
+ while ((c = getc(in)) != EOF)
+ {
+ if (c == '\n')
+ ++outline;
+ putc(c, out);
+ }
+ if (!lflag)
+ fprintf(out, line_format, ++outline + 1, code_file_name);
+}
+
+
+output_debug()
+{
+}
+
+output_trailing_text()
+{
+ register int c, last;
+ register FILE *in, *out;
+
+ if (line == 0)
+ return;
+
+ in = input_file;
+ out = code_file;
+ c = *cptr;
+ if (c == '\n')
+ {
+ ++lineno;
+ if ((c = getc(in)) == EOF)
+ return;
+ if (!lflag)
+ {
+ ++outline;
+ fprintf(out, line_format, lineno, input_file_name);
+ }
+ if (c == '\n')
+ ++outline;
+ putc(c, out);
+ last = c;
+ }
+ else
+ {
+ if (!lflag)
+ {
+ ++outline;
+ fprintf(out, line_format, lineno, input_file_name);
+ }
+ do { putc(c, out); } while ((c = *++cptr) != '\n');
+ ++outline;
+ putc('\n', out);
+ last = '\n';
+ }
+
+ while ((c = getc(in)) != EOF)
+ {
+ if (c == '\n')
+ ++outline;
+ putc(c, out);
+ last = c;
+ }
+
+ if (last != '\n')
+ {
+ ++outline;
+ putc('\n', out);
+ }
+ if (!lflag)
+ fprintf(out, line_format, ++outline + 1, code_file_name);
+}
+
+
+copy_file(file, file_name)
+ FILE ** file;
+ char * file_name;
+{
+ register int c, last;
+ register FILE *out;
+
+ fclose(*file);
+ *file = fopen(file_name, "r");
+ if (*file == NULL)
+ open_error(file_name);
+
+ if ((c = getc(*file)) == EOF)
+ return;
+
+ out = code_file;
+ last = c;
+ if (c == '\n')
+ ++outline;
+ putc(c, out);
+ while ((c = getc(*file)) != EOF)
+ {
+ if (c == '\n')
+ ++outline;
+ putc(c, out);
+ last = c;
+ }
+
+ if (last != '\n')
+ {
+ ++outline;
+ putc('\n', out);
+ }
+
+}
+
+output_semantic_actions()
+{
+ copy_file (&action_file, action_file_name);
+}
+
+output_entries()
+{
+ copy_file (&entry_file, entry_file_name);
+}
+
+free_itemsets()
+{
+ register core *cp, *next;
+
+ FREE(state_table);
+ for (cp = first_state; cp; cp = next)
+ {
+ next = cp->next;
+ FREE(cp);
+ }
+}
+
+
+free_shifts()
+{
+ register shifts *sp, *next;
+
+ FREE(shift_table);
+ for (sp = first_shift; sp; sp = next)
+ {
+ next = sp->next;
+ FREE(sp);
+ }
+}
+
+
+
+free_reductions()
+{
+ register reductions *rp, *next;
+
+ FREE(reduction_table);
+ for (rp = first_reduction; rp; rp = next)
+ {
+ next = rp->next;
+ FREE(rp);
+ }
+}