]> git.saurik.com Git - bison.git/blobdiff - src/reader.c
* tests/regression.at, tests/torture.at, tests/calc.at: Adjust to
[bison.git] / src / reader.c
index 93fe353cc3e2ca8a97a57343e7f1a08c3e39d285..529cebe99efa8849280a59473610b1d824fbe523 100644 (file)
@@ -1,5 +1,5 @@
 /* Input parser for bison
 /* Input parser for bison
-   Copyright 1984, 1986, 1989, 1992, 1998, 2000
+   Copyright 1984, 1986, 1989, 1992, 1998, 2000, 2001
    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.
@@ -26,7 +26,6 @@
 #include "quote.h"
 #include "getargs.h"
 #include "files.h"
 #include "quote.h"
 #include "getargs.h"
 #include "files.h"
-#include "xalloc.h"
 #include "symtab.h"
 #include "lex.h"
 #include "gram.h"
 #include "symtab.h"
 #include "lex.h"
 #include "gram.h"
 #include "reader.h"
 #include "conflicts.h"
 
 #include "reader.h"
 #include "conflicts.h"
 
-/* Number of slots allocated (but not necessarily used yet) in `rline'  */
-static int rline_allocated;
-
 typedef struct symbol_list
 {
   struct symbol_list *next;
   bucket *sym;
 typedef struct symbol_list
 {
   struct symbol_list *next;
   bucket *sym;
+  int line;
   bucket *ruleprec;
 }
 symbol_list;
   bucket *ruleprec;
 }
 symbol_list;
@@ -65,6 +62,19 @@ static int lastprec;
 
 static bucket *errtoken;
 static bucket *undeftoken;
 
 static bucket *errtoken;
 static bucket *undeftoken;
+
+
+static symbol_list *
+symbol_list_new (bucket *sym)
+{
+  symbol_list *res = XMALLOC (symbol_list, 1);
+  res->next = NULL;
+  res->sym = sym;
+  res->line = lineno;
+  res->ruleprec = NULL;
+  return res;
+}
+
 \f
 
 /*===================\
 \f
 
 /*===================\
@@ -122,7 +132,7 @@ read_signed_integer (FILE *stream)
 `--------------------------------------------------------------*/
 
 static char *
 `--------------------------------------------------------------*/
 
 static char *
-get_type_name (int n, symbol_list * rule)
+get_type_name (int n, symbol_list *rule)
 {
   int i;
   symbol_list *rp;
 {
   int i;
   symbol_list *rp;
@@ -294,13 +304,15 @@ copy_comment (FILE *fin, struct obstack *oout)
 /*-----------------------------------------------------------------.
 | FIN is pointing to a location (i.e., a `@').  Output to OOUT a   |
 | reference to this location. STACK_OFFSET is the number of values |
 /*-----------------------------------------------------------------.
 | FIN is pointing to a location (i.e., a `@').  Output to OOUT a   |
 | reference to this location. STACK_OFFSET is the number of values |
-| in the current rule so far, which says where to find `$0' with   |
+| in the current rule so far, which says where to find `@0' with   |
 | respect to the top of the stack.                                 |
 `-----------------------------------------------------------------*/
 
 static inline void
 | respect to the top of the stack.                                 |
 `-----------------------------------------------------------------*/
 
 static inline void
-copy_at (FILE *fin, struct obstack *oout, int stack_offset)
+copy_at (FILE *fin, struct obstack *oout,
+        struct symbol_list *rule, int stack_offset)
 {
 {
+  symbol_list *rp;
   int c;
 
   c = getc (fin);
   int c;
 
   c = getc (fin);
@@ -311,11 +323,25 @@ copy_at (FILE *fin, struct obstack *oout, int stack_offset)
     }
   else if (isdigit (c) || c == '-')
     {
     }
   else if (isdigit (c) || c == '-')
     {
-      int n;
+      int n, i;
 
       ungetc (c, fin);
       n = read_signed_integer (fin);
 
 
       ungetc (c, fin);
       n = read_signed_integer (fin);
 
+      rp = rule;
+      i = 0;
+
+      while (i < n)
+       {
+         rp = rp->next;
+         if (rp == NULL)
+           {
+             complain (_("invalid @ value"));
+             return;
+           }
+         i++;
+       }
+
       obstack_fgrow1 (oout, "yylsp[%d]", n - stack_offset);
       locations_flag = 1;
     }
       obstack_fgrow1 (oout, "yylsp[%d]", n - stack_offset);
       locations_flag = 1;
     }
@@ -462,8 +488,8 @@ copy_definition (void)
 static void
 parse_token_decl (symbol_class what_is, symbol_class what_is_not)
 {
 static void
 parse_token_decl (symbol_class what_is, symbol_class what_is_not)
 {
-  token_t token = 0;
-  char *typename = 0;
+  token_t token = tok_undef;
+  char *typename = NULL;
 
   /* The symbol being defined.  */
   struct bucket *symbol = NULL;
 
   /* The symbol being defined.  */
   struct bucket *symbol = NULL;
@@ -512,7 +538,6 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not)
              /* symbol and symval combined are only one symbol */
              nsyms--;
            }
              /* symbol and symval combined are only one symbol */
              nsyms--;
            }
-         translations = 1;
          symbol = NULL;
        }
       else if (token == tok_identifier)
          symbol = NULL;
        }
       else if (token == tok_identifier)
@@ -537,12 +562,12 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not)
       else if (symbol && token == tok_number)
        {
          symbol->user_token_number = numval;
       else if (symbol && token == tok_number)
        {
          symbol->user_token_number = numval;
-         translations = 1;
        }
       else
        {
          complain (_("`%s' is invalid in %s"),
        }
       else
        {
          complain (_("`%s' is invalid in %s"),
-                   token_buffer, (what_is == token_sym) ? "%token" : "%nterm");
+                   token_buffer,
+                   (what_is == token_sym) ? "%token" : "%nterm");
          skip_to_char ('%');
        }
     }
          skip_to_char ('%');
        }
     }
