]> git.saurik.com Git - bison.git/blobdiff - src/reader.c
* src/symtab.c (symbol_user_token_number_set): Don't complain when
[bison.git] / src / reader.c
index 527194e06ea2a3c8f99f0b234c00a65461907680..f2bc42e724db4bf926575c3939a92651d3c0a59d 100644 (file)
@@ -1,5 +1,5 @@
 /* Input parser for bison
 /* Input parser for bison
-   Copyright 1984, 1986, 1989, 1992, 1998, 2000, 2001
+   Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000, 2001, 2002
    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.
 typedef struct symbol_list
 {
   struct symbol_list *next;
 typedef struct symbol_list
 {
   struct symbol_list *next;
-  bucket *sym;
+  symbol_t *sym;
   int line;
 
   /* The action is attached to the LHS of a rule. */
   const char *action;
   int action_line;
 
   int line;
 
   /* The action is attached to the LHS of a rule. */
   const char *action;
   int action_line;
 
-  /* The guard is attached to the LHS of a rule. */
-  const char *guard;
-  int guard_line;
-  bucket *ruleprec;
+  symbol_t *ruleprec;
 } symbol_list;
 
 int lineno;
 } symbol_list;
 
 int lineno;
-static symbol_list *grammar;
-static int start_flag;
-static bucket *startval;
-
-/* Nonzero if components of semantic values are used, implying
-   they must be unions.  */
-static int value_components_used;
+static symbol_list *grammar = NULL;
+static int start_flag = 0;
 
 /* Nonzero if %union has been seen.  */
 
 /* Nonzero if %union has been seen.  */
-static int typed;
+static int typed = 0;
 
 /* Incremented for each %left, %right or %nonassoc seen */
 
 /* Incremented for each %left, %right or %nonassoc seen */
-static int lastprec;
-
-static bucket *errtoken = NULL;
-static bucket *undeftoken = NULL;
-static bucket *eoftoken = NULL;
-static bucket *axiom = NULL;
+static int lastprec = 0;
 
 static symbol_list *
 
 static symbol_list *
-symbol_list_new (bucket *sym)
+symbol_list_new (symbol_t *sym)
 {
   symbol_list *res = XMALLOC (symbol_list, 1);
   res->next = NULL;
 {
   symbol_list *res = XMALLOC (symbol_list, 1);
   res->next = NULL;
@@ -80,14 +67,10 @@ symbol_list_new (bucket *sym)
   res->line = lineno;
   res->action = NULL;
   res->action_line = 0;
   res->line = lineno;
   res->action = NULL;
   res->action_line = 0;
-  res->guard = NULL;
-  res->guard_line = 0;
   res->ruleprec = NULL;
   return res;
 }
 
   res->ruleprec = NULL;
   return res;
 }
 
-\f
-
 /*===================\
 | Low level lexing.  |
 \===================*/
 /*===================\
 | Low level lexing.  |
 \===================*/
@@ -165,12 +148,34 @@ get_type_name (int n, symbol_list *rule)
          complain (_("invalid $ value"));
          return NULL;
        }
          complain (_("invalid $ value"));
          return NULL;
        }
-      i++;
+      ++i;
     }
 
   return rp->sym->type_name;
 }
 \f
     }
 
   return rp->sym->type_name;
 }
 \f
+/*------------------------------------------------------------------.
+| Copy the character C to OOUT, and insert quadigraphs when needed. |
+`------------------------------------------------------------------*/
+
+static inline void
+copy_character (struct obstack *oout, int c)
+{
+  switch (c)
+    {
+    case '[':
+      obstack_sgrow (oout, "@<:@");
+      break;
+
+    case ']':
+      obstack_sgrow (oout, "@:>@");
+      break;
+
+    default:
+      obstack_1grow (oout, c);
+    }
+}
+
 /*------------------------------------------------------------.
 | Dump the string from FIN to OOUT if non null.  MATCH is the |
 | delimiter of the string (either ' or ").                    |
 /*------------------------------------------------------------.
 | Dump the string from FIN to OOUT if non null.  MATCH is the |
 | delimiter of the string (either ' or ").                    |
@@ -198,17 +203,17 @@ copy_string2 (FILE *fin, struct obstack *oout, int match, int store)
          continue;
        }
 
          continue;
        }
 
-      obstack_1grow (oout, c);
+      copy_character (oout, c);
 
       if (c == '\\')
        {
          c = getc (fin);
          if (c == EOF)
            fatal (_("unterminated string at end of file"));
 
       if (c == '\\')
        {
          c = getc (fin);
          if (c == EOF)
            fatal (_("unterminated string at end of file"));
-         obstack_1grow (oout, c);
+         copy_character (oout, c);
 
          if (c == '\n')
 
          if (c == '\n')
-           lineno++;
+           ++lineno;
        }
 
       c = getc (fin);
        }
 
       c = getc (fin);
@@ -291,7 +296,7 @@ copy_comment (FILE *fin, struct obstack *oout)
        }
       else if (c == '\n')
        {
        }
       else if (c == '\n')
        {
-         lineno++;
+         ++lineno;
          obstack_1grow (oout, c);
          if (cplus_comment)
            ended = 1;
          obstack_1grow (oout, c);
          if (cplus_comment)
            ended = 1;
@@ -302,30 +307,29 @@ copy_comment (FILE *fin, struct obstack *oout)
        fatal (_("unterminated comment"));
       else
        {
        fatal (_("unterminated comment"));
       else
        {
-         obstack_1grow (oout, c);
+         copy_character (oout, c);
          c = getc (fin);
        }
     }
 }
 
 
          c = getc (fin);
        }
     }
 }
 
 
-/*-----------------------------------------------------------------.
-| 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   |
-| respect to the top of the stack.                                 |
-`-----------------------------------------------------------------*/
+/*-------------------------------------------------------------------.
+| FIN is pointing to a location (i.e., a `@').  Output to OOUT a     |
+| reference to this location. RULE_LENGTH is the number of values in |
+| the current rule so far, which says where to find `$0' with        |
+| respect to the top of the stack.                                   |
+`-------------------------------------------------------------------*/
 
 static inline void
 
 static inline void
