]> git.saurik.com Git - bison.git/blobdiff - src/reader.c
* src/LR0.c, src/derives.c, src/gram.c, src/gram.h, src/lalr.c,
[bison.git] / src / reader.c
index db168b68edcaef7539823557814c331ea0cb7040..185ca0fa97a76fe9aa4059f90de651dd88bc28e3 100644 (file)
@@ -45,9 +45,6 @@ typedef struct symbol_list
   const char *action;
   int action_line;
 
-  /* The guard is attached to the LHS of a rule. */
-  const char *guard;
-  int guard_line;
   symbol_t *ruleprec;
 } symbol_list;
 
@@ -80,8 +77,6 @@ symbol_list_new (symbol_t *sym)
   res->line = lineno;
   res->action = NULL;
   res->action_line = 0;
-  res->guard = NULL;
-  res->guard_line = 0;
   res->ruleprec = NULL;
   return res;
 }
@@ -131,7 +126,7 @@ symbol_make_alias (symbol_t *symbol, char *typename)
       symval->class = token_sym;
       symval->type_name = typename;
       symval->user_token_number = symbol->user_token_number;
-      symbol->user_token_number = SALIAS;
+      symbol->user_token_number = USER_NUMBER_ALIAS;
       symval->alias = symbol;
       symbol->alias = symval;
       /* symbol and symval combined are only one symbol */
@@ -154,7 +149,7 @@ static bool
 symbol_check_alias_consistence (symbol_t *this)
 {
   /* Check only those who _are_ the aliases. */
-  if (this->alias && this->user_token_number == SALIAS)
+  if (this->alias && this->user_token_number == USER_NUMBER_ALIAS)
     {
       if (this->prec != this->alias->prec)
        {
@@ -199,23 +194,23 @@ symbol_pack (symbol_t *this)
       /* 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 (this->number == -1)
+      if (this->number == NUMBER_UNDEFINED)
        {
          if (this == eoftoken || this->alias == eoftoken)
            this->number = this->alias->number = 0;
          else
            {
-             assert (this->alias->number != -1);
+             assert (this->alias->number != NUMBER_UNDEFINED);
              this->number = this->alias->number;
            }
        }
-      /* Do not do processing below for SALIASs.  */
-      if (this->user_token_number == SALIAS)
+      /* Do not do processing below for USER_NUMBER_ALIASs.  */
+      if (this->user_token_number == USER_NUMBER_ALIAS)
        return TRUE;
     }
   else /* this->class == token_sym */
     {
-      assert (this->number != -1);
+      assert (this->number != NUMBER_UNDEFINED);
     }
 
   symbols[this->number] = this;
@@ -234,10 +229,10 @@ symbol_translation (symbol_t *this)
 {
   /* Non-terminal? */
   if (this->class == token_sym
-      && this->user_token_number != SALIAS)
+      && this->user_token_number != USER_NUMBER_ALIAS)
     {
       /* A token which translation has already been set? */
-      if (token_translations[this->user_token_number] != 2)
+      if (token_translations[this->user_token_number] != undeftoken->number)
        complain (_("tokens %s and %s both assigned number %d"),
                  symbols[token_translations[this->user_token_number]]->tag,
                  this->tag, this->user_token_number);
@@ -326,12 +321,34 @@ get_type_name (int n, symbol_list *rule)
          complain (_("invalid $ value"));
          return NULL;
        }
-      i++;
+      ++i;
     }
 
   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 ").                    |
@@ -359,17 +376,17 @@ copy_string2 (FILE *fin, struct obstack *oout, int match, int store)
          continue;
        }
 
-      obstack_1grow (oout, c);
+      copy_character (oout, c);
 
       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')
-           lineno++;
+           ++lineno;
        }
 
       c = getc (fin);