@@ -679,7 +704,6 @@ parse_assoc_decl (associativity assoc)
          if (prev == tok_identifier)
            {
              symval->user_token_number = numval;
          if (prev == tok_identifier)
            {
              symval->user_token_number = numval;
-             translations = 1;
            }
          else
            {
            }
          else
            {
@@ -699,7 +723,6 @@ token_buffer);
        }
 
       prev = t;
        }
 
       prev = t;
-
     }
 }
 
     }
 }
 
@@ -716,6 +739,13 @@ parse_union_decl (void)
 {
   int c;
   int count = 0;
 {
   int c;
   int count = 0;
+  const char *prologue = "\
+#ifndef YYSTYPE\n\
+typedef union";
+  const char *epilogue = "\
+ yystype;\n\
+# define YYSTYPE yystype\n\
+#endif\n";
 
   if (typed)
     complain (_("multiple %s declarations"), "%union");
 
   if (typed)
     complain (_("multiple %s declarations"), "%union");
@@ -728,17 +758,22 @@ parse_union_decl (void)
   else
     obstack_1grow (&attrs_obstack, '\n');
 
   else
     obstack_1grow (&attrs_obstack, '\n');
 
-  obstack_sgrow (&attrs_obstack, "typedef union");
+  obstack_sgrow (&attrs_obstack, prologue);
   if (defines_flag)
   if (defines_flag)
-    obstack_sgrow (&defines_obstack, "typedef union");
+    obstack_sgrow (&defines_obstack, prologue);
 
   c = getc (finput);
 
   while (c != EOF)
     {
 
   c = getc (finput);
 
   while (c != EOF)
     {
-      obstack_1grow (&attrs_obstack, c);
-      if (defines_flag)
-       obstack_1grow (&defines_obstack, c);
+
+      /* If C contains '/', it is output by copy_comment ().  */
+      if (c != '/')
+       {
+         obstack_1grow (&attrs_obstack, c);
+         if (defines_flag)
+           obstack_1grow (&defines_obstack, c);
+       }
 
       switch (c)
        {
 
       switch (c)
        {
@@ -760,9 +795,9 @@ parse_union_decl (void)
          count--;
          if (count <= 0)
            {
          count--;
          if (count <= 0)
            {
-             obstack_sgrow (&attrs_obstack, " YYSTYPE;\n");
+             obstack_sgrow (&attrs_obstack, epilogue);
              if (defines_flag)
              if (defines_flag)
-               obstack_sgrow (&defines_obstack, " YYSTYPE;\n");
+               obstack_sgrow (&defines_obstack, epilogue);
              /* JF don't choke on trailing semi */
              c = skip_white_space ();
              if (c != ';')
              /* JF don't choke on trailing semi */
              c = skip_white_space ();
              if (c != ';')
@@ -820,9 +855,8 @@ parse_thong_decl (void)
   token_t token;
   struct bucket *symbol;
   char *typename = 0;
   token_t token;
   struct bucket *symbol;
   char *typename = 0;
-  int usrtoknum;
+  int usrtoknum = SUNDEF;
 
 
-  translations = 1;
   token = lex ();              /* fetch typename or first token */
   if (token == tok_typename)
     {
   token = lex ();              /* fetch typename or first token */
   if (token == tok_typename)
     {
@@ -852,8 +886,6 @@ parse_thong_decl (void)
       usrtoknum = numval;
       token = lex ();          /* okay, did number, now get literal */
     }
       usrtoknum = numval;
       token = lex ();          /* okay, did number, now get literal */
     }
-  else
-    usrtoknum = 0;
 
   /* process literal string token */
 
 
   /* process literal string token */
 
@@ -874,46 +906,62 @@ parse_thong_decl (void)
   nsyms--;
 }
 
   nsyms--;
 }
 
-/*------------------------------------------.
-| Parse what comes after %header_extension. |
-`------------------------------------------*/
 
 
-static void
-parse_header_extension_decl (void)
-{
-  char buff[32];
-  int len;
-  
-  if (header_extension)
-    complain (_("multiple %%header_extension declarations"));
-  fscanf (finput, "%s", buff);
-  printf("-> %s\n", buff);
-  len = strlen (buff);
-  buff[len] = '\0';
-  src_extension = XMALLOC (char, len + 1);
-  stpcpy (header_extension, buff);
-}
+/*------------------------------------------------------------------.
+| Parse a double quoted parameter. It was used for                  |
+| %{source,header}_extension.  For the moment, It is not used since |
+| extension features have been removed.                             |
+`------------------------------------------------------------------*/
 
 
-/*------------------------------------------.
-| Parse what comes after %source_extension. |
-`------------------------------------------*/
+#if 0
 
 
-static void
-parse_source_extension_decl (void)
+static const char *
+parse_dquoted_param (const char *from)
 {
   char buff[32];
 {
   char buff[32];
-  int len;
-  
-  if (src_extension)
-    complain (_("multiple %%source_extension declarations"));
-  fscanf (finput, "%s", buff);
-  printf("-> %s\n", buff);
-  len = strlen (buff);
-  buff[len] = '\0';
-  src_extension = XMALLOC (char, len + 1);
-  stpcpy (src_extension, buff);
+  int c;
+  int i;
+
+  c = skip_white_space ();
+
+  if (c != '"')
+    {
+      ungetc (c, finput);
+      complain (_("invalid %s declaration"), from);
+      return NULL;
+    }
+
+  c = getc (finput);
+  for (i = 0; (c >= '!') && (c <= '~'); i++)
+    {
+      if (c == '"')
+       break;
+
+      if (c == '\\')
+       {
+         c = getc (finput);
+         if ((c < '!') && (c > '~'))
+           break;
+       }
+
+      buff[i] = c;
+      c = getc (finput);
+    }
+  buff[i] = '\0';
+
+  if (c != '"')
+    {
+      ungetc (c, finput);
+      complain (_("invalid %s declaration"), from);
+      return NULL;
+    }
+
+  return xstrdup (buff);
 }
 
 }
 
+#endif
+
+
 /*----------------------------------------------------------------.
 | Read from finput until `%%' is seen.  Discard the `%%'.  Handle |
 | any `%' declarations, and copy the contents of any `%{ ... %}'  |
 /*----------------------------------------------------------------.
 | Read from finput until `%%' is seen.  Discard the `%%'.  Handle |
 | any `%' declarations, and copy the contents of any `%{ ... %}'  |
@@ -923,16 +971,13 @@ parse_source_extension_decl (void)
 static void
 read_declarations (void)
 {
 static void
 read_declarations (void)
 {
-  int c;
-  int tok;
-
   for (;;)
     {
   for (;;)
     {
-      c = skip_white_space ();
+      int c = skip_white_space ();
 
       if (c == '%')
        {
 
       if (c == '%')
        {
-         tok = parse_percent_token ();
+         token_t tok = parse_percent_token ();
 
          switch (tok)
            {
 
          switch (tok)
            {
@@ -983,16 +1028,16 @@ read_declarations (void)
              parse_assoc_decl (non_assoc);
              break;
 
              parse_assoc_decl (non_assoc);
              break;
 
-           case tok_hdrext:
+           case tok_noop:
              break;
 
              break;
 
-           case tok_srcext:
-             parse_source_extension_decl();
-             break;
-
-           case tok_noop:
+           case tok_stropt:
+           case tok_intopt:
+           case tok_obsolete:
+             abort ();
              break;
 
              break;
 
+           case tok_illegal:
            default:
              complain (_("unrecognized: %s"), token_buffer);
              skip_to_char ('%');
            default:
              complain (_("unrecognized: %s"), token_buffer);
              skip_to_char ('%');
@@ -1074,7 +1119,7 @@ copy_action (symbol_list *rule, int stack_offset)
 
            case '@':
              copy_at (finput, &action_obstack,
 
            case '@':
              copy_at (finput, &action_obstack,
-                      stack_offset);
+                      rule, stack_offset);
              break;
 
            case EOF:
              break;
 
            case EOF:
@@ -1096,7 +1141,13 @@ copy_action (symbol_list *rule, int stack_offset)
        }
     }
 
        }
     }
 
-  obstack_sgrow (&action_obstack, ";\n    break;}");
+  /* As a Bison extension, add the ending semicolon.  Since some Yacc
+     don't do that, help people using bison as a Yacc finding their
+     missing semicolons.  */
+  if (yacc_flag)
+    obstack_sgrow (&action_obstack, "}\n    break;");
+  else
+    obstack_sgrow (&action_obstack, ";\n    break;}");
 }
 \f
 /*-------------------------------------------------------------------.
 }
 \f
 /*-------------------------------------------------------------------.
@@ -1168,7 +1219,7 @@ copy_guard (symbol_list *rule, int stack_offset)
          break;
 
        case '@':
          break;
 
        case '@':
-         copy_at (finput, &guard_obstack, stack_offset);
+         copy_at (finput, &guard_obstack, rule, stack_offset);
          break;
 
        case EOF:
          break;
 
        case EOF:
@@ -1198,20 +1249,6 @@ copy_guard (symbol_list *rule, int stack_offset)
 }
 \f
 
 }
 \f
 
-static void
-record_rule_line (void)
-{
-  /* Record each rule's source line number in rline table.  */
-
-  if (nrules >= rline_allocated)
-    {
-      rline_allocated = nrules * 2;
-      rline = XREALLOC (rline, short, rline_allocated);
-    }
-  rline[nrules] = lineno;
-}
-
-
 /*-------------------------------------------------------------------.
 | Generate a dummy symbol, a nonterminal, whose name cannot conflict |
 | with the user's names.                                             |
 /*-------------------------------------------------------------------.
 | Generate a dummy symbol, a nonterminal, whose name cannot conflict |
 | with the user's names.                                             |
@@ -1354,10 +1391,7 @@ readgram (void)
          nrules++;
          nitems++;
 
          nrules++;
          nitems++;
 
-         record_rule_line ();
-
-         p = XCALLOC (symbol_list, 1);
-         p->sym = lhs;
+         p = symbol_list_new (lhs);
 
          crule1 = p1;
          if (p1)
 
          crule1 = p1;
          if (p1)
@@ -1419,36 +1453,35 @@ readgram (void)
                 non-terminal.  */
              if (action_flag)
                {
                 non-terminal.  */
              if (action_flag)
                {
-                 bucket *sdummy;
-
                  /* Since the action was written out with this rule's
                     number, we must give the new rule this number by
                     inserting the new rule before it.  */
 
                  /* Make a dummy nonterminal, a gensym.  */
                  /* Since the action was written out with this rule's
                     number, we must give the new rule this number by
                     inserting the new rule before it.  */
 
                  /* Make a dummy nonterminal, a gensym.  */
-                 sdummy = gensym ();
+                 bucket *sdummy = gensym ();
 
 
-                 /* Make a new rule, whose body is empty,
-                    before the current one, so that the action
-                    just read can belong to it.  */
+                 /* Make a new rule, whose body is empty, before the
+                    current one, so that the action just read can
+                    belong to it.  */
                  nrules++;
                  nitems++;
                  nrules++;
                  nitems++;
-                 record_rule_line ();
-                 p = XCALLOC (symbol_list, 1);
+                 p = symbol_list_new (sdummy);
+                 /* Attach its lineno to that of the host rule. */
+                 p->line = crule->line;
                  if (crule1)
                    crule1->next = p;
                  else
                    grammar = p;
                  if (crule1)
                    crule1->next = p;
                  else
                    grammar = p;
-                 p->sym = sdummy;
-                 crule1 = XCALLOC (symbol_list, 1);
-                 p->next = crule1;
+                 /* End of the rule. */
+                 crule1 = symbol_list_new (NULL);
                  crule1->next = crule;
 
                  crule1->next = crule;
 
+                 p->next = crule1;
+
                  /* Insert the dummy generated by that rule into this
                     rule.  */
                  nitems++;
                  /* Insert the dummy generated by that rule into this
                     rule.  */
                  nitems++;
-                 p = XCALLOC (symbol_list, 1);
-                 p->sym = sdummy;
+                 p = symbol_list_new (sdummy);
                  p1->next = p;
                  p1 = p;
 
                  p1->next = p;
                  p1 = p;
 
@@ -1458,8 +1491,7 @@ readgram (void)
              if (t == tok_identifier)
                {
                  nitems++;
              if (t == tok_identifier)
                {
                  nitems++;
-                 p = XCALLOC (symbol_list, 1);
-                 p->sym = symval;
+                 p = symbol_list_new (symval);
                  p1->next = p;
                  p1 = p;
                }
                  p1->next = p;
                  p1 = p;
                }
@@ -1473,7 +1505,7 @@ readgram (void)
            }                   /* end of  read rhs of rule */
 
          /* Put an empty link in the list to mark the end of this rule  */
            }                   /* end of  read rhs of rule */
 
          /* Put an empty link in the list to mark the end of this rule  */
-         p = XCALLOC (symbol_list, 1);
+         p = symbol_list_new (NULL);
          p1->next = p;
          p1 = p;
 
          p1->next = p;
          p1 = p;
 
@@ -1584,9 +1616,9 @@ readgram (void)
                           "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
       if (defines_flag)
        obstack_sgrow (&defines_obstack, "\
                           "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
       if (defines_flag)
        obstack_sgrow (&defines_obstack, "\
-#ifndef YYSTYPE\n\
-# define YYSTYPE int\n\
-#endif\n");
+# ifndef YYSTYPE\n\
+#  define YYSTYPE int\n\
+# endif\n");
     }
 
   /* Report any undefined symbols and consider them nonterminals.  */
     }
 
   /* Report any undefined symbols and consider them nonterminals.  */
@@ -1643,17 +1675,101 @@ output_token_defines (struct obstack *oout)
       if (c != '\0')
        continue;
 
       if (c != '\0')
        continue;
 
-      obstack_fgrow2 (oout, "#define\t%s\t%d\n",
-                     symbol,
-                     (translations ? bp->user_token_number : bp->value));
+      obstack_fgrow2 (oout, "# define\t%s\t%d\n",
+                     symbol, bp->user_token_number);
       if (semantic_parser)
       if (semantic_parser)
-       obstack_fgrow2 (oout, "#define\tT%s\t%d\n", symbol, bp->value);
+       /* FIXME: This is certainly dead wrong, and should be just as
+          above. --akim.  */
+       obstack_fgrow2 (oout, "# define\tT%s\t%d\n", symbol, bp->value);
     }
 
   obstack_1grow (oout, '\n');
 }
 
 
     }
 
   obstack_1grow (oout, '\n');
 }
 
 