-copy_at (FILE *fin, struct obstack *oout, int stack_offset)
+copy_at (FILE *fin, struct obstack *oout, int rule_length)
 {
 {
-  int c;
+  int c = getc (fin);
+  locations_flag = 1;
 
 
-  c = getc (fin);
   if (c == '$')
     {
   if (c == '$')
     {
-      obstack_sgrow (oout, "yyloc");
-      locations_flag = 1;
+      obstack_sgrow (oout, "]b4_lhs_location[");
     }
   else if (isdigit (c) || c == '-')
     {
     }
   else if (isdigit (c) || c == '-')
     {
@@ -333,16 +337,11 @@ copy_at (FILE *fin, struct obstack *oout, int stack_offset)
 
       ungetc (c, fin);
       n = read_signed_integer (fin);
 
       ungetc (c, fin);
       n = read_signed_integer (fin);
-      if (n > stack_offset)
+      if (n > rule_length)
        complain (_("invalid value: %s%d"), "@", n);
       else
        complain (_("invalid value: %s%d"), "@", n);
       else
-       {
-         /* Offset is always 0 if parser has already popped the stack
-            pointer.  */
-         obstack_fgrow1 (oout, "yylsp[%d]",
-                         n - (semantic_parser ? 0 : stack_offset));
-         locations_flag = 1;
-       }
+       obstack_fgrow2 (oout, "]b4_rhs_location([%d], [%d])[",
+                       rule_length, n);
     }
   else
     {
     }
   else
     {
@@ -353,19 +352,19 @@ copy_at (FILE *fin, struct obstack *oout, int stack_offset)
 }
 
 
 }
 
 
-/*-------------------------------------------------------------------.
-| FIN is pointing to a wannabee semantic value (i.e., a `$').        |
-|                                                                    |
-| Possible inputs: $[<TYPENAME>]($|integer)                          |
-|                                                                    |
-| Output to OOUT a reference to this semantic value. STACK_OFFSET is |
-| the number of values in the current rule so far, which says where  |
-| to find `$0' with respect to the top of the stack.                 |
-`-------------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| FIN is pointing to a wannabee semantic value (i.e., a `$').       |
+|                                                                   |
+| Possible inputs: $[<TYPENAME>]($|integer)                         |
+|                                                                   |
+| Output to OOUT a reference to this semantic value. RULE_LENGTH is |
+| the number of values in the current rule so far, which says where |
+| to find `$0' with respect to the top of the stack.                |
+`------------------------------------------------------------------*/
 
 static inline void
 copy_dollar (FILE *fin, struct obstack *oout,
 
 static inline void
 copy_dollar (FILE *fin, struct obstack *oout,
-            symbol_list *rule, int stack_offset)
+            symbol_list *rule, int rule_length)
 {
   int c = getc (fin);
   const char *type_name = NULL;
 {
   int c = getc (fin);
   const char *type_name = NULL;
@@ -375,21 +374,20 @@ copy_dollar (FILE *fin, struct obstack *oout,
     {
       read_type_name (fin);
       type_name = token_buffer;
     {
       read_type_name (fin);
       type_name = token_buffer;
-      value_components_used = 1;
       c = getc (fin);
     }
 
   if (c == '$')
     {
       c = getc (fin);
     }
 
   if (c == '$')
     {
-      obstack_sgrow (oout, "yyval");
-
       if (!type_name)
        type_name = get_type_name (0, rule);
       if (!type_name)
        type_name = get_type_name (0, rule);
-      if (type_name)
-       obstack_fgrow1 (oout, ".%s", type_name);
       if (!type_name && typed)
        complain (_("$$ of `%s' has no declared type"),
                  rule->sym->tag);
       if (!type_name && typed)
        complain (_("$$ of `%s' has no declared type"),
                  rule->sym->tag);
+      if (!type_name)
+       type_name = "";
+      obstack_fgrow1 (oout,
+                     "]b4_lhs_value([%s])[", type_name);
     }
   else if (isdigit (c) || c == '-')
     {
     }
   else if (isdigit (c) || c == '-')
     {
@@ -397,23 +395,19 @@ copy_dollar (FILE *fin, struct obstack *oout,
       ungetc (c, fin);
       n = read_signed_integer (fin);
 
       ungetc (c, fin);
       n = read_signed_integer (fin);
 
-      if (n > stack_offset)
+      if (n > rule_length)
        complain (_("invalid value: %s%d"), "$", n);
       else
        {
          if (!type_name && n > 0)
            type_name = get_type_name (n, rule);
        complain (_("invalid value: %s%d"), "$", n);
       else
        {
          if (!type_name && n > 0)
            type_name = get_type_name (n, rule);
-
-         /* Offset is always 0 if parser has already popped the stack
-            pointer.  */
-         obstack_fgrow1 (oout, "yyvsp[%d]",
-                         n - (semantic_parser ? 0 : stack_offset));
-
-         if (type_name)
-           obstack_fgrow1 (oout, ".%s", type_name);
          if (!type_name && typed)
            complain (_("$%d of `%s' has no declared type"),
                      n, rule->sym->tag);
          if (!type_name && typed)
            complain (_("$%d of `%s' has no declared type"),
                      n, rule->sym->tag);
+         if (!type_name)
+           type_name = "";
+         obstack_fgrow3 (oout, "]b4_rhs_value([%d], [%d], [%s])[",
+                         rule_length, n, type_name);
        }
     }
   else
        }
     }
   else
@@ -430,7 +424,7 @@ copy_dollar (FILE *fin, struct obstack *oout,
 `-------------------------------------------------------------------*/
 
 static void
 `-------------------------------------------------------------------*/
 
 static void
-copy_definition (void)
+copy_definition (struct obstack *oout)
 {
   int c;
   /* -1 while reading a character if prev char was %. */
 {
   int c;
   /* -1 while reading a character if prev char was %. */
@@ -438,7 +432,7 @@ copy_definition (void)
 
   if (!no_lines_flag)
     {
 
   if (!no_lines_flag)
     {
-      obstack_fgrow2 (&attrs_obstack, muscle_find ("linef"),
+      obstack_fgrow2 (oout, muscle_find ("linef"),
                      lineno, quotearg_style (c_quoting_style,
                                              muscle_find ("filename")));
     }
                      lineno, quotearg_style (c_quoting_style,
                                              muscle_find ("filename")));
     }
@@ -452,8 +446,8 @@ copy_definition (void)
       switch (c)
        {
        case '\n':
       switch (c)
        {
        case '\n':
-         obstack_1grow (&attrs_obstack, c);
-         lineno++;
+         obstack_1grow (oout, c);
+         ++lineno;
          break;
 
        case '%':
          break;
 
        case '%':
@@ -462,18 +456,18 @@ copy_definition (void)
 
        case '\'':
        case '"':
 
        case '\'':
        case '"':
-         copy_string (finput, &attrs_obstack, c);
+         copy_string (finput, oout, c);
          break;
 
        case '/':
          break;
 
        case '/':
-         copy_comment (finput, &attrs_obstack);
+         copy_comment (finput, oout);
          break;
 
        case EOF:
          fatal ("%s", _("unterminated `%{' definition"));
 
        default:
          break;
 
        case EOF:
          fatal ("%s", _("unterminated `%{' definition"));
 
        default:
-         obstack_1grow (&attrs_obstack, c);
+         copy_character (oout, c);
        }
 
       c = getc (finput);
        }
 
       c = getc (finput);
@@ -482,27 +476,25 @@ copy_definition (void)
        {
          if (c == '}')
            return;
        {
          if (c == '}')
            return;
-         obstack_1grow (&attrs_obstack, '%');
+         obstack_1grow (oout, '%');
        }
       after_percent = 0;
     }
 }
 
 
        }
       after_percent = 0;
     }
 }
 
 
-/*-------------------------------------------------------------------.
-| Parse what comes after %token or %nterm.  For %token, WHAT_IS is   |
-| token_sym and WHAT_IS_NOT is nterm_sym.  For %nterm, the arguments |
-| are reversed.                                                      |
-`-------------------------------------------------------------------*/
+/*------------------------------------------.
+| Parse what comes after %token or %nterm.  |
+`------------------------------------------*/
 
 static void
 
 static void
-parse_token_decl (symbol_class what_is, symbol_class what_is_not)
+parse_token_decl (symbol_class class)
 {
   token_t token = tok_undef;
   char *typename = NULL;
 
   /* The symbol being defined.  */
 {
   token_t token = tok_undef;
   char *typename = NULL;
 
   /* The symbol being defined.  */
-  struct bucket *symbol = NULL;
+  symbol_t *symbol = NULL;
 
   /* After `%token' and `%nterm', any number of symbols maybe be
      defined.  */
 
   /* After `%token' and `%nterm', any number of symbols maybe be
      defined.  */
@@ -518,69 +510,40 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not)
        fatal (_("Premature EOF after %s"), token_buffer);
 
       token = lex ();
        fatal (_("Premature EOF after %s"), token_buffer);
 
       token = lex ();
-      if (token == tok_comma)
+      switch (token)
        {
        {
+       case tok_comma:
          symbol = NULL;
          symbol = NULL;
-         continue;
-       }
-      if (token == tok_typename)
-       {
+         break;
+
+       case tok_typename:
          typename = xstrdup (token_buffer);
          typename = xstrdup (token_buffer);
-         value_components_used = 1;
          symbol = NULL;
          symbol = NULL;
-       }
-      else if (token == tok_identifier && *symval->tag == '\"' && symbol)
-       {
-         if (symval->alias)
-           warn (_("symbol `%s' used more than once as a literal string"),
-                 symval->tag);
-         else if (symbol->alias)
-           warn (_("symbol `%s' given more than one literal string"),
-                 symbol->tag);
+         break;
+
+       case tok_identifier:
+         if (*symval->tag == '\"' && symbol)
+           {
+             symbol_make_alias (symbol, symval, typename);
+             symbol = NULL;
+           }
          else
            {
          else
            {
-             symval->class = token_sym;
-             symval->type_name = typename;
-             symval->user_token_number = symbol->user_token_number;
-             symbol->user_token_number = SALIAS;
-             symval->alias = symbol;
-             symbol->alias = symval;
-             /* symbol and symval combined are only one symbol */
-             nsyms--;
+             symbol = symval;
+             symbol_class_set (symbol, class);
+             if (typename)
+               symbol_type_set (symbol, typename);
            }
            }
-         symbol = NULL;
-       }
-      else if (token == tok_identifier)
-       {
-         int oldclass = symval->class;
-         symbol = symval;
+         break;
 
 
-         if (symbol->class == what_is_not)
-           complain (_("symbol %s redefined"), symbol->tag);
-         symbol->class = what_is;
-         if (what_is == nterm_sym && oldclass != nterm_sym)
-           symbol->value = nvars++;
+       case tok_number:
+         symbol_user_token_number_set (symbol, numval);
+         break;
 
 
-         if (typename)
-           {
-             if (symbol->type_name == NULL)
-               symbol->type_name = typename;
-             else if (strcmp (typename, symbol->type_name) != 0)
-               complain (_("type redeclaration for %s"), symbol->tag);
-           }
-       }
-      else if (symbol && token == tok_number)
-       {
-         symbol->user_token_number = numval;
-         /* User defined EOF token? */
-         if (numval == 0)
-           eoftoken = symbol;
-       }
-      else
-       {
+       default:
          complain (_("`%s' is invalid in %s"),
                    token_buffer,
          complain (_("`%s' is invalid in %s"),
                    token_buffer,
-                   (what_is == token_sym) ? "%token" : "%nterm");
+                   (class == token_sym) ? "%token" : "%nterm");
          skip_to_char ('%');
        }
     }
          skip_to_char ('%');
        }
     }
@@ -602,7 +565,7 @@ parse_start_decl (void)
   else
     {
       start_flag = 1;
   else
     {
       start_flag = 1;
-      startval = symval;
+      startsymbol = symval;
     }
 }
 
     }
 }
 
@@ -639,17 +602,12 @@ parse_type_decl (void)
 
       switch (t)
        {
 
       switch (t)
        {
-
        case tok_comma:
        case tok_semicolon:
          break;
 
        case tok_identifier:
        case tok_comma:
        case tok_semicolon:
          break;
 
        case tok_identifier:
-         if (symval->type_name == NULL)
-           symval->type_name = name;
-         else if (strcmp (name, symval->type_name) != 0)
-           complain (_("type redeclaration for %s"), symval->tag);
-
+         symbol_type_set (symval, name);
          break;
 
        default:
          break;
 
        default:
@@ -673,7 +631,8 @@ parse_assoc_decl (associativity assoc)
   char *name = NULL;
   int prev = 0;
 
   char *name = NULL;
   int prev = 0;
 
-  lastprec++;                  /* Assign a new precedence level, never 0.  */
+  /* Assign a new precedence level, never 0.  */
+  ++lastprec;
 
   for (;;)
     {
 
   for (;;)
     {
@@ -697,32 +656,22 @@ parse_assoc_decl (associativity assoc)
          break;
 
        case tok_identifier:
          break;
 
        case tok_identifier:
-         if (symval->prec != 0)
-           complain (_("redefining precedence of %s"), symval->tag);
-         symval->prec = lastprec;
-         symval->assoc = assoc;
-         if (symval->class == nterm_sym)
-           complain (_("symbol %s redefined"), symval->tag);
-         symval->class = token_sym;
+         symbol_class_set (symval, token_sym);
+         symbol_precedence_set (symval, lastprec, assoc);
          if (name)
          if (name)
-           {                   /* record the type, if one is specified */
-             if (symval->type_name == NULL)
-               symval->type_name = name;
-             else if (strcmp (name, symval->type_name) != 0)
-               complain (_("type redeclaration for %s"), symval->tag);
-           }
+           symbol_type_set (symval, name);
          break;
 
        case tok_number:
          if (prev == tok_identifier)
            {
          break;
 
        case tok_number:
          if (prev == tok_identifier)
            {
-             symval->user_token_number = numval;
+             symbol_user_token_number_set (symval, numval);
            }
          else
            {
            }
          else
            {
-             complain (_
-                       ("invalid text (%s) - number should be after identifier"),
-token_buffer);
+             complain
+               (_("invalid text (%s) - number should be after identifier"),
+                token_buffer);
              skip_to_char ('%');
            }
          break;
              skip_to_char ('%');
            }
          break;
@@ -759,6 +708,7 @@ parse_union_decl (void)
 
   typed = 1;
 
 
   typed = 1;
 
+  MUSCLE_INSERT_INT ("stype_line", lineno);
   obstack_init (&union_obstack);
   obstack_sgrow (&union_obstack, "union");
 
   obstack_init (&union_obstack);
   obstack_sgrow (&union_obstack, "union");
 
@@ -773,7 +723,7 @@ parse_union_decl (void)
       switch (c)
        {
        case '\n':
       switch (c)
        {
        case '\n':
-         lineno++;
+         ++lineno;
          break;
 
        case '/':
          break;
 
        case '/':
@@ -781,7 +731,7 @@ parse_union_decl (void)
          break;
 
        case '{':
          break;
 
        case '{':
-         count++;
+         ++count;
          break;
 
        case '}':
          break;
 
        case '}':
@@ -822,84 +772,6 @@ parse_expect_decl (void)
 }
 
 
 }
 
 
-/*-------------------------------------------------------------------.
-| Parse what comes after %thong.  the full syntax is                 |
-|                                                                    |
-|                %thong <type> token number literal                  |
-|                                                                    |
-| the <type> or number may be omitted.  The number specifies the     |
-| user_token_number.                                                 |
-|                                                                    |
-| Two symbols are entered in the table, one for the token symbol and |
-| one for the literal.  Both are given the <type>, if any, from the  |
-| declaration.  The ->user_token_number of the first is SALIAS and   |
-| the ->user_token_number of the second is set to the number, if     |
-| any, from the declaration.  The two symbols are linked via         |
-| pointers in their ->alias fields.                                  |
-|                                                                    |
-| During OUTPUT_DEFINES_TABLE, the symbol is reported thereafter,    |
-| only the literal string is retained it is the literal string that  |
-| is output to yytname                                               |
-`-------------------------------------------------------------------*/
-
-static void
-parse_thong_decl (void)
-{
-  token_t token;
-  struct bucket *symbol;
-  char *typename = 0;
-  int usrtoknum = SUNDEF;
-
-  token = lex ();              /* fetch typename or first token */
-  if (token == tok_typename)
-    {
-      typename = xstrdup (token_buffer);
-      value_components_used = 1;
-      token = lex ();          /* fetch first token */
-    }
-
-  /* process first token */
-
-  if (token != tok_identifier)
-    {
-      complain (_("unrecognized item %s, expected an identifier"),
-               token_buffer);
-      skip_to_char ('%');
-      return;
-    }
-  symval->class = token_sym;
-  symval->type_name = typename;
-  symval->user_token_number = SALIAS;
-  symbol = symval;
-
-  token = lex ();              /* get number or literal string */
-
-  if (token == tok_number)
-    {
-      usrtoknum = numval;
-      token = lex ();          /* okay, did number, now get literal */
-    }
-
-  /* process literal string token */
-
-  if (token != tok_identifier || *symval->tag != '\"')
-    {
-      complain (_("expected string constant instead of %s"), token_buffer);
-      skip_to_char ('%');
-      return;
-    }
-  symval->class = token_sym;
-  symval->type_name = typename;
-  symval->user_token_number = usrtoknum;
-
-  symval->alias = symbol;
-  symbol->alias = symval;
-
-  /* symbol and symval combined are only one symbol.  */
-  nsyms--;
-}
-
-
 static void
 parse_muscle_decl (void)
 {
 static void
 parse_muscle_decl (void)
 {
@@ -995,7 +867,7 @@ parse_skel_decl (void)
 /*----------------------------------------------------------------.
 | 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 `%{ ... %}'  |
-| groups to ATTRS_OBSTACK.                                        |
+| groups to PRE_PROLOGUE_OBSTACK or POST_PROLOGUE_OBSTACK.        |
 `----------------------------------------------------------------*/
 
 static void
 `----------------------------------------------------------------*/
 
 static void
@@ -1015,15 +887,18 @@ read_declarations (void)
              return;
 
            case tok_percent_left_curly:
              return;
 
            case tok_percent_left_curly:
-             copy_definition ();
+              if (!typed)
+               copy_definition (&pre_prologue_obstack);
+             else
+               copy_definition (&post_prologue_obstack);
              break;
 
            case tok_token:
              break;
 
            case tok_token:
-             parse_token_decl (token_sym, nterm_sym);
+             parse_token_decl (token_sym);
              break;
 
            case tok_nterm:
              break;
 
            case tok_nterm:
-             parse_token_decl (nterm_sym, token_sym);
+             parse_token_decl (nterm_sym);
              break;
 
            case tok_type:
              break;
 
            case tok_type:
@@ -1042,10 +917,6 @@ read_declarations (void)
              parse_expect_decl ();
              break;
 
              parse_expect_decl ();
              break;
 
-           case tok_thong:
-             parse_thong_decl ();
-             break;
-
            case tok_left:
              parse_assoc_decl (left_assoc);
              break;
            case tok_left:
              parse_assoc_decl (left_assoc);
              break;
@@ -1072,7 +943,7 @@ read_declarations (void)
            case tok_stropt:
            case tok_intopt:
            case tok_obsolete:
            case tok_stropt:
            case tok_intopt:
            case tok_obsolete:
-             abort ();
+             assert (0);
              break;
 
            case tok_illegal:
              break;
 
            case tok_illegal:
@@ -1093,37 +964,37 @@ read_declarations (void)
     }
 }
 \f
     }
 }
 \f
-/*-------------------------------------------------------------------.
-| Assuming that a `{' has just been seen, copy everything up to the  |
-| matching `}' into the actions file.  STACK_OFFSET is the number of |
-| values in the current rule so far, which says where to find `$0'   |
-| with respect to the top of the stack.                              |
-|                                                                    |
-| This routine is used both for actions and guards.  Only            |
-| ACTION_OBSTACK is used, but this is fine, since we use only        |
-| pointers to relevant portions inside this obstack.                 |
-`-------------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| Assuming that a `{' has just been seen, copy everything up to the |
+| matching `}' into ACTION_OBSTACK.                                 |
+|                                                                   |
+| RULE_LENGTH is the number of values in the current rule so far,   |
+| which says where to find `$0' with respect to the top of the      |
+| stack.  It is not the same as the rule->length in the case of mid |
+| rule actions.                                                     |
+|                                                                   |
+| This routine is used for actions.                                 |
+`------------------------------------------------------------------*/
 
 static void
 
 static void
-parse_braces (symbol_list *rule, int stack_offset)
+parse_action (symbol_list *rule, int rule_length)
 {
 {
-  int c;
-  int count;
-
-  count = 1;
+  int count = 1;
+  rule->action_line = lineno;
   while (count > 0)
     {
   while (count > 0)
     {
+      int c;
       while ((c = getc (finput)) != '}')
        switch (c)
          {
          case '\n':
       while ((c = getc (finput)) != '}')
        switch (c)
          {
          case '\n':
-           obstack_1grow (&action_obstack, c);
-           lineno++;
+           copy_character (&action_obstack, c);
+           ++lineno;
            break;
 
          case '{':
            break;
 
          case '{':
-           obstack_1grow (&action_obstack, c);
-           count++;
+           copy_character (&action_obstack, c);
+           ++count;
            break;
 
          case '\'':
            break;
 
          case '\'':
@@ -1136,54 +1007,29 @@ parse_braces (symbol_list *rule, int stack_offset)
            break;
 
          case '$':
            break;
 
          case '$':
-           copy_dollar (finput, &action_obstack,
-                        rule, stack_offset);
+           copy_dollar (finput, &action_obstack, rule, rule_length);
            break;
 
          case '@':
            break;
 
          case '@':
-           copy_at (finput, &action_obstack,
-                    stack_offset);
+           copy_at (finput, &action_obstack, rule_length);
            break;
 
          case EOF:
            fatal (_("unmatched %s"), "`{'");
 
          default:
            break;
 
          case EOF:
            fatal (_("unmatched %s"), "`{'");
 
          default:
-           obstack_1grow (&action_obstack, c);
+           copy_character (&action_obstack, c);
          }
 
       /* Above loop exits when C is '}'.  */
       if (--count)
          }
 
       /* Above loop exits when C is '}'.  */
       if (--count)
-       {
-         obstack_1grow (&action_obstack, c);
-         c = getc (finput);
-       }
+       copy_character (&action_obstack, c);
     }
 
   obstack_1grow (&action_obstack, '\0');
     }
 
   obstack_1grow (&action_obstack, '\0');
-}
-
-
-static void
-parse_action (symbol_list *rule, int stack_offset)
-{
-  rule->action_line = lineno;
-  parse_braces (rule, stack_offset);
   rule->action = obstack_finish (&action_obstack);
 }
 
   rule->action = obstack_finish (&action_obstack);
 }
 
-
-static void
-parse_guard (symbol_list *rule, int stack_offset)
-{
-  token_t t = lex ();
-  if (t != tok_left_curly)
-    complain (_("invalid %s declaration"), "%guard");
-  rule->guard_line = lineno;
-  parse_braces (rule, stack_offset);
-  rule->guard = obstack_finish (&action_obstack);
-}
-
 \f
 
 /*-------------------------------------------------------------------.
 \f
 
 /*-------------------------------------------------------------------.
@@ -1191,20 +1037,20 @@ parse_guard (symbol_list *rule, int stack_offset)
 | with the user's names.                                             |
 `-------------------------------------------------------------------*/
 
 | with the user's names.                                             |
 `-------------------------------------------------------------------*/
 
-static bucket *
+static symbol_t *
 gensym (void)
 {
   /* Incremented for each generated symbol */
   static int gensym_count = 0;
   static char buf[256];
 
 gensym (void)
 {
   /* Incremented for each generated symbol */
   static int gensym_count = 0;
   static char buf[256];
 
-  bucket *sym;
+  symbol_t *sym;
 
   sprintf (buf, "@%d", ++gensym_count);
   token_buffer = buf;
   sym = getsym (token_buffer);
   sym->class = nterm_sym;
 
   sprintf (buf, "@%d", ++gensym_count);
   token_buffer = buf;
   sym = getsym (token_buffer);
   sym->class = nterm_sym;
-  sym->value = nvars++;
+  sym->number = nvars++;
   return sym;
 }
 \f
   return sym;
 }
 \f
@@ -1215,8 +1061,8 @@ gensym (void)
 | null pointer instead of a symbol to terminate the rule.  The next  |
 | symbol is the lhs of the following rule.                           |
 |                                                                    |
 | null pointer instead of a symbol to terminate the rule.  The next  |
 | symbol is the lhs of the following rule.                           |
 |                                                                    |
-| All guards and actions are copied out to the appropriate files,    |
-| labelled by the rule number they apply to.                         |
+| All actions are copied out, labelled by the rule number they apply |
+| to.                                                                |
 |                                                                    |
 | Bison used to allow some %directives in the rules sections, but    |
 | this is no longer consider appropriate: (i) the documented grammar |
 |                                                                    |
 | Bison used to allow some %directives in the rules sections, but    |
 | this is no longer consider appropriate: (i) the documented grammar |
@@ -1230,10 +1076,9 @@ static void
 readgram (void)
 {
   token_t t;
 readgram (void)
 {
   token_t t;
-  bucket *lhs = NULL;
+  symbol_t *lhs = NULL;
   symbol_list *p = NULL;
   symbol_list *p1 = NULL;
   symbol_list *p = NULL;
   symbol_list *p1 = NULL;
-  bucket *bp;
 
   /* Points to first symbol_list of current rule. its symbol is the
      lhs of the rule.  */
 
   /* Points to first symbol_list of current rule. its symbol is the
      lhs of the rule.  */
@@ -1250,7 +1095,7 @@ readgram (void)
        /* Number of symbols in rhs of this rule so far */
        int rulelength = 0;
        int xactions = 0;       /* JF for error checking */
        /* Number of symbols in rhs of this rule so far */
        int rulelength = 0;
        int xactions = 0;       /* JF for error checking */
-       bucket *first_rhs = 0;
+       symbol_t *first_rhs = 0;
 
        if (t == tok_identifier)
          {
 
        if (t == tok_identifier)
          {
@@ -1258,7 +1103,7 @@ readgram (void)
 
            if (!start_flag)
              {
 
            if (!start_flag)
              {
-               startval = lhs;
+               startsymbol = lhs;
                start_flag = 1;
              }
 
                start_flag = 1;
              }
 
@@ -1277,8 +1122,8 @@ readgram (void)
          }
        /* start a new rule and record its lhs.  */
 
          }
        /* start a new rule and record its lhs.  */
 
-       nrules++;
-       nitems++;
+       ++nrules;
+       ++nritems;
 
        p = symbol_list_new (lhs);
 
 
        p = symbol_list_new (lhs);
 
@@ -1296,8 +1141,8 @@ readgram (void)
        if (lhs->class == unknown_sym)
          {
            lhs->class = nterm_sym;
        if (lhs->class == unknown_sym)
          {
            lhs->class = nterm_sym;
-           lhs->value = nvars;
-           nvars++;
+           lhs->number = nvars;
+           ++nvars;
          }
        else if (lhs->class == token_sym)
          complain (_("rule given for %s, which is a token"), lhs->tag);
          }
        else if (lhs->class == token_sym)
          complain (_("rule given for %s, which is a token"), lhs->tag);
@@ -1321,7 +1166,7 @@ readgram (void)
               If one does, exit this rule now.  */
            if (t == tok_identifier)
              {
               If one does, exit this rule now.  */
            if (t == tok_identifier)
              {
-               bucket *ssave;
+               symbol_t *ssave;
                token_t t1;
 
                ssave = symval;
                token_t t1;
 
                ssave = symval;
@@ -1329,7 +1174,10 @@ readgram (void)
                unlex (t1);
                symval = ssave;
                if (t1 == tok_colon)
                unlex (t1);
                symval = ssave;
                if (t1 == tok_colon)
-                 break;
+                 {
+                   warn (_("previous rule lacks an ending `;'"));
+                   break;
+                 }
 
                if (!first_rhs) /* JF */
                  first_rhs = symval;
 
                if (!first_rhs) /* JF */
                  first_rhs = symval;
@@ -1347,16 +1195,21 @@ readgram (void)
                   inserting the new rule before it.  */
 
                /* Make a dummy nonterminal, a gensym.  */
                   inserting the new rule before it.  */
 
                /* Make a dummy nonterminal, a gensym.  */
-               bucket *sdummy = gensym ();
+               symbol_t *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;
+               ++nritems;
                p = symbol_list_new (sdummy);
                /* Attach its lineno to that of the host rule. */
                p->line = crule->line;
                p = symbol_list_new (sdummy);
                /* Attach its lineno to that of the host rule. */
                p->line = crule->line;
+               /* Move the action from the host rule to this one. */
+               p->action = crule->action;
+               p->action_line = crule->action_line;
+               crule->action = NULL;
+
                if (crule1)
                  crule1->next = p;
                else
                if (crule1)
                  crule1->next = p;
                else
@@ -1369,7 +1222,7 @@ readgram (void)
 
                /* Insert the dummy generated by that rule into this
                   rule.  */
 
                /* Insert the dummy generated by that rule into this
                   rule.  */
-               nitems++;
+               ++nritems;
                p = symbol_list_new (sdummy);
                p1->next = p;
                p1 = p;
                p = symbol_list_new (sdummy);
                p1->next = p;
                p1 = p;
@@ -1379,7 +1232,7 @@ readgram (void)
 
            if (t == tok_identifier)
              {
 
            if (t == tok_identifier)
              {
-               nitems++;
+               ++nritems;
                p = symbol_list_new (symval);
                p1->next = p;
                p1 = p;
                p = symbol_list_new (symval);
                p1->next = p;
                p1 = p;
@@ -1388,9 +1241,9 @@ readgram (void)
              {
                parse_action (crule, rulelength);
                action_flag = 1;
              {
                parse_action (crule, rulelength);
                action_flag = 1;
-               xactions++;     /* JF */
+               ++xactions;     /* JF */
              }
              }
-           rulelength++;
+           ++rulelength;
          }                     /* 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  */
@@ -1406,15 +1259,6 @@ readgram (void)
            t = lex ();
          }
 
            t = lex ();
          }
 
-       if (t == tok_guard)
-         {
-           if (!semantic_parser)
-             complain (_("%%guard present but %%semantic_parser not specified"));
-
-           parse_guard (crule, rulelength);
-           t = lex ();
-         }
-
        if (t == tok_left_curly)
          {
            /* This case never occurs -wjh */
        if (t == tok_left_curly)
          {
            /* This case never occurs -wjh */
@@ -1422,7 +1266,7 @@ readgram (void)
              complain (_("two actions at end of one rule"));
            parse_action (crule, rulelength);
            action_flag = 1;
              complain (_("two actions at end of one rule"));
            parse_action (crule, rulelength);
            action_flag = 1;
-           xactions++; /* -wjh */
+           ++xactions; /* -wjh */
            t = lex ();
          }
        /* If $$ is being set in default way, report if any type
            t = lex ();
          }
        /* If $$ is being set in default way, report if any type
@@ -1440,6 +1284,8 @@ readgram (void)
        /* Warn if there is no default for $$ but we need one.  */
        else if (!xactions && !first_rhs && lhs->type_name != 0)
          complain (_("empty rule for typed nonterminal, and no action"));
        /* Warn if there is no default for $$ but we need one.  */
        else if (!xactions && !first_rhs && lhs->type_name != 0)
          complain (_("empty rule for typed nonterminal, and no action"));
+       if (t == tok_two_percents || t == tok_eof)
+         warn (_("previous rule lacks an ending `;'"));
        if (t == tok_semicolon)
          t = lex ();
       }
        if (t == tok_semicolon)
          t = lex ();
       }
@@ -1455,16 +1301,7 @@ readgram (void)
     fatal (_("no rules in the input grammar"));
 
   /* Report any undefined symbols and consider them nonterminals.  */
     fatal (_("no rules in the input grammar"));
 
   /* Report any undefined symbols and consider them nonterminals.  */
-
-  for (bp = firstsymbol; bp; bp = bp->next)
-    if (bp->class == unknown_sym)
-      {
-       complain (_
-                 ("symbol %s is used, but is not defined as a token and has no rules"),
-                 bp->tag);
-       bp->class = nterm_sym;
-       bp->value = nvars++;
-      }
+  symbols_check_defined ();
 
   /* Insert the initial rule, which line is that of the first rule
      (not that of the start symbol):
 
   /* Insert the initial rule, which line is that of the first rule
      (not that of the start symbol):
@@ -1472,20 +1309,19 @@ readgram (void)
      axiom: %start EOF.  */
   p = symbol_list_new (axiom);
   p->line = grammar->line;
      axiom: %start EOF.  */
   p = symbol_list_new (axiom);
   p->line = grammar->line;
-  p->next = symbol_list_new (startval);
+  p->next = symbol_list_new (startsymbol);
   p->next->next = symbol_list_new (eoftoken);
   p->next->next->next = symbol_list_new (NULL);
   p->next->next->next->next = grammar;
   nrules += 1;
   p->next->next = symbol_list_new (eoftoken);
   p->next->next->next = symbol_list_new (NULL);
   p->next->next->next->next = grammar;
   nrules += 1;
-  nitems += 3;
+  nritems += 3;
   grammar = p;
   grammar = p;
-  startval = axiom;
 
 
-  if (nsyms > MAXSHORT)
+  if (nsyms > SHRT_MAX)
     fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
     fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
-          MAXSHORT);
+          SHRT_MAX);
 
 
-  ntokens = nsyms - nvars;
+  assert (nsyms == ntokens + nvars);
 }
 
 /* At the end of the grammar file, some C source code must
 }
 
 /* At the end of the grammar file, some C source code must
@@ -1494,7 +1330,7 @@ readgram (void)
 static void
 read_additionnal_code (void)
 {
 static void
 read_additionnal_code (void)
 {
-  char c;
+  int c;
   struct obstack el_obstack;
 
   obstack_init (&el_obstack);
   struct obstack el_obstack;
 
   obstack_init (&el_obstack);
@@ -1507,220 +1343,27 @@ read_additionnal_code (void)
     }
 
   while ((c = getc (finput)) != EOF)
     }
 
   while ((c = getc (finput)) != EOF)
-    obstack_1grow (&el_obstack, c);
+    copy_character (&el_obstack, c);
 
   obstack_1grow (&el_obstack, 0);
   muscle_insert ("epilogue", obstack_finish (&el_obstack));
 }
 
 \f
 
   obstack_1grow (&el_obstack, 0);
   muscle_insert ("epilogue", obstack_finish (&el_obstack));
 }
 
 \f
-/*------------------------------------------------------------------.
-| 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"),
-                 symbols[token_translations[bp->user_token_number]]->tag,
-                 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 SYMBOL_TABLE, TAGS of symbols.        |
-`----------------------------------------------------------------*/
-
-static void
-packsymbols (void)
-{
-  bucket *bp = NULL;
-  int tokno = 1;
-  int last_user_token_number;
-
-  symbols = XCALLOC (bucket *, nsyms);
-
-  max_user_token_number = 256;
-  last_user_token_number = 256;
-
-  for (bp = firstsymbol; bp; bp = bp->next)
-    {
-      if (bp->class == nterm_sym)
-       {
-         bp->value += ntokens;
-       }
-      else if (bp->alias)
-       {
-         /* This symbol and its alias are a single token defn.
-            Allocate a tokno, and assign to both check agreement of
-            prec and assoc fields and make both the same */
-         if (bp->value == -1)
-           {
-             if (bp == eoftoken || bp->alias == eoftoken)
-               bp->value = bp->alias->value = 0;
-             else
-               {
-                 bp->value = bp->alias->value = tokno++;
-               }
-           }
-
-         if (bp->prec != bp->alias->prec)
-           {
-             if (bp->prec != 0 && bp->alias->prec != 0
-                 && bp->user_token_number == SALIAS)
-               complain (_("conflicting precedences for %s and %s"),
-                         bp->tag, bp->alias->tag);
-             if (bp->prec != 0)
-               bp->alias->prec = bp->prec;
-             else
-               bp->prec = bp->alias->prec;
-           }
-
-         if (bp->assoc != bp->alias->assoc)
-           {
-             if (bp->assoc != 0 && bp->alias->assoc != 0
-                 && bp->user_token_number == SALIAS)
-               complain (_("conflicting assoc values for %s and %s"),
-                         bp->tag, bp->alias->tag);
-             if (bp->assoc != 0)
-               bp->alias->assoc = bp->assoc;
-             else
-               bp->assoc = bp->alias->assoc;
-           }
-
-         /* Do not do processing below for SALIASs.  */
-         if (bp->user_token_number == SALIAS)
-           continue;
-
-       }
-      else /* bp->class == token_sym */
-       {
-         if (bp == eoftoken)
-           bp->value = 0;
-         else
-           bp->value = tokno++;
-       }
-
-      if (bp->class == token_sym)
-       {
-         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;
-       }
-
-      symbols[bp->value] = bp;
-    }
-
-  token_translations_init ();
-
-  error_token_number = errtoken->value;
-
-  if (startval->class == unknown_sym)
-    fatal (_("the start symbol %s is undefined"), startval->tag);
-  else if (startval->class == token_sym)
-    fatal (_("the start symbol %s is a token"), startval->tag);
-
-  start_symbol = startval->value;
-}
-
-
-/*---------------------------------------------------------------.
-| Save the definition of token names in the `TOKENDEFS' muscle.  |
-`---------------------------------------------------------------*/
-
-static void
-symbols_save (void)
-{
-  struct obstack tokendefs;
-  bucket *bp;
-  obstack_init (&tokendefs);
-
-  for (bp = firstsymbol; bp; bp = bp->next)
-    {
-      char *symbol = bp->tag;                /* get symbol */
-
-      if (bp->value >= ntokens)
-       continue;
-      if (bp->user_token_number == SALIAS)
-       continue;
-      if ('\'' == *symbol)
-       continue;               /* skip literal character */
-      if (bp == errtoken)
-       continue;               /* skip error token */
-      if ('\"' == *symbol)
-       {
-         /* use literal string only if given a symbol with an alias */
-         if (bp->alias)
-           symbol = bp->alias->tag;
-         else
-           continue;
-       }
-
-      /* Don't #define nonliteral tokens whose names contain periods.  */
-      if (strchr (symbol, '.'))
-       continue;
-
-      obstack_fgrow2 (&tokendefs, "# define %s\t%d\n",
-                     symbol, bp->user_token_number);
-      if (semantic_parser)
-       /* FIXME: This is probably wrong, and should be just as
-          above. --akim.  */
-       obstack_fgrow2 (&tokendefs, "# define T%s\t%d\n", symbol, bp->value);
-    }
-
-  obstack_1grow (&tokendefs, 0);
-  muscle_insert ("tokendef", xstrdup (obstack_finish (&tokendefs)));
-  obstack_free (&tokendefs, NULL);
-}
-
-
 /*---------------------------------------------------------------.
 | Convert the rules into the representation using RRHS, RLHS and |
 /*---------------------------------------------------------------.
 | Convert the rules into the representation using RRHS, RLHS and |
-| RITEMS.                                                        |
+| RITEM                                                        |
 `---------------------------------------------------------------*/
 
 static void
 packgram (void)
 {
 `---------------------------------------------------------------*/
 
 static void
 packgram (void)
 {
-  int itemno;
+  unsigned int itemno;
   int ruleno;
   symbol_list *p;
 
   int ruleno;
   symbol_list *p;
 
-  /* We use short to index items.  */
-  if (nitems >= MAXSHORT)
-    fatal (_("too many items (max %d)"), MAXSHORT);
-
-  ritem = XCALLOC (short, nitems + 1);
-  rule_table = XCALLOC (rule_t, nrules) - 1;
+  ritem = XCALLOC (item_number_t, nritems);
+  rules = XCALLOC (rule_t, nrules) - 1;
 
   itemno = 0;
   ruleno = 1;
 
   itemno = 0;
   ruleno = 1;
@@ -1728,27 +1371,26 @@ packgram (void)
   p = grammar;
   while (p)
     {
   p = grammar;
   while (p)
     {
-      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;
-      rule_table[ruleno].action = p->action;
-      rule_table[ruleno].action_line = p->action_line;
-      rule_table[ruleno].guard = p->guard;
-      rule_table[ruleno].guard_line = p->guard_line;
+      symbol_t *ruleprec = p->ruleprec;
+      rules[ruleno].user_number = ruleno;
+      rules[ruleno].number = ruleno;
+      rules[ruleno].lhs = p->sym;
+      rules[ruleno].rhs = ritem + itemno;
+      rules[ruleno].line = p->line;
+      rules[ruleno].useful = TRUE;
+      rules[ruleno].action = p->action;
+      rules[ruleno].action_line = p->action_line;
 
       p = p->next;
       while (p && p->sym)
        {
 
       p = p->next;
       while (p && p->sym)
        {
-         ritem[itemno++] = p->sym->value;
+         /* item_number_t = symbol_number_t.
+            But the former needs to contain more: negative rule numbers. */
+         ritem[itemno++] = symbol_number_as_item_number (p->sym->number);
          /* A rule gets by default the precedence and associativity
             of the last token in it.  */
          if (p->sym->class == token_sym)
          /* A rule gets by default the precedence and associativity
             of the last token in it.  */
          if (p->sym->class == token_sym)
-           {
-             rule_table[ruleno].prec = p->sym->prec;
-             rule_table[ruleno].assoc = p->sym->assoc;
-           }
+           rules[ruleno].prec = p->sym;
          if (p)
            p = p->next;
        }
          if (p)
            p = p->next;
        }
@@ -1757,53 +1399,32 @@ packgram (void)
          the specified symbol's precedence replaces the default.  */
       if (ruleprec)
        {
          the specified symbol's precedence replaces the default.  */
       if (ruleprec)
        {
-         rule_table[ruleno].prec = ruleprec->prec;
-         rule_table[ruleno].assoc = ruleprec->assoc;
-         rule_table[ruleno].precsym = ruleprec->value;
+         rules[ruleno].precsym = ruleprec;
+         rules[ruleno].prec = ruleprec;
        }
        }
-
       ritem[itemno++] = -ruleno;
       ritem[itemno++] = -ruleno;
-      ruleno++;
+      ++ruleno;
 
       if (p)
        p = p->next;
     }
 
 
       if (p)
        p = p->next;
     }
 
-  ritem[itemno] = 0;
-  nritems = itemno;
-  assert (nritems == nitems);
+  assert (itemno == nritems);
 
   if (trace_flag)
     ritem_print (stderr);
 }
 \f
 
   if (trace_flag)
     ritem_print (stderr);
 }
 \f
-/*-------------------------------------------------------------------.
-| Read in the grammar specification and record it in the format      |
-| described in gram.h.  All guards are copied into the GUARD_OBSTACK |
-| and all actions into ACTION_OBSTACK, in each case forming the body |
-| of a C function (YYGUARD or YYACTION) which contains a switch      |
-| statement to decide which guard or action to execute.              |
-`-------------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| Read in the grammar specification and record it in the format     |
+| described in gram.h.  All actions are copied into ACTION_OBSTACK, |
+| in each case forming the body of a C function (YYACTION) which    |
+| contains a switch statement to decide which action to execute.    |
+`------------------------------------------------------------------*/
 
 void
 reader (void)
 {
 
 void
 reader (void)
 {
-  start_flag = 0;
-  startval = NULL;             /* start symbol not specified yet. */
-
-  nsyms = 0;
-  nvars = 0;
-  nrules = 0;
-  nitems = 0;
-
-  typed = 0;
-  lastprec = 0;
-
-  semantic_parser = 0;
-  pure_parser = 0;
-
-  grammar = NULL;
-
   lex_init ();
   lineno = 1;
 
   lex_init ();
   lineno = 1;
 
@@ -1811,28 +1432,29 @@ reader (void)
   obstack_init (&muscle_obstack);
 
   /* Initialize the symbol table.  */
   obstack_init (&muscle_obstack);
 
   /* Initialize the symbol table.  */
-  tabinit ();
+  symbols_new ();
 
   /* Construct the axiom symbol. */
   axiom = getsym ("$axiom");
   axiom->class = nterm_sym;
 
   /* Construct the axiom symbol. */
   axiom = getsym ("$axiom");
   axiom->class = nterm_sym;
-  axiom->value = nvars++;
+  axiom->number = nvars++;
 
   /* Construct the error token */
   errtoken = getsym ("error");
   errtoken->class = token_sym;
 
   /* Construct the error token */
   errtoken = getsym ("error");
   errtoken->class = token_sym;
-  errtoken->user_token_number = 256;   /* Value specified by POSIX.  */
+  errtoken->number = ntokens++;
 
   /* Construct a token that represents all undefined literal tokens.
      It is always token number 2.  */
   undeftoken = getsym ("$undefined.");
   undeftoken->class = token_sym;
 
   /* Construct a token that represents all undefined literal tokens.
      It is always token number 2.  */
   undeftoken = getsym ("$undefined.");
   undeftoken->class = token_sym;
-  undeftoken->user_token_number = 2;
+  undeftoken->number = ntokens++;
 
   /* Initialize the obstacks. */
   obstack_init (&action_obstack);
 
   /* Initialize the obstacks. */
   obstack_init (&action_obstack);
-  obstack_init (&attrs_obstack);
   obstack_init (&output_obstack);
   obstack_init (&output_obstack);
+  obstack_init (&pre_prologue_obstack);
+  obstack_init (&post_prologue_obstack);
 
   finput = xfopen (infile, "r");
 
 
   finput = xfopen (infile, "r");
 
@@ -1846,12 +1468,13 @@ reader (void)
     {
       eoftoken = getsym ("$");
       eoftoken->class = token_sym;
     {
       eoftoken = getsym ("$");
       eoftoken->class = token_sym;
+      eoftoken->number = 0;
       /* Value specified by POSIX.  */
       eoftoken->user_token_number = 0;
     }
 
   /* Read in the grammar, build grammar in list form.  Write out
       /* Value specified by POSIX.  */
       eoftoken->user_token_number = 0;
     }
 
   /* Read in the grammar, build grammar in list form.  Write out
-     guards and actions.  */
+     actions.  */
   readgram ();
   /* Some C code is given at the end of the grammar file. */
   read_additionnal_code ();
   readgram ();
   /* Some C code is given at the end of the grammar file. */
   read_additionnal_code ();
@@ -1861,10 +1484,11 @@ reader (void)
 
   /* Assign the symbols their symbol numbers.  Write #defines for the
      token symbols into FDEFINES if requested.  */
 
   /* Assign the symbols their symbol numbers.  Write #defines for the
      token symbols into FDEFINES if requested.  */
-  packsymbols ();
-  /* Save them. */
-  symbols_save ();
+  symbols_pack ();
 
   /* Convert the grammar into the format described in gram.h.  */
   packgram ();
 
   /* Convert the grammar into the format described in gram.h.  */
   packgram ();
+
+  /* The grammar as a symbol_list is no longer needed. */
+  LIST_FREE (symbol_list, grammar);
 }
 }