]> git.saurik.com Git - bison.git/blobdiff - src/lalr.c
Fix the previous test.
[bison.git] / src / lalr.c
index 7e8aff70146dc51d227e3c116d4d5eaa6d6ae839..c16c6f52dafaea945a222c3f6103f32c6c312cf2 100644 (file)
@@ -1,5 +1,5 @@
 /* Compute look-ahead criteria for bison,
 /* Compute look-ahead criteria for bison,
-   Copyright 1984, 1986, 1989, 2000 Free Software Foundation, Inc.
+   Copyright 1984, 1986, 1989, 2000, 2001  Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
    tokens they accept.  */
 
 #include "system.h"
    tokens they accept.  */
 
 #include "system.h"
+#include "reader.h"
 #include "types.h"
 #include "LR0.h"
 #include "types.h"
 #include "LR0.h"
-#include "xalloc.h"
+#include "symtab.h"
 #include "gram.h"
 #include "complain.h"
 #include "lalr.h"
 #include "nullable.h"
 #include "derives.h"
 #include "gram.h"
 #include "complain.h"
 #include "lalr.h"
 #include "nullable.h"
 #include "derives.h"
+#include "getargs.h"
+
+/* All the decorated states, indexed by the state number.  */
+state_t **states = NULL;
 
 int tokensetsize;
 
 int tokensetsize;
-short *lookaheads;
 short *LAruleno;
 unsigned *LA;
 short *LAruleno;
 unsigned *LA;
-short *accessing_symbol;
-char *consistent;
-core **state_table;
-shifts **shift_table;
-reductions **reduction_table;
+size_t nLA;
+
+static int ngotos;
 short *goto_map;
 short *from_state;
 short *to_state;
 
 short *goto_map;
 short *from_state;
 short *to_state;
 
-extern void berror PARAMS ((const char *));
+/* And for the famous F variable, which name is so descriptive that a
+   comment is hardly needed.  <grin>.  */
+static unsigned *F = NULL;
+#define F(Rule)  (F + (Rule) * tokensetsize)
 
 
-static int infinity;
-static int maxrhs;
-static int ngotos;
-static unsigned *F;
 static short **includes;
 static shorts **lookback;
 static short **includes;
 static shorts **lookback;
+
+
+/*---------------------------------------------------------------.
+| digraph & traverse.                                            |
+|                                                                |
+| The following variables are used as common storage between the |
+| two.                                                           |
+`---------------------------------------------------------------*/
+
 static short **R;
 static short *INDEX;
 static short *VERTICES;
 static int top;
 static short **R;
 static short *INDEX;
 static short *VERTICES;
 static int top;
-
+static int infinity;
 
 static void
 traverse (int i)
 {
 
 static void
 traverse (int i)
 {
-  unsigned *fp1;
-  unsigned *fp2;
-  unsigned *fp3;
   int j;
   int j;
-  short *rp;
-
+  size_t k;
   int height;
   int height;
-  unsigned *base;
+  size_t size = F (i + 1) - F(i);
 
   VERTICES[++top] = i;
   INDEX[i] = height = top;
 
 
   VERTICES[++top] = i;
   INDEX[i] = height = top;
 
-  base = F + i * tokensetsize;
-  fp3 = base + tokensetsize;
-
-  rp = R[i];
-  if (rp)
-    {
-      while ((j = *rp++) >= 0)
-       {
-         if (INDEX[j] == 0)
-           traverse (j);
-
-         if (INDEX[i] > INDEX[j])
-           INDEX[i] = INDEX[j];
+  if (R[i])
+    for (j = 0; R[i][j] >= 0; ++j)
+      {
+       if (INDEX[R[i][j]] == 0)
+         traverse (R[i][j]);
 
 
-         fp1 = base;
-         fp2 = F + j * tokensetsize;
+       if (INDEX[i] > INDEX[R[i][j]])
+         INDEX[i] = INDEX[R[i][j]];
 
 
-         while (fp1 < fp3)
-           *fp1++ |= *fp2++;
-       }
-    }
+       for (k = 0; k < size; ++k)
+         F (i)[k] |= F (R[i][j])[k];
+      }
 
   if (INDEX[i] == height)
 
   if (INDEX[i] == height)
-    {
-      for (;;)
-       {
-         j = VERTICES[top--];
-         INDEX[j] = infinity;
-
-         if (i == j)
-           break;
+    for (;;)
+      {
+       j = VERTICES[top--];
+       INDEX[j] = infinity;
 
 
-         fp1 = base;
-         fp2 = F + j * tokensetsize;
+       if (i == j)
+         break;
 
 
-         while (fp1 < fp3)
-           *fp2++ = *fp1++;
-       }
-    }
+       for (k = 0; k < size; ++k)
+         F (j)[k] = F (i)[k];
+      }
 }
 
 
 }
 
 