+/*--------------------.
+| Output the header.  |
+`--------------------*/
+
+static void
+symbols_output (void)
+{
+  if (defines_flag)
+    {
+      output_token_defines (&defines_obstack);
+
+      if (!pure_parser)
+       {
+         if (spec_name_prefix)
+           obstack_fgrow1 (&defines_obstack, "\nextern YYSTYPE %slval;\n",
+                           spec_name_prefix);
+         else
+           obstack_sgrow (&defines_obstack,
+                                "\nextern YYSTYPE yylval;\n");
+       }
+
+      if (semantic_parser)
+       {
+         int i;
+
+         for (i = ntokens; i < nsyms; i++)
+           {
+             /* don't make these for dummy nonterminals made by gensym.  */
+             if (*tags[i] != '@')
+               obstack_fgrow2 (&defines_obstack,
+                               "# define\tNT%s\t%d\n", tags[i], i);
+           }
+#if 0
+         /* `fdefines' is now a temporary file, so we need to copy its
+            contents in `done', so we can't close it here.  */
+         fclose (fdefines);
+         fdefines = NULL;
+#endif
+       }
+    }
+}
+
+
+/*------------------------------------------------------------------.
+| Set TOKEN_TRANSLATIONS.  Check that no two symbols share the same |
+| number.                                                           |
+`------------------------------------------------------------------*/
+
+static void
+token_translations_init (void)
+{
+  bucket *bp = NULL;
+  int i;
+
+  token_translations = XCALLOC (short, max_user_token_number + 1);
+
+  /* Initialize all entries for literal tokens to 2, the internal
+     token number for $undefined., which represents all invalid
+     inputs.  */
+  for (i = 0; i <= max_user_token_number; i++)
+    token_translations[i] = 2;
+
+  for (bp = firstsymbol; bp; bp = bp->next)
+    {
+      /* Non-terminal? */
+      if (bp->value >= ntokens)
+       continue;
+      /* A token string alias? */
+      if (bp->user_token_number == SALIAS)
+       continue;
+
+      assert (bp->user_token_number != SUNDEF);
+
+      /* A token which translation has already been set? */
+      if (token_translations[bp->user_token_number] != 2)
+       complain (_("tokens %s and %s both assigned number %d"),
+                 tags[token_translations[bp->user_token_number]],
+                 bp->tag, bp->user_token_number);
+      token_translations[bp->user_token_number] = bp->value;
+    }
+}
+
+
 /*------------------------------------------------------------------.
 | Assign symbol numbers, and write definition of token names into   |
 | FDEFINES.  Set up vectors TAGS and SPREC of names and precedences |
 /*------------------------------------------------------------------.
 | Assign symbol numbers, and write definition of token names into   |
 | FDEFINES.  Set up vectors TAGS and SPREC of names and precedences |
@@ -1663,22 +1779,21 @@ output_token_defines (struct obstack *oout)
 static void
 packsymbols (void)
 {
 static void
 packsymbols (void)
 {
-  bucket *bp;
+  bucket *bp = NULL;
   int tokno = 1;
   int tokno = 1;
-  int i;
   int last_user_token_number;
   static char DOLLAR[] = "$";
 
   int last_user_token_number;
   static char DOLLAR[] = "$";
 
-  /* int lossage = 0; JF set but not used */
-
   tags = XCALLOC (char *, nsyms + 1);
   tags = XCALLOC (char *, nsyms + 1);
