]> git.saurik.com Git - bison.git/blobdiff - src/lalr.c
* data/yacc.c (yyparse): Pacify non-GCC compilers about yyerrorlab
[bison.git] / src / lalr.c
index b1f84607ffb7396dd6e6d3f19d6cc450ab8f307b..e69c05c75d972c7d94bf1d4009325ad1482c88d7 100644 (file)
@@ -1,5 +1,6 @@
-/* Compute look-ahead criteria for bison,
-   Copyright (C) 1984, 1986, 1989, 2000, 2001, 2002
+/* Compute look-ahead criteria for Bison.
+
+   Copyright (C) 1984, 1986, 1989, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
    Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
 /* Compute how to make the finite state machine deterministic; find
 
 
 /* Compute how to make the finite state machine deterministic; find
-   which rules need lookahead in each state, and which lookahead
+   which rules need look-ahead in each state, and which look-ahead
    tokens they accept.  */
 
 #include "system.h"
    tokens they accept.  */
 
 #include "system.h"
-#include "bitset.h"
-#include "bitsetv.h"
-#include "quotearg.h"
-#include "symtab.h"
-#include "gram.h"
-#include "reader.h"
-#include "types.h"
+
+#include <bitset.h>
+#include <bitsetv.h>
+#include <quotearg.h>
+
 #include "LR0.h"
 #include "complain.h"
 #include "LR0.h"
 #include "complain.h"
-#include "lalr.h"
-#include "nullable.h"
 #include "derives.h"
 #include "getargs.h"
 #include "derives.h"
 #include "getargs.h"