@@ -452,7 +469,7 @@ copy_comment (FILE *fin, struct obstack *oout)
        }
       else if (c == '\n')
        {
-         lineno++;
+         ++lineno;
          obstack_1grow (oout, c);
          if (cplus_comment)
            ended = 1;
@@ -463,30 +480,29 @@ copy_comment (FILE *fin, struct obstack *oout)
        fatal (_("unterminated comment"));
       else
        {
-         obstack_1grow (oout, c);
+         copy_character (oout, c);
          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
-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 == '$')
     {
-      obstack_sgrow (oout, "yyloc");
-      locations_flag = 1;
+      obstack_sgrow (oout, "]b4_lhs_location[");
     }
   else if (isdigit (c) || c == '-')
     {
@@ -494,16 +510,11 @@ copy_at (FILE *fin, struct obstack *oout, int stack_offset)
 
       ungetc (c, fin);
       n = read_signed_integer (fin);
-      if (n > stack_offset)
+      if (n > rule_length)
        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
     {
@@ -514,19 +525,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,
-            symbol_list *rule, int stack_offset)
+            symbol_list *rule, int rule_length)
 {
   int c = getc (fin);
   const char *type_name = NULL;
@@ -542,15 +553,15 @@ copy_dollar (FILE *fin, struct obstack *oout,
 
   if (c == '$')
     {
-      obstack_sgrow (oout, "yyval");
-
       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)
+       type_name = "";
+      obstack_fgrow1 (oout,
+                     "]b4_lhs_value([%s])[", type_name);
     }
   else if (isdigit (c) || c == '-')
     {
@@ -558,23 +569,19 @@ copy_dollar (FILE *fin, struct obstack *oout,
       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);
-
-         /* 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)
+           type_name = "";
+         obstack_fgrow3 (oout, "]b4_rhs_value([%d], [%d], [%s])[",
+                         rule_length, n, type_name);
        }
     }
   else
@@ -591,7 +598,7 @@ copy_dollar (FILE *fin, struct obstack *oout,
 `-------------------------------------------------------------------*/
 
 static void
-copy_definition (void)
+copy_definition (struct obstack *oout)
 {
   int c;
   /* -1 while reading a character if prev char was %. */
@@ -599,7 +606,7 @@ copy_definition (void)
 
   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")));
     }
@@ -613,8 +620,8 @@ copy_definition (void)
       switch (c)
        {
        case '\n':
-         obstack_1grow (&attrs_obstack, c);
-         lineno++;
+         obstack_1grow (oout, c);
+         ++lineno;
          break;
 
        case '%':
@@ -623,18 +630,18 @@ copy_definition (void)
 
        case '\'':
        case '"':
-         copy_string (finput, &attrs_obstack, c);
+         copy_string (finput, oout, c);
          break;
 
        case '/':
-         copy_comment (finput, &attrs_obstack);
+         copy_comment (finput, oout);
          break;
 
        case EOF:
          fatal ("%s", _("unterminated `%{' definition"));
 
        default:
-         obstack_1grow (&attrs_obstack, c);
+         copy_character (oout, c);
        }
 
       c = getc (finput);
@@ -643,7 +650,7 @@ copy_definition (void)
        {
          if (c == '}')
            return;
-         obstack_1grow (&attrs_obstack, '%');
+         obstack_1grow (oout, '%');
        }
       after_percent = 0;
     }
@@ -705,7 +712,7 @@ parse_token_decl (symbol_class what_is, symbol_class what_is_not)
          symbol->class = what_is;
          if (what_is == nterm_sym && oldclass != nterm_sym)
            symbol->number = nvars++;
-         if (what_is == token_sym && symbol->number == -1)
+         if (what_is == token_sym && symbol->number == NUMBER_UNDEFINED)
            symbol->number = ntokens++;
 
          if (typename)
@@ -826,7 +833,8 @@ parse_assoc_decl (associativity assoc)
   char *name = NULL;
   int prev = 0;
 
-  lastprec++;                  /* Assign a new precedence level, never 0.  */
+  /* Assign a new precedence level, never 0.  */
+  ++lastprec;
 
   for (;;)
     {
@@ -856,7 +864,7 @@ parse_assoc_decl (associativity assoc)
          symval->assoc = assoc;
          if (symval->class == nterm_sym)
            complain (_("symbol %s redefined"), symval->tag);
-         if (symval->number == -1)
+         if (symval->number == NUMBER_UNDEFINED)
            {
              symval->number = ntokens++;
              symval->class = token_sym;
@@ -931,7 +939,7 @@ parse_union_decl (void)
       switch (c)
        {
        case '\n':
-         lineno++;
+         ++lineno;
          break;
 
        case '/':
@@ -939,7 +947,7 @@ parse_union_decl (void)
          break;
 
        case '{':
-         count++;
+         ++count;
          break;
 
        case '}':
@@ -990,10 +998,10 @@ parse_expect_decl (void)
 |                                                                    |
 | 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.                                  |
+| declaration.  The ->user_token_number of the first is              |
+| USER_NUMBER_ALIAS 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  |
@@ -1006,7 +1014,7 @@ parse_thong_decl (void)
   token_t token;
   symbol_t *symbol;
   char *typename = 0;
-  int usrtoknum = SUNDEF;
+  int usrtoknum = USER_NUMBER_UNDEFINED;
 
   token = lex ();              /* fetch typename or first token */
   if (token == tok_typename)
@@ -1027,7 +1035,7 @@ parse_thong_decl (void)
     }
   symval->class = token_sym;
   symval->type_name = typename;
-  symval->user_token_number = SALIAS;
+  symval->user_token_number = USER_NUMBER_ALIAS;
   symbol = symval;
 
   token = lex ();              /* get number or literal string */
@@ -1153,7 +1161,7 @@ parse_skel_decl (void)
 /*----------------------------------------------------------------.
 | 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
@@ -1173,7 +1181,10 @@ read_declarations (void)
              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:
@@ -1251,37 +1262,37 @@ read_declarations (void)
     }
 }
 \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
-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)
     {
+      int c;
       while ((c = getc (finput)) != '}')
        switch (c)
          {
          case '\n':
-           obstack_1grow (&action_obstack, c);
-           lineno++;
+           copy_character (&action_obstack, c);
+           ++lineno;
            break;
 
          case '{':
-           obstack_1grow (&action_obstack, c);
-           count++;
+           copy_character (&action_obstack, c);
+           ++count;
            break;
 
          case '\'':
@@ -1294,51 +1305,29 @@ parse_braces (symbol_list *rule, int stack_offset)
            break;
 
          case '$':
-           copy_dollar (finput, &action_obstack,
-                        rule, stack_offset);
+           copy_dollar (finput, &action_obstack, rule, rule_length);
            break;
 
          case '@':
-           copy_at (finput, &action_obstack,
-                    stack_offset);
+           copy_at (finput, &action_obstack, rule_length);
            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)
-       obstack_1grow (&action_obstack, c);
+       copy_character (&action_obstack, c);
     }
 
   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);
 }
 
-
-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
 
 /*-------------------------------------------------------------------.
@@ -1370,8 +1359,8 @@ gensym (void)
 | 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 |
@@ -1431,8 +1420,8 @@ readgram (void)
          }
        /* start a new rule and record its lhs.  */
 
-       nrules++;
-       nitems++;
+       ++nrules;
+       ++nritems;
 
        p = symbol_list_new (lhs);
 
@@ -1451,7 +1440,7 @@ readgram (void)
          {
            lhs->class = nterm_sym;
            lhs->number = nvars;
-           nvars++;
+           ++nvars;
          }
        else if (lhs->class == token_sym)
          complain (_("rule given for %s, which is a token"), lhs->tag);
@@ -1509,8 +1498,8 @@ readgram (void)
                /* 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;
@@ -1531,7 +1520,7 @@ readgram (void)
 
                /* Insert the dummy generated by that rule into this
                   rule.  */
-               nitems++;
+               ++nritems;
                p = symbol_list_new (sdummy);
                p1->next = p;
                p1 = p;
@@ -1541,7 +1530,7 @@ readgram (void)
 
            if (t == tok_identifier)
              {
-               nitems++;
+               ++nritems;
                p = symbol_list_new (symval);
                p1->next = p;
                p1 = p;
@@ -1550,9 +1539,9 @@ readgram (void)
              {
                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  */
@@ -1568,15 +1557,6 @@ readgram (void)
            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 */
@@ -1584,7 +1564,7 @@ readgram (void)
              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
@@ -1632,13 +1612,13 @@ readgram (void)
   p->next->next->next = symbol_list_new (NULL);
   p->next->next->next->next = grammar;
   nrules += 1;
-  nitems += 3;
+  nritems += 3;
   grammar = p;
   startval = axiom;
 
-  if (nsyms > MAXSHORT)
+  if (nsyms > SHRT_MAX)
     fatal (_("too many symbols (tokens plus nonterminals); maximum %d"),
-          MAXSHORT);
+          SHRT_MAX);
 
   assert (nsyms == ntokens + nvars);
 }
@@ -1662,7 +1642,7 @@ read_additionnal_code (void)
     }
 
   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));
@@ -1677,27 +1657,49 @@ read_additionnal_code (void)
 static void
 token_translations_init (void)
 {
-  int last_user_token_number = 256;
+  int num_256_available_p = TRUE;
   int i;
 
-  /* Set the user numbers. */
+  /* Find the highest user token number, and whether 256, the POSIX
+     preferred user token number for the error token, is used.  */
+  max_user_token_number = 0;
   for (i = 0; i < ntokens; ++i)
     {
       symbol_t *this = symbols[i];
-      if (this->user_token_number == SUNDEF)
-       this->user_token_number = ++last_user_token_number;
+      if (this->user_token_number != USER_NUMBER_UNDEFINED)
+       {
+         if (this->user_token_number > max_user_token_number)
+           max_user_token_number = this->user_token_number;
+         if (this->user_token_number == 256)
+           num_256_available_p = FALSE;
+       }
+    }
+
+  /* If 256 is not used, assign it to error, to follow POSIX.  */
+  if (num_256_available_p
+      && errtoken->user_token_number == USER_NUMBER_UNDEFINED)
+    errtoken->user_token_number = 256;
+
+  /* Set the missing user numbers. */
+  if (max_user_token_number < 256)
+    max_user_token_number = 256;
+
+  for (i = 0; i < ntokens; ++i)
+    {
+      symbol_t *this = symbols[i];
+      if (this->user_token_number == USER_NUMBER_UNDEFINED)
+       this->user_token_number = ++max_user_token_number;
       if (this->user_token_number > max_user_token_number)
        max_user_token_number = this->user_token_number;
     }
 
-  token_translations = XCALLOC (short, max_user_token_number + 1);
+  token_translations = XCALLOC (symbol_number_t, 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 + 1; i++)
-    token_translations[i] = 2;
-
+    token_translations[i] = undeftoken->number;
   symbols_do (symbol_translation, NULL);
 }
 
@@ -1717,8 +1719,6 @@ packsymbols (void)
 
   token_translations_init ();
 
-  error_token_number = errtoken->number;
-
   if (startval->class == unknown_sym)
     fatal (_("the start symbol %s is undefined"), startval->tag);
   else if (startval->class == token_sym)
@@ -1736,15 +1736,11 @@ packsymbols (void)
 static void
 packgram (void)
 {
-  int itemno;
+  unsigned int itemno;
   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);
+  ritem = XCALLOC (item_number_t, nritems);
   rules = XCALLOC (rule_t, nrules) - 1;
 
   itemno = 0;
@@ -1762,13 +1758,13 @@ packgram (void)
       rules[ruleno].useful = TRUE;
       rules[ruleno].action = p->action;
       rules[ruleno].action_line = p->action_line;
-      rules[ruleno].guard = p->guard;
-      rules[ruleno].guard_line = p->guard_line;
 
       p = p->next;
       while (p && p->sym)
        {
-         ritem[itemno++] = p->sym->number;
+         /* 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)
@@ -1785,27 +1781,24 @@ packgram (void)
          rules[ruleno].prec = ruleprec;
        }
       ritem[itemno++] = -ruleno;
-      ruleno++;
+      ++ruleno;
 
       if (p)
        p = p->next;
     }
 
-  ritem[itemno] = 0;
-  nritems = itemno;
-  assert (nritems == nitems);
+  assert (itemno == nritems);
 
   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)
@@ -1828,19 +1821,18 @@ reader (void)
   errtoken = getsym ("error");
   errtoken->class = token_sym;
   errtoken->number = ntokens++;
-  errtoken->user_token_number = 256;   /* Value specified by POSIX.  */
 
   /* Construct a token that represents all undefined literal tokens.
      It is always token number 2.  */
   undeftoken = getsym ("$undefined.");
   undeftoken->class = token_sym;
   undeftoken->number = ntokens++;
-  undeftoken->user_token_number = 2;
 
   /* Initialize the obstacks. */
   obstack_init (&action_obstack);
-  obstack_init (&attrs_obstack);
   obstack_init (&output_obstack);
+  obstack_init (&pre_prologue_obstack);
+  obstack_init (&post_prologue_obstack);
 
   finput = xfopen (infile, "r");
 
@@ -1860,7 +1852,7 @@ reader (void)
     }
 
   /* 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 ();
@@ -1878,12 +1870,3 @@ reader (void)
   /* The grammar as a symbol_list is no longer needed. */
   LIST_FREE (symbol_list, grammar);
 }
-
-void
-grammar_free (void)
-{
-  XFREE (ritem);
-  free (rules + 1);
-  /* Free the symbol table data structure.  */
-  symbols_free ();
-}