-  tags[0] = DOLLAR;
   user_toknums = XCALLOC (short, nsyms + 1);
   user_toknums = XCALLOC (short, nsyms + 1);
-  user_toknums[0] = 0;
 
   sprec = XCALLOC (short, nsyms);
   sassoc = XCALLOC (short, nsyms);
 
 
   sprec = XCALLOC (short, nsyms);
   sassoc = XCALLOC (short, nsyms);
 
+  /* The EOF token. */
+  tags[0] = DOLLAR;
+  user_toknums[0] = 0;
+
   max_user_token_number = 256;
   last_user_token_number = 256;
 
   max_user_token_number = 256;
   last_user_token_number = 256;
 
@@ -1731,7 +1846,7 @@ packsymbols (void)
 
       if (bp->class == token_sym)
        {
 
       if (bp->class == token_sym)
        {
-         if (translations && !(bp->user_token_number))
+         if (bp->user_token_number == SUNDEF)
            bp->user_token_number = ++last_user_token_number;
          if (bp->user_token_number > max_user_token_number)
            max_user_token_number = bp->user_token_number;
            bp->user_token_number = ++last_user_token_number;
          if (bp->user_token_number > max_user_token_number)
            max_user_token_number = bp->user_token_number;
@@ -1741,34 +1856,9 @@ packsymbols (void)
       user_toknums[bp->value] = bp->user_token_number;
       sprec[bp->value] = bp->prec;
       sassoc[bp->value] = bp->assoc;
       user_toknums[bp->value] = bp->user_token_number;
       sprec[bp->value] = bp->prec;
       sassoc[bp->value] = bp->assoc;
-
     }
 
     }
 