+#include "gram.h"
+#include "lalr.h"
+#include "nullable.h"
+#include "reader.h"
+#include "relation.h"
+#include "symtab.h"
 
 
-rule_t **LArule = NULL;
-bitsetv LA = NULL;
-size_t nLA;
-
-static int ngotos;
-short *goto_map = NULL;
-state_number_t *from_state = NULL;
-state_number_t *to_state = NULL;
-
-/* And for the famous F variable, which name is so descriptive that a
-   comment is hardly needed.  <grin>.  */
-static bitsetv F = NULL;
-
-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 int infinity;
-
-static void
-traverse (int i)
-{
-  int j;
-  int height;
-
-  VERTICES[++top] = i;
-  INDEX[i] = height = top;
-
-  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[R[i][j]])
-         INDEX[i] = INDEX[R[i][j]];
-
-       bitset_or (F[i], F[i], F[R[i][j]]);
-      }
-
-  if (INDEX[i] == height)
-    for (;;)
-      {
-       j = VERTICES[top--];
-       INDEX[j] = infinity;
-
-       if (i == j)
-         break;
-
-       bitset_copy (F[j], F[i]);
-      }
-}
-
+goto_number *goto_map;
+static goto_number ngotos;
+state_number *from_state;
+state_number *to_state;
 
 
-static void
-digraph (short **relation)
+/* Linked list of goto numbers.  */
+typedef struct goto_list
 {
 {
-  int i;
+  struct goto_list *next;
+  goto_number value;
+} goto_list;
 
 
-  infinity = ngotos + 2;
-  INDEX = XCALLOC (short, ngotos + 1);
-  VERTICES = XCALLOC (short, ngotos + 1);
-  top = 0;
 
 
-  R = relation;
+/* LA is a LR by NTOKENS matrix of bits.  LA[l, i] is 1 if the rule
+   LArule[l] is applicable in the appropriate state when the next
+   token is symbol i.  If LA[l, i] and LA[l, j] are both 1 for i != j,
+   it is a conflict.  */
 
 
-  for (i = 0; i < ngotos; i++)
-    INDEX[i] = 0;
-
-  for (i = 0; i < ngotos; i++)
-    if (INDEX[i] == 0 && R[i])
-      traverse (i);
-
-  XFREE (INDEX);
-  XFREE (VERTICES);
-}
+static bitsetv LA = NULL;
+size_t nLA;
 
 
 
 
-static void
-initialize_LA (void)
-{
-  state_number_t i;
-  int j;
-  rule_t **np;
+/* And for the famous F variable, which name is so descriptive that a
+   comment is hardly needed.  <grin>.  */
+static bitsetv F = NULL;
 
 
-  /* Avoid having to special case 0.  */
-  if (!nLA)
-    nLA = 1;
+static goto_number **includes;
+static goto_list **lookback;
 
 
-  LA = bitsetv_create (nLA, ntokens, BITSET_FIXED);
-  LArule = XCALLOC (rule_t *, nLA);
-  lookback = XCALLOC (shorts *, nLA);
 
 
-  np = LArule;
-  for (i = 0; i < nstates; i++)
-    if (!states[i]->consistent)
-      for (j = 0; j < states[i]->reductions->nreds; j++)
-       *np++ = &rules[states[i]->reductions->rules[j]];
-}
 
 
 static void
 set_goto_map (void)
 {
 
 
 static void
 set_goto_map (void)
 {
-  state_number_t state;
-  short *temp_map;
+  state_number s;
+  goto_number *temp_map;
 
 
-  goto_map = XCALLOC (short, nvars + 1) - ntokens;
-  temp_map = XCALLOC (short, nvars + 1) - ntokens;
+  goto_map = xcalloc (nvars + 1, sizeof *goto_map);
+  temp_map = xnmalloc (nvars + 1, sizeof *temp_map);
 
   ngotos = 0;
 
   ngotos = 0;
-  for (state = 0; state < nstates; ++state)
+  for (s = 0; s < nstates; ++s)
     {
     {
-      shifts_t *sp = states[state]->shifts;
+      transitions *sp = states[s]->transitions;
       int i;
       int i;
-      for (i = sp->nshifts - 1; i >= 0 && SHIFT_IS_GOTO (sp, i); --i)
+      for (i = sp->num - 1; i >= 0 && TRANSITION_IS_GOTO (sp, i); --i)
        {
        {
-         if (ngotos == SHRT_MAX)
-           fatal (_("too many gotos (max %d)"), SHRT_MAX);
-
          ngotos++;
          ngotos++;
-         goto_map[SHIFT_SYMBOL (sp, i)]++;
+
+         /* Abort if (ngotos + 1) would overflow.  */
+         if (ngotos == GOTO_NUMBER_MAXIMUM)
+           abort ();
+
+         goto_map[TRANSITION_SYMBOL (sp, i) - ntokens]++;
        }
     }
 
   {
        }
     }
 
   {
-    int k = 0;
+    goto_number k = 0;
     int i;
     for (i = ntokens; i < nsyms; i++)
       {
     int i;
     for (i = ntokens; i < nsyms; i++)
       {
-       temp_map[i] = k;
-       k += goto_map[i];
+       temp_map[i - ntokens] = k;
+       k += goto_map[i - ntokens];
       }
 
     for (i = ntokens; i < nsyms; i++)
       }
 
     for (i = ntokens; i < nsyms; i++)
-      goto_map[i] = temp_map[i];
+      goto_map[i - ntokens] = temp_map[i - ntokens];
 
 
-    goto_map[nsyms] = ngotos;
-    temp_map[nsyms] = ngotos;
+    goto_map[nsyms - ntokens] = ngotos;
+    temp_map[nsyms - ntokens] = ngotos;
   }
 
   }
 
-  from_state = XCALLOC (state_number_t, ngotos);
-  to_state = XCALLOC (state_number_t, ngotos);
+  from_state = xcalloc (ngotos, sizeof *from_state);
+  to_state = xcalloc (ngotos, sizeof *to_state);
 
 
-  for (state = 0; state < nstates; ++state)
+  for (s = 0; s < nstates; ++s)
     {
     {
-      shifts_t *sp = states[state]->shifts;
+      transitions *sp = states[s]->transitions;
       int i;
       int i;
-      for (i = sp->nshifts - 1; i >= 0 && SHIFT_IS_GOTO (sp, i); --i)
+      for (i = sp->num - 1; i >= 0 && TRANSITION_IS_GOTO (sp, i); --i)
        {
        {
-         int k = temp_map[SHIFT_SYMBOL (sp, i)]++;
-         from_state[k] = state;
-         to_state[k] = sp->shifts[i];
+         goto_number k = temp_map[TRANSITION_SYMBOL (sp, i) - ntokens]++;
+         from_state[k] = s;
+         to_state[k] = sp->states[i]->number;
        }
     }
 
        }
     }
 
-  XFREE (temp_map + ntokens);
+  free (temp_map);
 }
 
 
 }
 
 
@@ -215,259 +140,160 @@ set_goto_map (void)
 | Map a state/symbol pair into its numeric representation.  |
 `----------------------------------------------------------*/
 
 | Map a state/symbol pair into its numeric representation.  |
 `----------------------------------------------------------*/
 