@@ -133,219 +125,86 @@ digraph (short **relation)
     INDEX[i] = 0;
 
   for (i = 0; i < ngotos; i++)
     INDEX[i] = 0;
 
   for (i = 0; i < ngotos; i++)
-    {
-      if (INDEX[i] == 0 && R[i])
-       traverse (i);
-    }
+    if (INDEX[i] == 0 && R[i])
+      traverse (i);
 
   XFREE (INDEX);
   XFREE (VERTICES);
 }
 
 
   XFREE (INDEX);
   XFREE (VERTICES);
 }
 
-static void
-set_state_table (void)
-{
-  core *sp;
-
-  state_table = XCALLOC (core *, nstates);
-
-  for (sp = first_state; sp; sp = sp->next)
-    state_table[sp->number] = sp;
-}
-
-
-static void
-set_accessing_symbol (void)
-{
-  core *sp;
-
-  accessing_symbol = XCALLOC (short, nstates);
-
-  for (sp = first_state; sp; sp = sp->next)
-    accessing_symbol[sp->number] = sp->accessing_symbol;
-}
-
-
-static void
-set_shift_table (void)
-{
-  shifts *sp;
-
-  shift_table = XCALLOC (shifts *, nstates);
-
-  for (sp = first_shift; sp; sp = sp->next)
-    shift_table[sp->number] = sp;
-}
-
-
-static void
-set_reduction_table (void)
-{
-  reductions *rp;
-
-  reduction_table = XCALLOC (reductions *, nstates);
-
-  for (rp = first_reduction; rp; rp = rp->next)
-    reduction_table[rp->number] = rp;
-}
-
-
-static void
-set_maxrhs (void)
-{
-  short *itemp;
-  int length;
-  int max;
-
-  length = 0;
-  max = 0;
-  for (itemp = ritem; *itemp; itemp++)
-    {
-      if (*itemp > 0)
-       {
-         length++;
-       }
-      else
-       {
-         if (length > max)
-           max = length;
-         length = 0;
-       }
-    }
-
-  maxrhs = max;
-}
-
 
 static void
 initialize_LA (void)
 {
   int i;
   int j;
 
 static void
 initialize_LA (void)
 {
   int i;
   int j;
-  int count;
-  reductions *rp;
-  shifts *sp;
   short *np;
 
   short *np;
 
-  consistent = XCALLOC (char, nstates);
-  lookaheads = XCALLOC (short, nstates + 1);
-
-  count = 0;
-  for (i = 0; i < nstates; i++)
-    {
-      int k;
+  /* Avoid having to special case 0.  */
+  if (!nLA)
+    nLA = 1;
 
 
-      lookaheads[i] = count;
-
-      rp = reduction_table[i];
-      sp = shift_table[i];
-      if (rp && (rp->nreds > 1
-                || (sp && !ISVAR (accessing_symbol[sp->shifts[0]]))))
-       count += rp->nreds;
-      else
-       consistent[i] = 1;
-
-      if (sp)
-       for (k = 0; k < sp->nshifts; k++)
-         {
-           if (accessing_symbol[sp->shifts[k]] == error_token_number)
-             {
-               consistent[i] = 0;
-               break;
-             }
-         }
-    }
-
-  lookaheads[nstates] = count;
-
-  if (count == 0)
-    {
-      LA = XCALLOC (unsigned, 1 * tokensetsize);
-      LAruleno = XCALLOC (short, 1);
-      lookback = XCALLOC (shorts *, 1);
-    }
-  else
-    {
-      LA = XCALLOC (unsigned, count * tokensetsize);
-      LAruleno = XCALLOC (short, count);
-      lookback = XCALLOC (shorts *, count);
-    }
+  LA = XCALLOC (unsigned, nLA * tokensetsize);
+  LAruleno = XCALLOC (short, nLA);
+  lookback = XCALLOC (shorts *, nLA);
 
   np = LAruleno;
   for (i = 0; i < nstates; i++)
 
   np = LAruleno;
   for (i = 0; i < nstates; i++)
-    {
-      if (!consistent[i])
-       {
-         if ((rp = reduction_table[i]))
-           for (j = 0; j < rp->nreds; j++)
-             *np++ = rp->rules[j];
-       }
-    }
+    if (!states[i]->consistent)
+      for (j = 0; j < states[i]->reductions->nreds; j++)
+       *np++ = states[i]->reductions->rules[j];
 }
 
 
 static void
 set_goto_map (void)
 {
 }
 
 
 static void
 set_goto_map (void)
 {
-  shifts *sp;
-  int i;
-  int symbol;
-  int k;
+  int state, i;
   short *temp_map;
   short *temp_map;
-  int state2;
-  int state1;
 
   goto_map = XCALLOC (short, nvars + 1) - ntokens;
   temp_map = XCALLOC (short, nvars + 1) - ntokens;
 
   ngotos = 0;
 
   goto_map = XCALLOC (short, nvars + 1) - ntokens;
   temp_map = XCALLOC (short, nvars + 1) - ntokens;
 
   ngotos = 0;
-  for (sp = first_shift; sp; sp = sp->next)
+  for (state = 0; state < nstates; ++state)
     {
     {
-      for (i = sp->nshifts - 1; i >= 0; i--)
+      shifts *sp = states[state]->shifts;
+      for (i = sp->nshifts - 1; i >= 0 && SHIFT_IS_GOTO (sp, i); --i)
        {
        {
-         symbol = accessing_symbol[sp->shifts[i]];
-
-         if (ISTOKEN (symbol))
-           break;
-
          if (ngotos == MAXSHORT)
            fatal (_("too many gotos (max %d)"), MAXSHORT);
 
          ngotos++;
          if (ngotos == MAXSHORT)
            fatal (_("too many gotos (max %d)"), MAXSHORT);
 
          ngotos++;
-         goto_map[symbol]++;
+         goto_map[SHIFT_SYMBOL (sp, i)]++;
        }
     }
 
        }
     }
 
-  k = 0;
-  for (i = ntokens; i < nsyms; i++)
-    {
-      temp_map[i] = k;
-      k += goto_map[i];
-    }
+  {
+    int k = 0;
+    for (i = ntokens; i < nsyms; i++)
+      {
+       temp_map[i] = k;
+       k += goto_map[i];
+      }
 
 
-  for (i = ntokens; i < nsyms; i++)
-    goto_map[i] = temp_map[i];
+    for (i = ntokens; i < nsyms; i++)
+      goto_map[i] = temp_map[i];
 
 
-  goto_map[nsyms] = ngotos;
-  temp_map[nsyms] = ngotos;
+    goto_map[nsyms] = ngotos;
+    temp_map[nsyms] = ngotos;
+  }
 
   from_state = XCALLOC (short, ngotos);
   to_state = XCALLOC (short, ngotos);
 
 
   from_state = XCALLOC (short, ngotos);
   to_state = XCALLOC (short, ngotos);
 
-  for (sp = first_shift; sp; sp = sp->next)
+  for (state = 0; state < nstates; ++state)
     {
     {
-      state1 = sp->number;
-      for (i = sp->nshifts - 1; i >= 0; i--)
+      shifts *sp = states[state]->shifts;
+      for (i = sp->nshifts - 1; i >= 0 && SHIFT_IS_GOTO (sp, i); --i)
        {
        {
-         state2 = sp->shifts[i];
-         symbol = accessing_symbol[state2];
-
-         if (ISTOKEN (symbol))
-           break;
-
-         k = temp_map[symbol]++;
-         from_state[k] = state1;
-         to_state[k] = state2;
+         int k = temp_map[SHIFT_SYMBOL (sp, i)]++;
+         from_state[k] = state;
+         to_state[k] = sp->shifts[i];
        }
     }
 
        }
     }
 
@@ -390,73 +249,43 @@ map_goto (int state, int symbol)
 static void
 initialize_F (void)
 {
 static void
 initialize_F (void)
 {
-  int i;
-  int j;
-  int k;
-  shifts *sp;
-  short *edge;
-  unsigned *rowp;
-  short *rp;
-  short **reads;
-  int nedges;
-  int stateno;
-  int symbol;
-  int nwords;
-
-  nwords = ngotos * tokensetsize;
-  F = XCALLOC (unsigned, nwords);
-
-  reads = XCALLOC (short *, ngotos);
-  edge = XCALLOC (short, ngotos + 1);
-  nedges = 0;
-
-  rowp = F;
-  for (i = 0; i < ngotos; i++)
-    {
-      stateno = to_state[i];
-      sp = shift_table[stateno];
-
-      if (sp)
-       {
-         k = sp->nshifts;
+  short **reads = XCALLOC (short *, ngotos);
+  short *edge = XCALLOC (short, ngotos + 1);
+  int nedges = 0;
 
 
-         for (j = 0; j < k; j++)
-           {
-             symbol = accessing_symbol[sp->shifts[j]];
-             if (ISVAR (symbol))
-               break;
-             SETBIT (rowp, symbol);
-           }
+  int i;
 
 
-         for (; j < k; j++)
-           {
-             symbol = accessing_symbol[sp->shifts[j]];
-             if (nullable[symbol])
-               edge[nedges++] = map_goto (stateno, symbol);
-           }
+  F = XCALLOC (unsigned, ngotos * tokensetsize);
 
 
-         if (nedges)
-           {
-             reads[i] = rp = XCALLOC (short, nedges + 1);
+  for (i = 0; i < ngotos; i++)
+    {
+      int stateno = to_state[i];
+      shifts *sp = states[stateno]->shifts;
 
 
-             for (j = 0; j < nedges; j++)
-               rp[j] = edge[j];
+      int j;
+      for (j = 0; j < sp->nshifts && SHIFT_IS_SHIFT (sp, j); j++)
+       SETBIT (F (i), SHIFT_SYMBOL (sp, j));
 
 
-             rp[nedges] = -1;
-             nedges = 0;
-           }
+      for (; j < sp->nshifts; j++)
+       {
+         int symbol = SHIFT_SYMBOL (sp, j);
+         if (nullable[symbol])
+           edge[nedges++] = map_goto (stateno, symbol);
        }
 
        }
 
-      rowp += tokensetsize;
+      if (nedges)
+       {
+         reads[i] = XCALLOC (short, nedges + 1);
+         shortcpy (reads[i], edge, nedges);
+         reads[i][nedges] = -1;
+         nedges = 0;
+       }
     }
 
   digraph (reads);
 
   for (i = 0; i < ngotos; i++)
     }
 
   digraph (reads);
 
   for (i = 0; i < ngotos; i++)
-    {
-      if (reads[i])
-       XFREE (reads[i]);
-    }
+    XFREE (reads[i]);
 
   XFREE (reads);
   XFREE (edge);
 
   XFREE (reads);
   XFREE (edge);
@@ -464,84 +293,106 @@ initialize_F (void)
 
 
 static void
 
 
 static void
-add_lookback_edge (int stateno, int ruleno, int gotono)
+add_lookback_edge (state_t *state, int ruleno, int gotono)
 {
   int i;
 {
   int i;
-  int k;
-  int found;
   shorts *sp;
 
   shorts *sp;
 
-  i = lookaheads[stateno];
-  k = lookaheads[stateno + 1];
-  found = 0;
-  while (!found && i < k)
-    {
-      if (LAruleno[i] == ruleno)
-       found = 1;
-      else
-       i++;
-    }
+  for (i = 0; i < state->nlookaheads; ++i)
+    if (LAruleno[state->lookaheadsp + i] == ruleno)
+      break;
 
 
-  assert (found);
+  assert (LAruleno[state->lookaheadsp + i] == ruleno);
 
   sp = XCALLOC (shorts, 1);
 
   sp = XCALLOC (shorts, 1);
-  sp->next = lookback[i];
+  sp->next = lookback[state->lookaheadsp + i];
   sp->value = gotono;
   sp->value = gotono;
-  lookback[i] = sp;
+  lookback[state->lookaheadsp + i] = sp;
 }
 
 
 }
 
 
-static short **
-transpose (short **R_arg, int n)
+static void
+matrix_print (FILE *out, short **matrix, int n)
 {
 {
-  short **new_R;
-  short **temp_R;
-  short *nedges;
-  short *sp;
-  int i;
-  int k;
+  int i, j;
+
+  for (i = 0; i < n; ++i)
+    {
+      fprintf (out, "%3d: ", i);
+      if (matrix[i])
+       for (j = 0; matrix[i][j] != -1; ++j)
+         fprintf (out, "%3d ", matrix[i][j]);
+      fputc ('\n', out);
+    }
+  fputc ('\n', out);
+}
 
 
-  nedges = XCALLOC (short, n);
+/*-------------------------------------------------------------------.
+| Return the transpose of R_ARG, of size N.  Destroy R_ARG, as it is |
+| replaced with the result.                                          |
+|                                                                    |
+| R_ARG[I] is NULL or a -1 terminated list of numbers.               |
+|                                                                    |
+| RESULT[NUM] is NULL or the -1 terminated list of the I such as NUM |
+| is in R_ARG[I].                                                    |
+`-------------------------------------------------------------------*/
 
 
-  for (i = 0; i < n; i++)
+static short **
+transpose (short **R_arg, int n)
+{
+  /* The result. */
+  short **new_R = XCALLOC (short *, n);
+  /* END_R[I] -- next entry of NEW_R[I]. */
+  short **end_R = XCALLOC (short *, n);
+  /* NEDGES[I] -- total size of NEW_R[I]. */
+  short *nedges = XCALLOC (short, n);
+  int i, j;
+
+  if (trace_flag)
     {
     {
-      sp = R_arg[i];
-      if (sp)
-       {
-         while (*sp >= 0)
-           nedges[*sp++]++;
-       }
+      fputs ("transpose: input\n", stderr);
+      matrix_print (stderr, R_arg, n);
     }
 
     }
 
-  new_R = XCALLOC (short *, n);
-  temp_R = XCALLOC (short *, n);
+  /* Count. */
+  for (i = 0; i < n; i++)
+    if (R_arg[i])
+      for (j = 0; R_arg[i][j] >= 0; ++j)
+       ++nedges[R_arg[i][j]];
 
 
+  /* Allocate. */
   for (i = 0; i < n; i++)
   for (i = 0; i < n; i++)
-    {
-      k = nedges[i];
-      if (k > 0)
+    if (nedges[i] > 0)
+      {
+       short *sp = XCALLOC (short, nedges[i] + 1);
+       sp[nedges[i]] = -1;
+       new_R[i] = sp;
+       end_R[i] = sp;
+      }
+
+  /* Store. */
+  for (i = 0; i < n; i++)
+    if (R_arg[i])
+      for (j = 0; R_arg[i][j] >= 0; ++j)
        {
        {
-         sp = XCALLOC (short, k + 1);
-         new_R[i] = sp;
-         temp_R[i] = sp;
-         sp[k] = -1;
+         *end_R[R_arg[i][j]] = i;
+         ++end_R[R_arg[i][j]];
        }
        }
-    }
 
 
-  XFREE (nedges);
+  free (nedges);
+  free (end_R);
 
 
+  /* Free the input: it is replaced with the result. */
   for (i = 0; i < n; i++)
   for (i = 0; i < n; i++)
+    XFREE (R_arg[i]);
+  free (R_arg);
+
+  if (trace_flag)
     {
     {
-      sp = R_arg[i];
-      if (sp)
-       {
-         while (*sp >= 0)
-           *temp_R[*sp++]++ = i;
-       }
+      fputs ("transpose: output\n", stderr);
+      matrix_print (stderr, new_R, n);
     }
 
     }
 
-  XFREE (temp_R);
-
   return new_R;
 }
 
   return new_R;
 }
 
@@ -549,58 +400,42 @@ transpose (short **R_arg, int n)
 static void
 build_relations (void)
 {
 static void
 build_relations (void)
 {
+  short *edge = XCALLOC (short, ngotos + 1);
+  short *states1 = XCALLOC (short, ritem_longest_rhs () + 1);
   int i;
   int i;
-  int j;
-  int k;
-  short *rulep;
-  short *rp;
-  shifts *sp;
-  int length;
-  int nedges;
-  int done;
-  int state1;
-  int stateno;
-  int symbol1;
-  int symbol2;
-  short *shortp;
-  short *edge;
-  short *states;
-  short **new_includes;
 
   includes = XCALLOC (short *, ngotos);
 
   includes = XCALLOC (short *, ngotos);
-  edge = XCALLOC (short, ngotos + 1);
-  states = XCALLOC (short, maxrhs + 1);
 
   for (i = 0; i < ngotos; i++)
     {
 
   for (i = 0; i < ngotos; i++)
     {
-      nedges = 0;
-      state1 = from_state[i];
-      symbol1 = accessing_symbol[to_state[i]];
+      int nedges = 0;
+      int symbol1 = states[to_state[i]]->accessing_symbol;
+      short *rulep;
 
       for (rulep = derives[symbol1]; *rulep > 0; rulep++)
        {
 
       for (rulep = derives[symbol1]; *rulep > 0; rulep++)
        {
-         length = 1;
-         states[0] = state1;
-         stateno = state1;
+         int done;
+         int length = 1;
+         short *rp;
+         state_t *state = states[from_state[i]];
+         states1[0] = state->number;
 
 
-         for (rp = ritem + rrhs[*rulep]; *rp > 0; rp++)
+         for (rp = &ritem[rules[*rulep].rhs]; *rp >= 0; rp++)
            {
            {
-             symbol2 = *rp;
-             sp = shift_table[stateno];
-             k = sp->nshifts;
-
-             for (j = 0; j < k; j++)
+             shifts *sp = state->shifts;
+             int j;
+             for (j = 0; j < sp->nshifts; j++)
                {
                {
-                 stateno = sp->shifts[j];
-                 if (accessing_symbol[stateno] == symbol2)
+                 state = states[sp->shifts[j]];
+                 if (state->accessing_symbol == *rp)
                    break;
                }
 
                    break;
                }
 
-             states[length++] = stateno;
+             states1[length++] = state->number;
            }
 
            }
 
-         if (!consistent[stateno])
-           add_lookback_edge (stateno, *rulep, i);
+         if (!state->consistent)
+           add_lookback_edge (state, *rulep, i);
 
          length--;
          done = 0;
 
          length--;
          done = 0;
@@ -611,8 +446,7 @@ build_relations (void)
              /* JF added rp>=ritem &&   I hope to god its right! */
              if (rp >= ritem && ISVAR (*rp))
                {
              /* JF added rp>=ritem &&   I hope to god its right! */
              if (rp >= ritem && ISVAR (*rp))
                {
-                 stateno = states[--length];
-                 edge[nedges++] = map_goto (stateno, *rp);
+                 edge[nedges++] = map_goto (states1[--length], *rp);
                  if (nullable[*rp])
                    done = 0;
                }
                  if (nullable[*rp])
                    done = 0;
                }
@@ -621,25 +455,18 @@ build_relations (void)
 
       if (nedges)
        {
 
       if (nedges)
        {
-         includes[i] = shortp = XCALLOC (short, nedges + 1);
+         int j;
+         includes[i] = XCALLOC (short, nedges + 1);
          for (j = 0; j < nedges; j++)
          for (j = 0; j < nedges; j++)
-           shortp[j] = edge[j];
-         shortp[nedges] = -1;
+           includes[i][j] = edge[j];
+         includes[i][nedges] = -1;
        }
     }
 
        }
     }
 
-  new_includes = transpose (includes, ngotos);
-
-  for (i = 0; i < ngotos; i++)
-    if (includes[i])
-      XFREE (includes[i]);
-
-  XFREE (includes);
-
-  includes = new_includes;
-
   XFREE (edge);
   XFREE (edge);
-  XFREE (states);
+  XFREE (states1);
+
+  includes = transpose (includes, ngotos);
 }
 
 
 }
 
 
@@ -652,10 +479,7 @@ compute_FOLLOWS (void)
   digraph (includes);
 
   for (i = 0; i < ngotos; i++)
   digraph (includes);
 
   for (i = 0; i < ngotos; i++)
-    {
-      if (includes[i])
-       XFREE (includes[i]);
-    }
+    XFREE (includes[i]);
 
   XFREE (includes);
 }
 
   XFREE (includes);
 }
@@ -664,60 +488,104 @@ compute_FOLLOWS (void)
 static void
 compute_lookaheads (void)
 {
 static void
 compute_lookaheads (void)
 {
-  int i;
-  int n;
-  unsigned *fp1;
-  unsigned *fp2;
-  unsigned *fp3;
+  size_t i;
   shorts *sp;
   shorts *sp;
-  unsigned *rowp;
-  shorts *sptmp;               /* JF */
 
 
-  rowp = LA;
-  n = lookaheads[nstates];
-  for (i = 0; i < n; i++)
+  for (i = 0; i < nLA; i++)
+    for (sp = lookback[i]; sp; sp = sp->next)
+      {
+       int size = LA (i + 1) - LA (i);
+       int j;
+       for (j = 0; j < size; ++j)
+         LA (i)[j] |= F (sp->value)[j];
+      }
+
+  /* Free LOOKBACK. */
+  for (i = 0; i < nLA; i++)
+    LIST_FREE (shorts, lookback[i]);
+
+  XFREE (lookback);
+  XFREE (F);
+}
+
+
+/*--------------------------------------.
+| Initializing the lookaheads members.  |
+`--------------------------------------*/
+
+static void
+initialize_lookaheads (void)
+{
+  int i;
+  nLA = 0;
+  for (i = 0; i < nstates; i++)
     {
     {
-      fp3 = rowp + tokensetsize;
-      for (sp = lookback[i]; sp; sp = sp->next)
-       {
-         fp1 = rowp;
-         fp2 = F + tokensetsize * sp->value;
-         while (fp1 < fp3)
-           *fp1++ |= *fp2++;
-       }
+      int k;
+      int nlookaheads = 0;
+      reductions *rp = states[i]->reductions;
+      shifts *sp = states[i]->shifts;
+
+      /* We need a lookahead either to distinguish different
+        reductions (i.e., there are two or more), or to distinguish a
+        reduction from a shift.  Otherwise, it is straightforward,
+        and the state is `consistent'.  */
+      if (rp->nreds > 1
+         || (rp->nreds == 1 && sp->nshifts && SHIFT_IS_SHIFT (sp, 0)))
+       nlookaheads += rp->nreds;
+      else
+       states[i]->consistent = 1;
 
 
-      rowp = fp3;
+      for (k = 0; k < sp->nshifts; k++)
+       if (SHIFT_IS_ERROR (sp, k))
+         {
+           states[i]->consistent = 0;
+           break;
+         }
+
+      states[i]->nlookaheads = nlookaheads;
+      states[i]->lookaheadsp = nLA;
+      nLA += nlookaheads;
     }
     }
+}
 
 
-  for (i = 0; i < n; i++)
+
+/*---------------------------------------.
+| Output the lookaheads for each state.  |
+`---------------------------------------*/
+
+static void
+lookaheads_print (FILE *out)
+{
+  int i, j, k;
+  fprintf (out, "Lookaheads: BEGIN\n");
+  for (i = 0; i < nstates; ++i)
     {
     {
-      /* JF removed ref to freed storage */
-      for (sp = lookback[i]; sp; sp = sptmp)
-       {
-         sptmp = sp->next;
-         XFREE (sp);
-       }
+      fprintf (out, "State %d: %d lookaheads\n",
+              i, states[i]->nlookaheads);
+
+      for (j = 0; j < states[i]->nlookaheads; ++j)
+       for (k = 0; k < ntokens; ++k)
+         if (BITISSET (LA (states[i]->lookaheadsp + j), j))
+           fprintf (out, "   on %d (%s) -> rule %d\n",
+                    k, symbols[k]->tag,
+                    -LAruleno[states[i]->lookaheadsp + j] - 1);
     }
     }
-
-  XFREE (lookback);
-  XFREE (F);
+  fprintf (out, "Lookaheads: END\n");
 }
 
 }
 
-
 void
 lalr (void)
 {
   tokensetsize = WORDSIZE (ntokens);
 
 void
 lalr (void)
 {
   tokensetsize = WORDSIZE (ntokens);
 
-  set_state_table ();
-  set_accessing_symbol ();
-  set_shift_table ();
-  set_reduction_table ();
-  set_maxrhs ();
+  initialize_lookaheads ();
   initialize_LA ();
   set_goto_map ();
   initialize_F ();
   build_relations ();
   compute_FOLLOWS ();
   compute_lookaheads ();
   initialize_LA ();
   set_goto_map ();
   initialize_F ();
   build_relations ();
   compute_FOLLOWS ();
   compute_lookaheads ();
+
+  if (trace_flag)
+    lookaheads_print (stderr);
 }
 }