-  if (translations)
-    {
-      int j;
-
-      token_translations = XCALLOC (short, max_user_token_number + 1);
-
-      /* initialize all entries for literal tokens to 2, the internal
-         token number for $undefined., which represents all invalid
-         inputs.  */
-      for (j = 0; j <= max_user_token_number; j++)
-       token_translations[j] = 2;
-
-      for (bp = firstsymbol; bp; bp = bp->next)
-       {
-         if (bp->value >= ntokens)
-           continue;           /* non-terminal */
-         if (bp->user_token_number == SALIAS)
-           continue;
-         if (token_translations[bp->user_token_number] != 2)
-           complain (_("tokens %s and %s both assigned number %d"),
-                     tags[token_translations[bp->user_token_number]],
-                     bp->tag, bp->user_token_number);
-         token_translations[bp->user_token_number] = bp->value;
-       }
-    }
+  token_translations_init ();
 
   error_token_number = errtoken->value;
 
 
   error_token_number = errtoken->value;
 
@@ -1781,36 +1871,6 @@ packsymbols (void)
     fatal (_("the start symbol %s is a token"), startval->tag);
 
   start_symbol = startval->value;
     fatal (_("the start symbol %s is a token"), startval->tag);
 
   start_symbol = startval->value;
-
-  if (defines_flag)
-    {
-      output_token_defines (&defines_obstack);
-
-      if (!pure_parser)
-       {
-         if (spec_name_prefix)
-           obstack_fgrow1 (&defines_obstack, "\nextern YYSTYPE %slval;\n",
-                           spec_name_prefix);
-         else
-           obstack_sgrow (&defines_obstack,
-                                "\nextern YYSTYPE yylval;\n");
-       }
-
-      if (semantic_parser)
-       for (i = ntokens; i < nsyms; i++)
-         {
-           /* don't make these for dummy nonterminals made by gensym.  */
-           if (*tags[i] != '@')
-              obstack_fgrow2 (&defines_obstack,
-                              "#define\tNT%s\t%d\n", tags[i], i);
-         }
-#if 0
-      /* `fdefines' is now a temporary file, so we need to copy its
-         contents in `done', so we can't close it here.  */
-      fclose (fdefines);
-      fdefines = NULL;
-#endif
-    }
 }
 
 
 }
 
 