-static int
-map_goto (state_number_t state, symbol_number_t symbol)
+static goto_number
+map_goto (state_number s0, symbol_number sym)
 {
 {
-  int high;
-  int low;
-  int middle;
-  state_number_t s;
+  goto_number high;
+  goto_number low;
+  goto_number middle;
+  state_number s;
 
 
-  low = goto_map[symbol];
-  high = goto_map[symbol + 1] - 1;
+  low = goto_map[sym - ntokens];
+  high = goto_map[sym - ntokens + 1] - 1;
 
 
-  while (low <= high)
+  for (;;)
     {
     {
+      if (high < low)
+       abort ();
       middle = (low + high) / 2;
       s = from_state[middle];
       middle = (low + high) / 2;
       s = from_state[middle];
-      if (s == state)
+      if (s == s0)
        return middle;
        return middle;
-      else if (s < state)
+      else if (s < s0)
        low = middle + 1;
       else
        high = middle - 1;
     }
        low = middle + 1;
       else
        high = middle - 1;
     }
-
-  assert (0);
-  /* NOTREACHED */
-  return 0;
 }
 
 
 static void
 initialize_F (void)
 {
 }
 
 
 static void
 initialize_F (void)
 {
-  short **reads = XCALLOC (short *, ngotos);
-  short *edge = XCALLOC (short, ngotos + 1);
-  int nedges = 0;
+  goto_number **reads = xnmalloc (ngotos, sizeof *reads);
+  goto_number *edge = xnmalloc (ngotos + 1, sizeof *edge);
+  goto_number nedges = 0;
 
 
-  int i;
+  goto_number i;
 
   F = bitsetv_create (ngotos, ntokens, BITSET_FIXED);
 
   for (i = 0; i < ngotos; i++)
     {
 
   F = bitsetv_create (ngotos, ntokens, BITSET_FIXED);
 
   for (i = 0; i < ngotos; i++)
     {
-      state_number_t stateno = to_state[i];
-      shifts_t *sp = states[stateno]->shifts;
+      state_number stateno = to_state[i];
+      transitions *sp = states[stateno]->transitions;
 
       int j;
 
       int j;
-      for (j = 0; j < sp->nshifts && SHIFT_IS_SHIFT (sp, j); j++)
-       bitset_set (F[i], SHIFT_SYMBOL (sp, j));
+      FOR_EACH_SHIFT (sp, j)
+       bitset_set (F[i], TRANSITION_SYMBOL (sp, j));
 
 
-      for (; j < sp->nshifts; j++)
+      for (; j < sp->num; j++)
        {
        {
-         symbol_number_t symbol = SHIFT_SYMBOL (sp, j);
-         if (nullable[symbol])
-           edge[nedges++] = map_goto (stateno, symbol);
+         symbol_number sym = TRANSITION_SYMBOL (sp, j);
+         if (nullable[sym - ntokens])
+           edge[nedges++] = map_goto (stateno, sym);
        }
 
        }
 
-      if (nedges)
+      if (nedges == 0)
+       reads[i] = NULL;
+      else
        {
        {
-         reads[i] = XCALLOC (short, nedges + 1);
-         memcpy (reads[i], edge, nedges * sizeof (edge[0]));
-         reads[i][nedges] = -1;
+         reads[i] = xnmalloc (nedges + 1, sizeof reads[i][0]);
+         memcpy (reads[i], edge, nedges * sizeof edge[0]);
+         reads[i][nedges] = END_NODE;
          nedges = 0;
        }
     }
 
          nedges = 0;
        }
     }
 
-  digraph (reads);
+  relation_digraph (reads, ngotos, &F);
 
   for (i = 0; i < ngotos; i++)
 
   for (i = 0; i < ngotos; i++)
-    XFREE (reads[i]);
+    free (reads[i]);
 
 
-  XFREE (reads);
-  XFREE (edge);
+  free (reads);
+  free (edge);
 }
 
 
 static void
 }
 
 
 static void
