]> git.saurik.com Git - bison.git/blobdiff - src/lalr.c
* src/lalr.c (F): Now a bitset*.
[bison.git] / src / lalr.c
index 4b11caaa7d124ecaeccee297da91031368ddb26f..87e91cd5f553e9857ab345cba7c43bb07eae3123 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 "bitset.h"
+#include "reader.h"
 #include "types.h"
 #include "LR0.h"
 #include "types.h"
 #include "LR0.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.  Warning:
-   there is a state_TABLE in LR0.c, but it is different and static.
-   */
-state_t *state_table = NULL;
+/* 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 = NULL;
+bitset *LA = NULL;
+size_t nLA;
 
 
-char *consistent;
-shifts **shift_table;
-reductions **reduction_table;
-short *goto_map;
-short *from_state;
-short *to_state;
+static int ngotos;
+short *goto_map = NULL;
+short *from_state = NULL;
+short *to_state = NULL;
 
 
-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 bitset *F = NULL;
 
 
-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;
-
   int height;
   int height;
-  unsigned *base;
 
   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 (R[i])
+    for (j = 0; R[i][j] >= 0; ++j)
+      {
+       if (INDEX[R[i][j]] == 0)
+         traverse (R[i][j]);
 
 
-         if (INDEX[i] > INDEX[j])
-           INDEX[i] = INDEX[j];
+       if (INDEX[i] > INDEX[R[i][j]])
+         INDEX[i] = INDEX[R[i][j]];
 
 
-         fp1 = base;
-         fp2 = F + j * tokensetsize;
-
-         while (fp1 < fp3)
-           *fp1++ |= *fp2++;
-       }
-    }
+       bitset_or (F[i], F[i], F[R[i][j]]);
+      }
 
   if (INDEX[i] == height)
 
   if (INDEX[i] == height)
-    {
-      for (;;)
-       {
-         j = VERTICES[top--];
-         INDEX[j] = infinity;
+    for (;;)
+      {
+       j = VERTICES[top--];
+       INDEX[j] = infinity;
 
 
-         if (i == j)
-           break;
+       if (i == j)
+         break;
 
 
-         fp1 = base;
-         fp2 = F + j * tokensetsize;
-
-         while (fp1 < fp3)
-           *fp2++ = *fp1++;
-       }
-    }
+       bitset_copy (F[j], F[i]);
+      }
 }
 
 
 }
 
 
@@ -136,210 +121,92 @@ 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 (state_t, nstates);
-
-  for (sp = first_state; sp; sp = sp->next)
-    {
-      state_table[sp->number].state = sp;
-      state_table[sp->number].accessing_symbol = 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)
 {
 
 static void
 initialize_LA (void)
 {
-  int i;
+  size_t i;
   int j;
   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;
-
-      lookaheads[i] = count;
-
-      rp = reduction_table[i];
-      sp = shift_table[i];
-      if (rp
-         && (rp->nreds > 1
-             || (sp && !ISVAR (state_table[sp->shifts[0]].accessing_symbol))))
-       count += rp->nreds;
-      else
-       consistent[i] = 1;
-
-      if (sp)
-       for (k = 0; k < sp->nshifts; k++)
-         if (state_table[sp->shifts[k]].accessing_symbol
-             == error_token_number)
-           {
-             consistent[i] = 0;
-             break;
-           }
-    }
-
-  lookaheads[nstates] = count;
+  /* Avoid having to special case 0.  */
+  if (!nLA)
+    nLA = 1;
 
 
-  if (count == 0)
+  LA = XCALLOC (bitset, nLA);
+  for (i = 0; i < nLA; ++i)
     {
     {
-      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[i] = bitset_create (ntokens, BITSET_FIXED);
+      bitset_zero (LA[i]);
     }
     }
+  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;
+  size_t state;
   int i;
   int i;
-  int symbol;
-  int k;
   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 = state_table[sp->shifts[i]].accessing_symbol;
-
-         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 = state_table[state2].accessing_symbol;
-
-         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];
        }
     }
 
        }
     }
 
@@ -384,73 +251,48 @@ 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 = state_table[sp->shifts[j]].accessing_symbol;
-             if (ISVAR (symbol))
-               break;
-             SETBIT (rowp, symbol);
-           }
+  int i;
 
 
-         for (; j < k; j++)
-           {
-             symbol = state_table[sp->shifts[j]].accessing_symbol;
-             if (nullable[symbol])
-               edge[nedges++] = map_goto (stateno, symbol);
-           }
+  F = XCALLOC (bitset, ngotos);
+  for (i = 0; i < ngotos; ++i)
+    {
+      F[i] = bitset_create (ntokens, BITSET_FIXED);
+      bitset_zero (F[i]);
+    }
 
 
-         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++)
+       bitset_set (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);
@@ -458,84 +300,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;
 
 
-  nedges = XCALLOC (short, n);
+  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);
+}
 
 
-  for (i = 0; i < n; i++)
+/*-------------------------------------------------------------------.
+| 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].                                                    |
+`-------------------------------------------------------------------*/
+
+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;
 }
 
@@ -543,58 +407,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 = state_table[to_state[i]].accessing_symbol;
+      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 (state_table[stateno].accessing_symbol == 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;
@@ -605,8 +453,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;
                }
@@ -615,25 +462,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);
 }
 
 
 }
 
 
@@ -646,10 +486,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);
 }
@@ -658,59 +495,102 @@ 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)
+      bitset_or (LA[i], LA[i], F[sp->value]);
+
+  /* Free LOOKBACK. */
+  for (i = 0; i < nLA; i++)
+    LIST_FREE (shorts, lookback[i]);
+
+  XFREE (lookback);
+  for (i = 0; i < (unsigned) ngotos; ++i)
+    bitset_free (F[i]);
+  XFREE (F);
+}
+
+
+/*--------------------------------------.
+| Initializing the lookaheads members.  |
+`--------------------------------------*/
+
+static void
+initialize_lookaheads (void)
+{
+  size_t 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;
+
+      for (k = 0; k < sp->nshifts; k++)
+       if (SHIFT_IS_ERROR (sp, k))
+         {
+           states[i]->consistent = 0;
+           break;
+         }
 
 
-      rowp = fp3;
+      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)
+{
+  size_t i;
+  int 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 (bitset_test (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_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);
 }
 }