@@ -1826,14 +1886,8 @@ packgram (void)
   int ruleno;
   symbol_list *p;
 
   int ruleno;
   symbol_list *p;
 
-  bucket *ruleprec;
-
   ritem = XCALLOC (short, nitems + 1);
   ritem = XCALLOC (short, nitems + 1);
-  rlhs = XCALLOC (short, nrules) - 1;
-  rrhs = XCALLOC (short, nrules) - 1;
-  rprec = XCALLOC (short, nrules) - 1;
-  rprecsym = XCALLOC (short, nrules) - 1;
-  rassoc = XCALLOC (short, nrules) - 1;
+  rule_table = XCALLOC (rule_t, nrules) - 1;
 
   itemno = 0;
   ruleno = 1;
 
   itemno = 0;
   ruleno = 1;
@@ -1841,9 +1895,11 @@ packgram (void)
   p = grammar;
   while (p)
     {
   p = grammar;
   while (p)
     {
-      rlhs[ruleno] = p->sym->value;
-      rrhs[ruleno] = itemno;
-      ruleprec = p->ruleprec;
+      bucket *ruleprec = p->ruleprec;
+      rule_table[ruleno].lhs = p->sym->value;
+      rule_table[ruleno].rhs = itemno;
+      rule_table[ruleno].line = p->line;
+      rule_table[ruleno].useful = TRUE;
 
       p = p->next;
       while (p && p->sym)
 
       p = p->next;
       while (p && p->sym)
@@ -1853,8 +1909,8 @@ packgram (void)
             of the last token in it.  */
          if (p->sym->class == token_sym)
            {
             of the last token in it.  */
          if (p->sym->class == token_sym)
            {
-             rprec[ruleno] = p->sym->prec;
-             rassoc[ruleno] = p->sym->assoc;
+             rule_table[ruleno].prec = p->sym->prec;
+             rule_table[ruleno].assoc = p->sym->assoc;
            }
          if (p)
            p = p->next;
            }
          if (p)
            p = p->next;
@@ -1864,9 +1920,9 @@ packgram (void)
          the specified symbol's precedence replaces the default.  */
       if (ruleprec)
        {
          the specified symbol's precedence replaces the default.  */
       if (ruleprec)
        {
-         rprec[ruleno] = ruleprec->prec;
-         rassoc[ruleno] = ruleprec->assoc;
-         rprecsym[ruleno] = ruleprec->value;
+         rule_table[ruleno].prec = ruleprec->prec;
+         rule_table[ruleno].assoc = ruleprec->assoc;
+         rule_table[ruleno].precsym = ruleprec->value;
        }
 
       ritem[itemno++] = -ruleno;
        }
 
       ritem[itemno++] = -ruleno;
@@ -1877,6 +1933,9 @@ packgram (void)
     }
 
   ritem[itemno] = 0;
     }
 
   ritem[itemno] = 0;