-add_lookback_edge (state_t *state, rule_number_t ruleno, int gotono)
+add_lookback_edge (state *s, rule *r, goto_number gotono)
 {
 {
-  int i;
-  shorts *sp;
-
-  for (i = 0; i < state->nlookaheads; ++i)
-    if (state->lookaheads_rule[i]->number == ruleno)
-      break;
-
-  assert (state->lookaheads_rule[i]->number == ruleno);
-
-  sp = XCALLOC (shorts, 1);
-  sp->next = lookback[(state->lookaheads - LA) + i];
+  int ri = state_reduction_find (s, r);
+  goto_list *sp = xmalloc (sizeof *sp);
+  sp->next = lookback[(s->reductions->look_ahead_tokens - LA) + ri];
   sp->value = gotono;
   sp->value = gotono;
-  lookback[(state->lookaheads - LA) + i] = sp;
-}
-
-
-static void
-matrix_print (FILE *out, short **matrix, int n)
-{
-  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);
+  lookback[(s->reductions->look_ahead_tokens - LA) + ri] = sp;
 }
 
 }
 
-/*-------------------------------------------------------------------.
-| 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)
-    {
-      fputs ("transpose: input\n", stderr);
-      matrix_print (stderr, R_arg, 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++)
-    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)
-       {
-         *end_R[R_arg[i][j]] = i;
-         ++end_R[R_arg[i][j]];
-       }
-
-  free (nedges);
-  free (end_R);
-
-  /* Free the input: it is replaced with the result. */
-  for (i = 0; i < n; i++)
-    XFREE (R_arg[i]);
-  free (R_arg);
-
-  if (trace_flag)
-    {
-      fputs ("transpose: output\n", stderr);
-      matrix_print (stderr, new_R, n);
-    }
-
-  return new_R;
-}
 
 
 static void
 build_relations (void)
 {
 
 
 static void
 build_relations (void)
 {
-  short *edge = XCALLOC (short, ngotos + 1);
-  state_number_t *states1 = XCALLOC (state_number_t, ritem_longest_rhs () + 1);
-  int i;
+  goto_number *edge = xnmalloc (ngotos + 1, sizeof *edge);
+  state_number *states1 = xnmalloc (ritem_longest_rhs () + 1, sizeof *states1);
+  goto_number i;
 
 
-  includes = XCALLOC (short *, ngotos);
+  includes = xnmalloc (ngotos, sizeof *includes);
 
   for (i = 0; i < ngotos; i++)
     {
       int nedges = 0;
 
   for (i = 0; i < ngotos; i++)
     {
       int nedges = 0;
-      symbol_number_t symbol1 = states[to_state[i]]->accessing_symbol;
-      rule_number_t *rulep;
+      symbol_number symbol1 = states[to_state[i]]->accessing_symbol;
+      rule **rulep;
 
 
-      for (rulep = derives[symbol1]; *rulep > 0; rulep++)
+      for (rulep = derives[symbol1 - ntokens]; *rulep; rulep++)
        {
        {
-         int done;
+         bool done;
          int length = 1;
          int length = 1;
-         item_number_t *rp;
-         state_t *state = states[from_state[i]];
-         states1[0] = state->number;
+         item_number *rp;
+         state *s = states[from_state[i]];
+         states1[0] = s->number;
 
 
-         for (rp = rules[*rulep].rhs; *rp >= 0; rp++)
+         for (rp = (*rulep)->rhs; *rp >= 0; rp++)
            {
            {
-             shifts_t *sp = state->shifts;
-             int j;
-             for (j = 0; j < sp->nshifts; j++)
-               {
-                 state = states[sp->shifts[j]];
-                 if (state->accessing_symbol
-                     == item_number_as_symbol_number (*rp))
-                   break;
-               }
-
-             states1[length++] = state->number;
+             s = transitions_to (s->transitions,
+                                 item_number_as_symbol_number (*rp));
+             states1[length++] = s->number;
            }
 
            }
 
-         if (!state->consistent)
-           add_lookback_edge (state, *rulep, i);
+         if (!s->consistent)
+           add_lookback_edge (s, *rulep, i);
 
          length--;
 
          length--;
-         done = 0;
+         done = false;
          while (!done)
            {
          while (!done)
            {
-             done = 1;
+             done = true;
              rp--;
              /* JF added rp>=ritem &&   I hope to god its right! */
              if (rp >= ritem && ISVAR (*rp))
                {
              rp--;
              /* JF added rp>=ritem &&   I hope to god its right! */
              if (rp >= ritem && ISVAR (*rp))
                {
-                 /* Downcasting from item_number_t to symbol_number_t. */
+                 /* Downcasting from item_number to symbol_number.  */
                  edge[nedges++] = map_goto (states1[--length],
                                             item_number_as_symbol_number (*rp));
                  edge[nedges++] = map_goto (states1[--length],
                                             item_number_as_symbol_number (*rp));
-                 if (nullable[*rp])
-                   done = 0;
+                 if (nullable[*rp - ntokens])
+                   done = false;
                }
            }
        }
 
                }
            }
        }
 
-      if (nedges)
+      if (nedges == 0)
+       includes[i] = NULL;
+      else
        {
          int j;
        {
          int j;
-         includes[i] = XCALLOC (short, nedges + 1);
+         includes[i] = xnmalloc (nedges + 1, sizeof includes[i][0]);
          for (j = 0; j < nedges; j++)
            includes[i][j] = edge[j];
          for (j = 0; j < nedges; j++)
            includes[i][j] = edge[j];
-         includes[i][nedges] = -1;
+         includes[i][nedges] = END_NODE;
        }
     }
 
        }
     }
 
-  XFREE (edge);
-  XFREE (states1);
+  free (edge);
+  free (states1);
 
 
-  includes = transpose (includes, ngotos);
+  relation_transpose (&includes, ngotos);
 }
 
 
 }
 
 
@@ -475,22 +301,22 @@ build_relations (void)
 static void
 compute_FOLLOWS (void)
 {
 static void
 compute_FOLLOWS (void)
 {
-  int i;
+  goto_number i;
 
 
-  digraph (includes);
+  relation_digraph (includes, ngotos, &F);
 
   for (i = 0; i < ngotos; i++)
 
   for (i = 0; i < ngotos; i++)
-    XFREE (includes[i]);
+    free (includes[i]);
 
 
-  XFREE (includes);
+  free (includes);
 }
 
 
 static void
 }
 
 
 static void
-compute_lookaheads (void)
+compute_look_ahead_tokens (void)
 {
   size_t i;
 {
   size_t i;
-  shorts *sp;
+  goto_list *sp;
 
   for (i = 0; i < nLA; i++)
     for (sp = lookback[i]; sp; sp = sp->next)
 
   for (i = 0; i < nLA; i++)
     for (sp = lookback[i]; sp; sp = sp->next)
@@ -498,115 +324,139 @@ compute_lookaheads (void)
 
   /* Free LOOKBACK. */
   for (i = 0; i < nLA; i++)
 
   /* Free LOOKBACK. */
   for (i = 0; i < nLA; i++)
-    LIST_FREE (shorts, lookback[i]);
+    LIST_FREE (goto_list, lookback[i]);
 
 
-  XFREE (lookback);
+  free (lookback);
   bitsetv_free (F);
 }
 
 
   bitsetv_free (F);
 }
 
 