+
+  if (trace_flag)
+    ritem_print (stderr);
 }
 \f
 /*-------------------------------------------------------------------.
 }
 \f
 /*-------------------------------------------------------------------.
@@ -1893,21 +1952,10 @@ reader (void)
   start_flag = 0;
   startval = NULL;             /* start symbol not specified yet. */
 
   start_flag = 0;
   startval = NULL;             /* start symbol not specified yet. */
 
-#if 0
-  /* initially assume token number translation not needed.  */
-  translations = 0;
-#endif
-  /* Nowadays translations is always set to 1, since we give `error' a
-     user-token-number to satisfy the Posix demand for YYERRCODE==256.
-   */
-  translations = 1;
-
   nsyms = 1;
   nvars = 0;
   nrules = 0;
   nitems = 0;
   nsyms = 1;
   nvars = 0;
   nrules = 0;
   nitems = 0;
-  rline_allocated = 10;
-  rline = XCALLOC (short, rline_allocated);
 
   typed = 0;
   lastprec = 0;
 
   typed = 0;
   lastprec = 0;
@@ -1917,7 +1965,7 @@ reader (void)
 
   grammar = NULL;
 
 
   grammar = NULL;
 
-  init_lex ();
+  lex_init ();
   lineno = 1;
 
   /* Initialize the symbol table.  */
   lineno = 1;
 
   /* Initialize the symbol table.  */
@@ -1935,7 +1983,6 @@ reader (void)
   /* Read the declaration section.  Copy %{ ... %} groups to
      TABLE_OBSTACK and FDEFINES file.  Also notice any %token, %left,
      etc. found there.  */
   /* Read the declaration section.  Copy %{ ... %} groups to
      TABLE_OBSTACK and FDEFINES file.  Also notice any %token, %left,
      etc. found there.  */
-  obstack_1grow (&table_obstack, '\n');
   obstack_fgrow3 (&table_obstack, "\
 /* %s, made from %s\n\
    by GNU bison %s.  */\n\
   obstack_fgrow3 (&table_obstack, "\
 /* %s, made from %s\n\
    by GNU bison %s.  */\n\
@@ -1964,9 +2011,8 @@ reader (void)
   packsymbols ();
   /* Convert the grammar into the format described in gram.h.  */
   packgram ();
   packsymbols ();
   /* Convert the grammar into the format described in gram.h.  */
   packgram ();
-  /* Free the symbol table data structure since symbols are now all
-     referred to by symbol number.  */
-  free_symtab ();
+  /* Output the headers. */
+  symbols_output ();
 }
 
 
 }