-/*-------------------------------------------------------------.
-| Count the number of lookaheads required for each state       |
-| (NLOOKAHEADS member).  Compute the total number of LA, NLA.  |
-`-------------------------------------------------------------*/
+/*-----------------------------------------------------.
+| Count the number of look-ahead tokens required for S |
+| (N_LOOK_AHEAD_TOKENS member).                        |
+`-----------------------------------------------------*/
 
 
-static void
-states_lookaheads_count (void)
+static int
+state_look_ahead_tokens_count (state *s)
 {
 {
-  state_number_t i;
-  nLA = 0;
-
-  /* Count   */
-  for (i = 0; i < nstates; i++)
-    {
-      int k;
-      int nlookaheads = 0;
-      reductions_t *rp = states[i]->reductions;
-      shifts_t *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;
-         }
+  int k;
+  int n_look_ahead_tokens = 0;
+  reductions *rp = s->reductions;
+  transitions *sp = s->transitions;
+
+  /* We need a look-ahead 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->num > 1
+      || (rp->num == 1 && sp->num &&
+         !TRANSITION_IS_DISABLED (sp, 0) && TRANSITION_IS_SHIFT (sp, 0)))
+    n_look_ahead_tokens += rp->num;
+  else
+    s->consistent = 1;
+
+  for (k = 0; k < sp->num; k++)
+    if (!TRANSITION_IS_DISABLED (sp, k) && TRANSITION_IS_ERROR (sp, k))
+      {
+       s->consistent = 0;
+       break;
+      }
 
 
-      states[i]->nlookaheads = nlookaheads;
-      nLA += nlookaheads;
-    }
+  return n_look_ahead_tokens;
 }
 
 
 }
 
 
-/*--------------------------------------.
-| Initializing the lookaheads members.  |
-`--------------------------------------*/
+/*-----------------------------------------------------.
+| Compute LA, NLA, and the look_ahead_tokens members.  |
+`-----------------------------------------------------*/
 
 static void
 
 static void
-states_lookaheads_initialize (void)
+initialize_LA (void)
 {
 {
-  state_number_t i;
-  bitsetv pLA = LA;
-  rule_t **pLArule = LArule;
+  state_number i;
+  bitsetv pLA;
 
 
-  /* Initialize the members LOOKAHEADS and LOOKAHEADS_RULE for each
-     state.  */
+  /* Compute the total number of reductions requiring a look-ahead.  */
+  nLA = 0;
+  for (i = 0; i < nstates; i++)
+    nLA += state_look_ahead_tokens_count (states[i]);
+  /* Avoid having to special case 0.  */
+  if (!nLA)
+    nLA = 1;
+
+  pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED);
+  lookback = xcalloc (nLA, sizeof *lookback);
+
+  /* Initialize the members LOOK_AHEAD_TOKENS for each state whose reductions
+     require look-ahead tokens.  */
   for (i = 0; i < nstates; i++)
     {
   for (i = 0; i < nstates; i++)
     {
-      states[i]->lookaheads = pLA;
-      states[i]->lookaheads_rule = pLArule;
-      pLA += states[i]->nlookaheads;
-      pLArule += states[i]->nlookaheads;
+      int count = state_look_ahead_tokens_count (states[i]);
+      if (count)
+       {
+         states[i]->reductions->look_ahead_tokens = pLA;
+         pLA += count;
+       }
     }
 }
 
 
     }
 }
 
 
-/*---------------------------------------.
-| Output the lookaheads for each state.  |
-`---------------------------------------*/
+/*----------------------------------------------.
+| Output the look-ahead tokens for each state.  |
+`----------------------------------------------*/
 
 static void
 
 static void
-lookaheads_print (FILE *out)
+look_ahead_tokens_print (FILE *out)
 {
 {
-  state_number_t i;
+  state_number i;
   int j, k;
   int j, k;
-  fprintf (out, "Lookaheads: BEGIN\n");
+  fprintf (out, "Look-ahead tokens: BEGIN\n");
   for (i = 0; i < nstates; ++i)
     {
   for (i = 0; i < nstates; ++i)
     {
-      fprintf (out, "State %d: %d lookaheads\n",
-              i, states[i]->nlookaheads);
+      reductions *reds = states[i]->reductions;
+      bitset_iterator iter;
+      int n_look_ahead_tokens = 0;
+
+      if (reds->look_ahead_tokens)
+       for (k = 0; k < reds->num; ++k)
+         if (reds->look_ahead_tokens[k])
+           ++n_look_ahead_tokens;
 
 
-      for (j = 0; j < states[i]->nlookaheads; ++j)
-       for (k = 0; k < ntokens; ++k)
-         if (bitset_test (states[i]->lookaheads[j], k))
+      fprintf (out, "State %d: %d look-ahead tokens\n",
+              i, n_look_ahead_tokens);
+
+      if (reds->look_ahead_tokens)
+       for (j = 0; j < reds->num; ++j)
+         BITSET_FOR_EACH (iter, reds->look_ahead_tokens[j], k, 0)
+         {
            fprintf (out, "   on %d (%s) -> rule %d\n",
            fprintf (out, "   on %d (%s) -> rule %d\n",
-                    k, symbol_tag_get (symbols[k]),
-                    states[i]->lookaheads_rule[j]->number - 1);
+                    k, symbols[k]->tag,
+                    reds->rules[j]->number);
+         };
     }
     }
-  fprintf (out, "Lookaheads: END\n");
+  fprintf (out, "Look-ahead tokens: END\n");
 }
 
 void
 lalr (void)
 {
 }
 
 void
 lalr (void)
 {
-  states_lookaheads_count ();
   initialize_LA ();
   initialize_LA ();
-  states_lookaheads_initialize ();
   set_goto_map ();
   initialize_F ();
   build_relations ();
   compute_FOLLOWS ();
   set_goto_map ();
   initialize_F ();
   build_relations ();
   compute_FOLLOWS ();
-  compute_lookaheads ();
+  compute_look_ahead_tokens ();
+
+  if (trace_flag & trace_sets)
+    look_ahead_tokens_print (stderr);
+}
 
 
-  if (trace_flag)
-    lookaheads_print (stderr);
+
+void
+lalr_free (void)
+{
+  state_number s;
+  for (s = 0; s < nstates; ++s)
+    states[s]->reductions->look_ahead_tokens = NULL;
+  bitsetv_free (LA);
 }
 }