bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] symbols: improve symbol aliasing


From: Valentin Tolmer
Subject: [PATCH 1/2] symbols: improve symbol aliasing
Date: Tue, 30 Jul 2013 17:37:33 +0200

From: nitnelave <address@hidden>

Rather than having duplicate info in the symbol and the alias that has to be
resolved later on, both the symbol and the alias have a common pointer to a
separate structure containing this info.

* src/symtab.h: New structure sym_content
* src/symtab.c (sym_content_new, sym_content_free, symbol_free): New
* src/AnnotationList.c, src/conflicts.c, src/gram.c, src/gram.h,
src/graphviz.c, src/ielr.c, src/output.c, src/parse-gram.y, src/print.c
src/print-xml.c, src/print_graph.c, src/reader.c, src/reduce.c,
src/state.h, src/symlist.c, src/symtab.c, src/symtab.h, src/tables.c (misc):
adaptation of the new structures
* tests/input.at: corrections
---
 NEWS                 |    9 ++
 src/AnnotationList.c |   17 ++--
 src/conflicts.c      |   16 +--
 src/gram.c           |   16 +--
 src/gram.h           |    9 +-
 src/graphviz.c       |    2 +-
 src/ielr.c           |    4 +-
 src/output.c         |   24 +++--
 src/parse-gram.y     |   23 +++--
 src/print-xml.c      |    8 +-
 src/print.c          |    9 +-
 src/print_graph.c    |    9 +-
 src/reader.c         |   55 +++++-----
 src/reduce.c         |   18 ++--
 src/state.h          |    2 +-
 src/symlist.c        |    8 +-
 src/symtab.c         |  275 +++++++++++++++++++++++---------------------------
 src/symtab.h         |   30 ++++--
 src/tables.c         |    4 +-
 tests/input.at       |   18 ++--
 20 files changed, 283 insertions(+), 273 deletions(-)

diff --git a/NEWS b/NEWS
index c6b6cfb..722e016 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,15 @@ GNU Bison NEWS
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Alias improvement
+
+  Aliases were formerly handled this way: information about the symbol was
+  repeated in the symbol and the alias, and any discrepancy was resolved
+  after reading the whole grammar.
+
+  Now, however, the symbol and the alias share a pointer to a separate
+  structure containing the common information, and any incompatible
+  statement is thus detected at the moment it is read.
 
 * Noteworthy changes in release 2.7.90 (2013-05-30) [beta]
 
diff --git a/src/AnnotationList.c b/src/AnnotationList.c
index b14c675..9f0adb9 100644
--- a/src/AnnotationList.c
+++ b/src/AnnotationList.c
@@ -242,7 +242,7 @@ AnnotationList__computePredecessorAnnotations 
(AnnotationList *self, state *s,
           {
             symbol_number contribution_token =
               InadequacyList__getContributionToken (self->inadequacyNode, ci)
-                ->number;
+                ->content->number;
             if (AnnotationList__isContributionAlways (self, ci))
               {
                 annotation_node->contributions[ci] = NULL;
@@ -549,7 +549,7 @@ AnnotationList__compute_from_inadequacies (
                    does discard annotations in the simplest case of a S/R
                    conflict with no token precedence.  */
                 aver (!bitset_test (shift_tokens, conflicted_token)
-                      || symbols[conflicted_token]->prec);
+                      || symbols[conflicted_token]->content->prec);
                 ++annotation_counts[s->number];
                 if (contribution_count > *max_contributionsp)
                   *max_contributionsp = contribution_count;
@@ -595,7 +595,7 @@ AnnotationList__debug (AnnotationList const *self, size_t 
nitems, int spaces)
           {
             symbol_number token =
               InadequacyList__getContributionToken (a->inadequacyNode, ci)
-                ->number;
+                ->content->number;
             {
               int j;
               for (j = 0; j < spaces+2; ++j)
@@ -644,7 +644,7 @@ AnnotationList__computeLookaheadFilter (AnnotationList 
const *self,
             Sbitset biter;
             symbol_number token =
               InadequacyList__getContributionToken (self->inadequacyNode, ci)
-                ->number;
+                ->content->number;
             SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item)
               bitset_set (lookahead_filter[item], token);
           }
@@ -679,7 +679,8 @@ AnnotationList__stateMakesContribution (AnnotationList 
const *self,
     return false;
   {
     symbol_number token =
-      InadequacyList__getContributionToken (self->inadequacyNode, ci)->number;
+      InadequacyList__getContributionToken (self->inadequacyNode, ci)
+      ->content->number;
     Sbitset__Index item;
     Sbitset biter;
     SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item)
@@ -709,7 +710,7 @@ AnnotationList__computeDominantContribution (AnnotationList 
const *self,
         ContributionIndex ci;
         int actioni;
         ContributionIndex ci_rr_dominator = ContributionIndex__none;
-        int shift_precedence = token->prec;
+        int shift_precedence = token->content->prec;
 
         /* If the token has no precedence set, shift is always chosen.  */
         if (!shift_precedence)
@@ -739,7 +740,7 @@ AnnotationList__computeDominantContribution (AnnotationList 
const *self,
             if (reduce_precedence
                 && (reduce_precedence < shift_precedence
                     || (reduce_precedence == shift_precedence
-                        && token->assoc == right_assoc)))
+                        && token->content->assoc == right_assoc)))
               continue;
             if (!AnnotationList__stateMakesContribution (self, nitems, ci,
                                                          lookaheads))
@@ -747,7 +748,7 @@ AnnotationList__computeDominantContribution (AnnotationList 
const *self,
             /* This uneliminated reduction contributes, so see if it can cause
                an error action.  */
             if (reduce_precedence == shift_precedence
-                 && token->assoc == non_assoc)
+                 && token->content->assoc == non_assoc)
               {
                 /* It's not possible to find split-stable domination over
                    shift after a potential %nonassoc.  */
diff --git a/src/conflicts.c b/src/conflicts.c
index 1840473..30a2cab 100644
--- a/src/conflicts.c
+++ b/src/conflicts.c
@@ -104,7 +104,7 @@ log_resolution (rule *r, symbol_number token,
         case shift_resolution:
           obstack_printf (&solved_conflicts_obstack,
                           " (%s < %s)",
-                          r->prec->tag,
+                          r->prec->symbol->tag,
                           symbols[token]->tag);
           break;
 
@@ -112,7 +112,7 @@ log_resolution (rule *r, symbol_number token,
           obstack_printf (&solved_conflicts_obstack,
                           " (%s < %s)",
                           symbols[token]->tag,
-                          r->prec->tag);
+                          r->prec->symbol->tag);
           break;
 
         case left_resolution:
@@ -176,7 +176,7 @@ log_resolution (rule *r, symbol_number token,
         case shift_resolution:
           obstack_printf (&solved_conflicts_xml_obstack,
                           "%s &lt; %s",
-                          xml_escape_n (0, r->prec->tag),
+                          xml_escape_n (0, r->prec->symbol->tag),
                           xml_escape_n (1, symbols[token]->tag));
           break;
 
@@ -184,7 +184,7 @@ log_resolution (rule *r, symbol_number token,
           obstack_printf (&solved_conflicts_xml_obstack,
                           "%s &lt; %s",
                           xml_escape_n (0, symbols[token]->tag),
-                          xml_escape_n (1, r->prec->tag));
+                          xml_escape_n (1, r->prec->symbol->tag));
           break;
 
         case left_resolution:
@@ -269,18 +269,18 @@ resolve_sr_conflict (state *s, int ruleno, symbol 
**errors, int *nerrs)
   for (i = 0; i < ntokens; i++)
     if (bitset_test (lookahead_tokens, i)
         && bitset_test (lookahead_set, i)
-        && symbols[i]->prec)
+        && symbols[i]->content->prec)
       {
         /* Shift-reduce conflict occurs for token number i
            and it has a precedence.
            The precedence of shifting is that of token i.  */
-        if (symbols[i]->prec < redprec)
+        if (symbols[i]->content->prec < redprec)
           {
             register_precedence (redrule->prec->number, i);
             log_resolution (redrule, i, reduce_resolution);
             flush_shift (s, i);
           }
-        else if (symbols[i]->prec > redprec)
+        else if (symbols[i]->content->prec > redprec)
           {
             register_precedence (i, redrule->prec->number);
             log_resolution (redrule, i, shift_resolution);
@@ -294,7 +294,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, 
int *nerrs)
              For right associativity, keep only the shift.
              For nonassociativity, keep neither.  */
 
-          switch (symbols[i]->assoc)
+          switch (symbols[i]->content->assoc)
             {
             case undef_assoc:
               abort ();
diff --git a/src/gram.c b/src/gram.c
index f6cc3c5..790ec3a 100644
--- a/src/gram.c
+++ b/src/gram.c
@@ -65,19 +65,19 @@ rule_useless_in_parser_p (rule const *r)
 }
 
 void
-rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out)
+rule_lhs_print (rule const *r, sym_content const *previous_lhs, FILE *out)
 {
   fprintf (out, "  %3d ", r->number);
   if (previous_lhs != r->lhs)
-    fprintf (out, "%s:", r->lhs->tag);
+    fprintf (out, "%s:", r->lhs->symbol->tag);
   else
-    fprintf (out, "%*s|", (int) strlen (previous_lhs->tag), "");
+    fprintf (out, "%*s|", (int) strlen (previous_lhs->symbol->tag), "");
 }
 
 void
 rule_lhs_print_xml (rule const *r, FILE *out, int level)
 {
-  xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->tag);
+  xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->symbol->tag);
 }
 
 size_t
@@ -158,7 +158,7 @@ grammar_rules_partial_print (FILE *out, const char *title,
 {
   rule_number r;
   bool first = true;
-  symbol *previous_lhs = NULL;
+  sym_content *previous_lhs = NULL;
 
   /* rule # : LHS -> RHS */
   for (r = 0; r < nrules + nuseless_productions; r++)
@@ -209,7 +209,7 @@ grammar_rules_print_xml (FILE *out, int level)
                  rules[r].number, usefulness);
         if (rules[r].precsym)
           fprintf (out, " percent_prec=\"%s\"",
-                   xml_escape (rules[r].precsym->tag));
+                   xml_escape (rules[r].precsym->symbol->tag));
         fputs (">\n", out);
       }
       rule_lhs_print_xml (&rules[r], out, level + 3);
@@ -239,7 +239,7 @@ grammar_dump (FILE *out, const char *title)
     for (i = ntokens; i < nsyms; i++)
       fprintf (out, "%5d  %5d   %5d  %s\n",
                i,
-               symbols[i]->prec, symbols[i]->assoc,
+               symbols[i]->content->prec, symbols[i]->content->assoc,
                symbols[i]->tag);
     fprintf (out, "\n\n");
   }
@@ -280,7 +280,7 @@ grammar_dump (FILE *out, const char *title)
     rule_number r;
     for (r = 0; r < nrules + nuseless_productions; r++)
       {
-        fprintf (out, "%-5d  %s:", r, rules[r].lhs->tag);
+        fprintf (out, "%-5d  %s:", r, rules[r].lhs->symbol->tag);
         rule_rhs_print (&rules[r], out);
         fprintf (out, "\n");
       }
diff --git a/src/gram.h b/src/gram.h
index c1dd9a6..52de2de 100644
--- a/src/gram.h
+++ b/src/gram.h
@@ -180,17 +180,17 @@ typedef struct
      except if some rules are useless.  */
   rule_number number;
 
-  symbol *lhs;
+  sym_content *lhs;
   item_number *rhs;
 
   /* This symbol provides both the associativity, and the precedence. */
-  symbol *prec;
+  sym_content *prec;
 
   int dprec;
   int merger;
 
   /* This symbol was attached to the rule via %prec. */
-  symbol *precsym;
+  sym_content *precsym;
 
   location location;
   bool useful;
@@ -220,7 +220,8 @@ bool rule_useless_in_parser_p (rule const *r);
 /* Print this rule's number and lhs on OUT.  If a PREVIOUS_LHS was
    already displayed (by a previous call for another rule), avoid
    useless repetitions.  */
-void rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out);
+void rule_lhs_print (rule const *r, sym_content const *previous_lhs,
+                     FILE *out);
 void rule_lhs_print_xml (rule const *r, FILE *out, int level);
 
 /* Return the length of the RHS.  */
diff --git a/src/graphviz.c b/src/graphviz.c
index 5ee41e7..7440545 100644
--- a/src/graphviz.c
+++ b/src/graphviz.c
@@ -93,7 +93,7 @@ no_reduce_bitset_init (state const *s, bitset *no_reduce_set)
     bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n));
   for (n = 0; n < s->errs->num; ++n)
     if (s->errs->symbols[n])
-      bitset_set (*no_reduce_set, s->errs->symbols[n]->number);
+      bitset_set (*no_reduce_set, s->errs->symbols[n]->content->number);
 }
 
 static void
diff --git a/src/ielr.c b/src/ielr.c
index 5500523..56df0f4 100644
--- a/src/ielr.c
+++ b/src/ielr.c
@@ -424,7 +424,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, 
size_t item,
           if (item_number_is_rule_number (ritem[s->items[item] - 2]))
             {
               state **predecessor;
-              aver (lhs != accept->number);
+              aver (lhs != accept->content->number);
               for (predecessor = predecessors[s->number];
                    *predecessor;
                    ++predecessor)
@@ -580,7 +580,7 @@ typedef struct state_list {
 static void
 ielr_compute_goto_follow_set (bitsetv follow_kernel_items,
                               bitsetv always_follows, state_list *s,
-                              symbol *n, bitset follow_set)
+                              sym_content *n, bitset follow_set)
 {
   goto_number n_goto = map_goto (s->lr0Isocore->state->number, n->number);
   bitset_copy (follow_set, always_follows[n_goto]);
diff --git a/src/output.c b/src/output.c
index 5eafb2e..a343253 100644
--- a/src/output.c
+++ b/src/output.c
@@ -149,7 +149,7 @@ prepare_symbols (void)
   MUSCLE_INSERT_INT ("tokens_number", ntokens);
   MUSCLE_INSERT_INT ("nterms_number", nvars);
   MUSCLE_INSERT_INT ("symbols_number", nsyms);
-  MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
+  MUSCLE_INSERT_INT ("undef_token_number", undeftoken->content->number);
   MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
 
   muscle_insert_symbol_number_table ("translate",
@@ -197,7 +197,7 @@ prepare_symbols (void)
     int i;
     int *values = xnmalloc (ntokens, sizeof *values);
     for (i = 0; i < ntokens; ++i)
-      values[i] = symbols[i]->user_token_number;
+      values[i] = symbols[i]->content->user_token_number;
     muscle_insert_int_table ("toknum", values,
                              values[0], 1, ntokens);
     free (values);
@@ -283,9 +283,9 @@ prepare_states (void)
 static int
 symbol_type_name_cmp (const symbol **lhs, const symbol **rhs)
 {
-  int res = uniqstr_cmp ((*lhs)->type_name, (*rhs)->type_name);
+  int res = uniqstr_cmp ((*lhs)->content->type_name, 
(*rhs)->content->type_name);
   if (!res)
-    res = (*lhs)->number - (*rhs)->number;
+    res = (*lhs)->content->number - (*rhs)->content->number;
   return res;
 }
 
@@ -320,8 +320,9 @@ type_names_output (FILE *out)
       /* The index of the first symbol of the current type-name.  */
       int i0 = i;
       fputs (i ? ",\n[" : "[", out);
-      for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i)
-        fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number);
+      for (; i < nsyms
+           && syms[i]->content->type_name == syms[i0]->content->type_name; ++i)
+        fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->content->number);
       fputs ("]", out);
     }
   fputs ("])\n\n", out);
@@ -428,20 +429,21 @@ prepare_symbol_definitions (void)
       MUSCLE_INSERT_STRING (key, sym->tag);
 
       SET_KEY ("user_number");
-      MUSCLE_INSERT_INT (key, sym->user_token_number);
+      MUSCLE_INSERT_INT (key, sym->content->user_token_number);
 
       SET_KEY ("is_token");
       MUSCLE_INSERT_INT (key,
                          i < ntokens && sym != errtoken && sym != undeftoken);
 
       SET_KEY ("number");
-      MUSCLE_INSERT_INT (key, sym->number);
+      MUSCLE_INSERT_INT (key, sym->content->number);
 
       SET_KEY ("has_type");
-      MUSCLE_INSERT_INT (key, !!sym->type_name);
+      MUSCLE_INSERT_INT (key, !!sym->content->type_name);
 
       SET_KEY ("type");
-      MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : "");
+      MUSCLE_INSERT_STRING (key, sym->content->type_name
+                            ? sym->content->type_name : "");
 
       {
         int j;
@@ -449,7 +451,7 @@ prepare_symbol_definitions (void)
           {
             /* "printer", not "%printer".  */
             char const *pname = code_props_type_string (j) + 1;
-            code_props const *p = symbol_code_props_get (sym, j);
+            code_props const *p = symbol_code_props_get (sym->content, j);
             SET_KEY2 ("has", pname);
             MUSCLE_INSERT_INT (key, !!p->code);
 
diff --git a/src/parse-gram.y b/src/parse-gram.y
index 1ec4b4d..e8f4aa0 100644
--- a/src/parse-gram.y
+++ b/src/parse-gram.y
@@ -452,7 +452,7 @@ symbol_declaration:
       symbol_list *list;
       tag_seen = true;
       for (list = $3; list; list = list->next)
-        symbol_type_set (list->content.sym, $2, @2);
+        symbol_type_set (list->content.sym->content, $2, @2);
       symbol_list_free ($3);
     }
 ;
@@ -464,8 +464,9 @@ precedence_declaration:
       ++current_prec;
       for (list = $3; list; list = list->next)
         {
-          symbol_type_set (list->content.sym, current_type, @2);
-          symbol_precedence_set (list->content.sym, current_prec, $1, @1);
+          symbol_type_set (list->content.sym->content, current_type, @2);
+          symbol_precedence_set (list->content.sym, current_prec,
+          $1, @1);
         }
       symbol_list_free ($3);
       current_type = NULL;
@@ -501,7 +502,7 @@ symbol.prec:
 | symbol INT
     {
       $$ = $1;
-      symbol_user_token_number_set ($1, $2, @2);
+      symbol_user_token_number_set ($1->content, $2, @2);
       symbol_class_set ($1, token_sym, @1, false);
     }
 ;
@@ -540,25 +541,25 @@ symbol_def:
 | id
     {
       symbol_class_set ($1, current_class, @1, true);
-      symbol_type_set ($1, current_type, @1);
+      symbol_type_set ($1->content, current_type, @1);
     }
 | id INT
     {
       symbol_class_set ($1, current_class, @1, true);
-      symbol_type_set ($1, current_type, @1);
-      symbol_user_token_number_set ($1, $2, @2);
+      symbol_type_set ($1->content, current_type, @1);
+      symbol_user_token_number_set ($1->content, $2, @2);
     }
 | id string_as_id
     {
       symbol_class_set ($1, current_class, @1, true);
-      symbol_type_set ($1, current_type, @1);
+      symbol_type_set ($1->content, current_type, @1);
       symbol_make_alias ($1, $2, @$);
     }
 | id INT string_as_id
     {
       symbol_class_set ($1, current_class, @1, true);
-      symbol_type_set ($1, current_type, @1);
-      symbol_user_token_number_set ($1, $2, @2);
+      symbol_type_set ($1->content, current_type, @1);
+      symbol_user_token_number_set ($1->content, $2, @2);
       symbol_make_alias ($1, $3, @$);
     }
 ;
@@ -684,7 +685,7 @@ id:
     {
       $$ = symbol_get (char_name ($1), @1);
       symbol_class_set ($$, token_sym, @1, false);
-      symbol_user_token_number_set ($$, $1, @1);
+      symbol_user_token_number_set ($$->content, $1, @1);
     }
 ;
 
diff --git a/src/print-xml.c b/src/print-xml.c
index e5c25c5..3ddaeba 100644
--- a/src/print-xml.c
+++ b/src/print-xml.c
@@ -260,7 +260,7 @@ print_reductions (FILE *out, int level, state *s)
     bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
   for (i = 0; i < s->errs->num; ++i)
     if (s->errs->symbols[i])
-      bitset_set (no_reduce_set, s->errs->symbols[i]->number);
+      bitset_set (no_reduce_set, s->errs->symbols[i]->content->number);
 
   if (default_reduction)
     report = true;
@@ -388,11 +388,11 @@ print_grammar (FILE *out, int level)
   /* Terminals */
   xml_puts (out, level + 1, "<terminals>");
   for (i = 0; i < max_user_token_number + 1; i++)
-    if (token_translations[i] != undeftoken->number)
+    if (token_translations[i] != undeftoken->content->number)
       {
         char const *tag = symbols[token_translations[i]]->tag;
-        int precedence = symbols[token_translations[i]]->prec;
-        assoc associativity = symbols[token_translations[i]]->assoc;
+        int precedence = symbols[token_translations[i]]->content->prec;
+        assoc associativity = symbols[token_translations[i]]->content->assoc;
         xml_indent (out, level + 2);
         fprintf (out,
                  "<terminal symbol-number=\"%d\" token-number=\"%d\""
diff --git a/src/print.c b/src/print.c
index 824bb4a..94d3d2d 100644
--- a/src/print.c
+++ b/src/print.c
@@ -72,7 +72,7 @@ print_core (FILE *out, state *s)
   size_t i;
   item_number *sitems = s->items;
   size_t snritems = s->nitems;
-  symbol *previous_lhs = NULL;
+  sym_content *previous_lhs = NULL;
 
   /* Output all the items of a state, not only its kernel.  */
   if (report_flag & report_itemsets)
@@ -223,7 +223,8 @@ print_reduction (FILE *out, size_t width,
   if (!enabled)
     fputc ('[', out);
   if (r->number)
-    fprintf (out, _("reduce using rule %d (%s)"), r->number, r->lhs->tag);
+    fprintf (out, _("reduce using rule %d (%s)"), r->number,
+             r->lhs->symbol->tag);
   else
     fprintf (out, _("accept"));
   if (!enabled)
@@ -257,7 +258,7 @@ print_reductions (FILE *out, state *s)
     bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
   for (i = 0; i < s->errs->num; ++i)
     if (s->errs->symbols[i])
-      bitset_set (no_reduce_set, s->errs->symbols[i]->number);
+        bitset_set (no_reduce_set, s->errs->symbols[i]->content->number);
 
   /* Compute the width of the lookahead token column.  */
   if (default_reduction)
@@ -408,7 +409,7 @@ print_grammar (FILE *out)
   /* TERMINAL (type #) : rule #s terminal is on RHS */
   fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
   for (i = 0; i < max_user_token_number + 1; i++)
-    if (token_translations[i] != undeftoken->number)
+    if (token_translations[i] != undeftoken->content->number)
       {
         const char *tag = symbols[token_translations[i]]->tag;
         rule_number r;
diff --git a/src/print_graph.c b/src/print_graph.c
index 7e429db..09e26b3 100644
--- a/src/print_graph.c
+++ b/src/print_graph.c
@@ -46,7 +46,7 @@ static void
 print_core (struct obstack *oout, state *s)
 {
   item_number const *sitems = s->items;
-  symbol *previous_lhs = NULL;
+  sym_content *previous_lhs = NULL;
   size_t i;
   size_t snritems = s->nitems;
 
@@ -72,11 +72,12 @@ print_core (struct obstack *oout, state *s)
       r = &rules[item_number_as_rule_number (*sp)];
 
       obstack_printf (oout, "%3d ", r->number);
-      if (previous_lhs && UNIQSTR_EQ (previous_lhs->tag, r->lhs->tag))
+      if (previous_lhs && UNIQSTR_EQ (previous_lhs->symbol->tag,
+                                      r->lhs->symbol->tag))
         obstack_printf (oout, "%*s| ",
-                        (int) strlen (previous_lhs->tag), "");
+                        (int) strlen (previous_lhs->symbol->tag), "");
       else
-        obstack_printf (oout, "%s: ", escape (r->lhs->tag));
+        obstack_printf (oout, "%s: ", escape (r->lhs->symbol->tag));
       previous_lhs = r->lhs;
 
       for (sp = r->rhs; sp < sp1; sp++)
diff --git a/src/reader.c b/src/reader.c
index 95c595e..f34b966 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -240,13 +240,13 @@ grammar_current_rule_begin (symbol *lhs, location loc,
   current_rule = grammar_end;
 
   /* Mark the rule's lhs as a nonterminal if not already so.  */
-  if (lhs->class == unknown_sym)
+  if (lhs->content->class == unknown_sym)
     {
-      lhs->class = nterm_sym;
-      lhs->number = nvars;
+      lhs->content->class = nterm_sym;
+      lhs->content->number = nvars;
       ++nvars;
     }
-  else if (lhs->class == token_sym)
+  else if (lhs->content->class == token_sym)
     complain (&loc, complaint, _("rule given for %s, which is a token"),
               lhs->tag);
 }
@@ -263,7 +263,7 @@ grammar_current_rule_begin (symbol *lhs, location loc,
 static bool
 symbol_should_be_used (symbol_list const *s, bool *midrule_warning)
 {
-  if (symbol_code_props_get (s->content.sym, destructor)->code)
+  if (symbol_code_props_get (s->content.sym->content, destructor)->code)
     return true;
   if ((s->midrule && s->midrule->action_props.is_value_used)
       || (s->midrule_parent_rule
@@ -292,15 +292,15 @@ grammar_rule_check (const symbol_list *r)
 
      Don't worry about the default action if $$ is untyped, since $$'s
      value can't be used.  */
-  if (!r->action_props.code && r->content.sym->type_name)
+  if (!r->action_props.code && r->content.sym->content->type_name)
     {
       symbol *first_rhs = r->next->content.sym;
       /* If $$ is being set in default way, report if any type mismatch.  */
       if (first_rhs)
         {
-          char const *lhs_type = r->content.sym->type_name;
+          char const *lhs_type = r->content.sym->content->type_name;
           const char *rhs_type =
-            first_rhs->type_name ? first_rhs->type_name : "";
+            first_rhs->content->type_name ? first_rhs->content->type_name : "";
           if (!UNIQSTR_EQ (lhs_type, rhs_type))
             complain (&r->location, Wother,
                       _("type clash on default action: <%s> != <%s>"),
@@ -350,7 +350,8 @@ grammar_rule_check (const symbol_list *r)
      it for char literals and strings, which are always tokens.  */
   if (r->ruleprec
       && r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
-      && r->ruleprec->status != declared && !r->ruleprec->prec)
+      && r->ruleprec->content->status != declared
+      && !r->ruleprec->content->prec)
     complain (&r->location, Wother,
               _("token for %%prec is not defined: %s"), r->ruleprec->tag);
 }
@@ -517,8 +518,8 @@ grammar_current_rule_symbol_append (symbol *sym, location 
loc,
   p = grammar_symbol_append (sym, loc);
   if (name)
     assign_named_ref (p, name);
-  if (sym->status == undeclared || sym->status == used)
-    sym->status = needed;
+  if (sym->content->status == undeclared || sym->content->status == used)
+    sym->content->status = needed;
 }
 
 /* Attach an ACTION to the current rule.  */
@@ -558,11 +559,11 @@ packgram (void)
   for (p = grammar; p; p = p->next)
     {
       symbol *ruleprec = p->ruleprec;
-      record_merge_function_type (p->merger, p->content.sym->type_name,
+      record_merge_function_type (p->merger, 
p->content.sym->content->type_name,
                                   p->merger_declaration_location);
       rules[ruleno].user_number = ruleno;
       rules[ruleno].number = ruleno;
-      rules[ruleno].lhs = p->content.sym;
+      rules[ruleno].lhs = p->content.sym->content;
       rules[ruleno].rhs = ritem + itemno;
       rules[ruleno].prec = NULL;
       rules[ruleno].dprec = p->dprec;
@@ -604,11 +605,11 @@ packgram (void)
             /* item_number = symbol_number.
                But the former needs to contain more: negative rule numbers. */
             ritem[itemno++] =
-              symbol_number_as_item_number (p->content.sym->number);
+              symbol_number_as_item_number (p->content.sym->content->number);
             /* A rule gets by default the precedence and associativity
                of its last token.  */
-            if (p->content.sym->class == token_sym && default_prec)
-              rules[ruleno].prec = p->content.sym;
+            if (p->content.sym->content->class == token_sym && default_prec)
+              rules[ruleno].prec = p->content.sym->content;
           }
       }
 
@@ -616,8 +617,8 @@ packgram (void)
          the specified symbol's precedence replaces the default.  */
       if (ruleprec)
         {
-          rules[ruleno].precsym = ruleprec;
-          rules[ruleno].prec = ruleprec;
+          rules[ruleno].precsym = ruleprec->content;
+          rules[ruleno].prec = ruleprec->content;
         }
       /* An item ends by the rule number (negated).  */
       ritem[itemno++] = rule_number_as_item_number (ruleno);
@@ -647,19 +648,19 @@ reader (void)
 
   /* Construct the accept symbol. */
   accept = symbol_get ("$accept", empty_location);
-  accept->class = nterm_sym;
-  accept->number = nvars++;
+  accept->content->class = nterm_sym;
+  accept->content->number = nvars++;
 
   /* Construct the error token */
   errtoken = symbol_get ("error", empty_location);
-  errtoken->class = token_sym;
-  errtoken->number = ntokens++;
+  errtoken->content->class = token_sym;
+  errtoken->content->number = ntokens++;
 
   /* Construct a token that represents all undefined literal tokens.
      It is always token number 2.  */
   undeftoken = symbol_get ("$undefined", empty_location);
-  undeftoken->class = token_sym;
-  undeftoken->number = ntokens++;
+  undeftoken->content->class = token_sym;
+  undeftoken->content->number = ntokens++;
 
   gram_in = xfopen (grammar_file, "r");
 
@@ -721,10 +722,10 @@ check_and_convert_grammar (void)
   if (!endtoken)
     {
       endtoken = symbol_get ("$end", empty_location);
-      endtoken->class = token_sym;
-      endtoken->number = 0;
+      endtoken->content->class = token_sym;
+      endtoken->content->number = 0;
       /* Value specified by POSIX.  */
-      endtoken->user_token_number = 0;
+      endtoken->content->user_token_number = 0;
     }
 
   /* Report any undefined symbols and consider them nonterminals.  */
diff --git a/src/reduce.c b/src/reduce.c
index eea11b1..23ab7e4 100644
--- a/src/reduce.c
+++ b/src/reduce.c
@@ -163,9 +163,9 @@ inaccessable_symbols (void)
   Pp = bitset_create (nrules, BITSET_FIXED);
 
   /* If the start symbol isn't useful, then nothing will be useful. */
-  if (bitset_test (N, accept->number - ntokens))
+  if (bitset_test (N, accept->content->number - ntokens))
     {
-      bitset_set (V, accept->number);
+      bitset_set (V, accept->content->number);
 
       while (1)
         {
@@ -196,9 +196,9 @@ inaccessable_symbols (void)
   V = Vp;
 
   /* Tokens 0, 1, and 2 are internal to Bison.  Consider them useful. */
-  bitset_set (V, endtoken->number);             /* end-of-input token */
-  bitset_set (V, errtoken->number);             /* error token */
-  bitset_set (V, undeftoken->number);           /* some undefined token */
+  bitset_set (V, endtoken->content->number);             /* end-of-input token 
*/
+  bitset_set (V, errtoken->content->number);             /* error token */
+  bitset_set (V, undeftoken->content->number);           /* some undefined 
token */
 
   bitset_free (P);
   P = Pp;
@@ -298,7 +298,7 @@ nonterminals_reduce (void)
     if (!bitset_test (V, i))
       {
         nontermmap[i - ntokens] = n++;
-        if (symbols[i]->status != used)
+        if (symbols[i]->content->status != used)
           complain (&symbols[i]->location, Wother,
                     _("nonterminal useless in grammar: %s"),
                     symbols[i]->tag);
@@ -310,7 +310,7 @@ nonterminals_reduce (void)
     symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted);
 
     for (i = ntokens; i < nsyms; i++)
-      symbols[i]->number = nontermmap[i - ntokens];
+      symbols[i]->content->number = nontermmap[i - ntokens];
     for (i = ntokens; i < nsyms; i++)
       symbols_sorted[nontermmap[i - ntokens] - ntokens] = symbols[i];
     for (i = ntokens; i < nsyms; i++)
@@ -328,7 +328,7 @@ nonterminals_reduce (void)
             *rhsp =  symbol_number_as_item_number (nontermmap[*rhsp
                                                               - ntokens]);
       }
-    accept->number = nontermmap[accept->number - ntokens];
+    accept->content->number = nontermmap[accept->content->number - ntokens];
   }
 
   nsyms -= nuseless_nonterminals;
@@ -415,7 +415,7 @@ reduce_grammar (void)
 
   reduce_print ();
 
-  if (!bitset_test (N, accept->number - ntokens))
+  if (!bitset_test (N, accept->content->number - ntokens))
     complain (&startsymbol_location, fatal,
               _("start symbol %s does not derive any sentence"),
               startsymbol->tag);
diff --git a/src/state.h b/src/state.h
index 37cd9bf..cd54fb3 100644
--- a/src/state.h
+++ b/src/state.h
@@ -135,7 +135,7 @@ typedef struct
 /* Is the TRANSITIONS->states[Num] labelled by the error token?  */
 
 # define TRANSITION_IS_ERROR(Transitions, Num) \
-  (TRANSITION_SYMBOL (Transitions, Num) == errtoken->number)
+  (TRANSITION_SYMBOL (Transitions, Num) == errtoken->content->number)
 
 /* When resolving a SR conflicts, if the reduction wins, the shift is
    disabled.  */
diff --git a/src/symlist.c b/src/symlist.c
index 50915c1..93ae72e 100644
--- a/src/symlist.c
+++ b/src/symlist.c
@@ -205,7 +205,7 @@ symbol_list_n_type_name_get (symbol_list *l, location loc, 
int n)
       return NULL;
     }
   aver (l->content_type == SYMLIST_SYMBOL);
-  return l->content.sym->type_name;
+  return l->content.sym->content->type_name;
 }
 
 bool
@@ -222,9 +222,9 @@ symbol_list_code_props_set (symbol_list *node, 
code_props_type kind,
   switch (node->content_type)
     {
     case SYMLIST_SYMBOL:
-      symbol_code_props_set (node->content.sym, kind, cprops);
-      if (node->content.sym->status == undeclared)
-        node->content.sym->status = used;
+      symbol_code_props_set (node->content.sym->content, kind, cprops);
+      if (node->content.sym->content->status == undeclared)
+        node->content.sym->content->status = used;
       break;
     case SYMLIST_TYPE:
       semantic_type_code_props_set
diff --git a/src/symtab.c b/src/symtab.c
index 1c2372c..5ccf28e 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -58,6 +58,35 @@ static symgraph **prec_nodes;
 
 bool *used_assoc = NULL;
 
+/*-----------------------------.
+| Create a new sym_content. |
+`-----------------------------*/
+
+static sym_content *
+sym_content_new (symbol *s)
+{
+  sym_content *res = xmalloc (sizeof *res);
+
+  res->symbol = s;
+
+  res->type_name = NULL;
+  {
+    int i;
+    for (i = 0; i < CODE_PROPS_SIZE; ++i)
+      code_props_none_init (&res->props[i]);
+  }
+
+  res->number = NUMBER_UNDEFINED;
+  res->prec = 0;
+  res->assoc = undef_assoc;
+  res->user_token_number = USER_NUMBER_UNDEFINED;
+
+  res->class = unknown_sym;
+  res->status = undeclared;
+
+  return res;
+}
+
 /*---------------------------------.
 | Create a new symbol, named TAG.  |
 `---------------------------------*/
@@ -76,22 +105,9 @@ symbol_new (uniqstr tag, location loc)
 
   res->tag = tag;
   res->location = loc;
-
-  res->type_name = NULL;
-  {
-    int i;
-    for (i = 0; i < CODE_PROPS_SIZE; ++i)
-      code_props_none_init (&res->props[i]);
-  }
-
-  res->number = NUMBER_UNDEFINED;
-  res->prec = 0;
-  res->assoc = undef_assoc;
-  res->user_token_number = USER_NUMBER_UNDEFINED;
-
   res->alias = NULL;
-  res->class = unknown_sym;
-  res->status = undeclared;
+  res->content = sym_content_new (res);
+  res->is_alias = false;
 
   if (nsyms == SYMBOL_NUMBER_MAXIMUM)
     complain (NULL, fatal, _("too many symbols in input grammar (limit is 
%d)"),
@@ -100,6 +116,30 @@ symbol_new (uniqstr tag, location loc)
   return res;
 }
 
+/*--------------------.
+| Free a sym_content. |
+`--------------------*/
+
+static void
+sym_content_free (sym_content *sym)
+{
+  free (sym);
+}
+
+
+/*---------------------------------------------------------.
+| Free a symbol and its associated content if appropriate. |
+`---------------------------------------------------------*/
+
+static void
+symbol_free (void *ptr)
+{
+  symbol *sym = (symbol *)ptr;
+  if (!sym->is_alias)
+    sym_content_free (sym->content);
+  free (sym);
+}
+
 char const *
 code_props_type_string (code_props_type kind)
 {
@@ -141,12 +181,12 @@ semantic_type_new (uniqstr tag, const location *loc)
 `-----------------*/
 
 #define SYMBOL_ATTR_PRINT(Attr)                         \
-  if (s->Attr)                                          \
-    fprintf (f, " %s { %s }", #Attr, s->Attr)
+  if (s->content->Attr)                                 \
+    fprintf (f, " %s { %s }", #Attr, s->content->Attr)
 
 #define SYMBOL_CODE_PRINT(Attr)                                         \
-  if (s->props[Attr].code)                                              \
-    fprintf (f, " %s { %s }", #Attr, s->props[Attr].code)
+  if (s->content->props[Attr].code)                                     \
+    fprintf (f, " %s { %s }", #Attr, s->content->props[Attr].code)
 
 void
 symbol_print (symbol const *s, FILE *f)
@@ -193,7 +233,7 @@ is_identifier (uniqstr s)
 uniqstr
 symbol_id_get (symbol const *sym)
 {
-  aver (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS);
+  aver (sym->content->user_token_number != USER_NUMBER_HAS_STRING_ALIAS);
   if (sym->alias)
     sym = sym->alias;
   return is_identifier (sym->tag) ? sym->tag : 0;
@@ -237,12 +277,12 @@ semantic_type_redeclaration (semantic_type *s, const char 
*what, location first,
 `-----------------------------------------------------------------*/
 
 void
-symbol_type_set (symbol *sym, uniqstr type_name, location loc)
+symbol_type_set (sym_content *sym, uniqstr type_name, location loc)
 {
   if (type_name)
     {
       if (sym->type_name)
-        symbol_redeclaration (sym, "%type", sym->type_location, loc);
+        symbol_redeclaration (sym->symbol, "%type", sym->type_location, loc);
       else
         {
           uniqstr_assert (type_name);
@@ -257,11 +297,11 @@ symbol_type_set (symbol *sym, uniqstr type_name, location 
loc)
 `--------------------------------------------------------*/
 
 void
-symbol_code_props_set (symbol *sym, code_props_type kind,
+symbol_code_props_set (sym_content *sym, code_props_type kind,
                        code_props const *code)
 {
   if (sym->props[kind].code)
-    symbol_redeclaration (sym, code_props_type_string (kind),
+    symbol_redeclaration (sym->symbol, code_props_type_string (kind),
                           sym->props[kind].location,
                           code->location);
   else
@@ -290,7 +330,7 @@ semantic_type_code_props_set (semantic_type *type,
 `---------------------------------------------------*/
 
 code_props *
-symbol_code_props_get (symbol *sym, code_props_type kind)
+symbol_code_props_get (sym_content *sym, code_props_type kind)
 {
   /* Per-symbol code props.  */
   if (sym->props[kind].code)
@@ -306,7 +346,7 @@ symbol_code_props_get (symbol *sym, code_props_type kind)
     }
 
   /* Apply default code props's only to user-defined symbols.  */
-  if (sym->tag[0] != '$' && sym != errtoken)
+  if (sym->symbol->tag[0] != '$' && sym->symbol != errtoken)
     {
       code_props *code =
         &semantic_type_get (sym->type_name ? "*" : "", NULL)->props[kind];
@@ -324,16 +364,17 @@ symbol_code_props_get (symbol *sym, code_props_type kind)
 void
 symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
 {
+  sym_content *s = sym->content;
   if (a != undef_assoc)
     {
-      if (sym->prec)
-        symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
-                              loc);
+      if (s->prec)
+        symbol_redeclaration (sym, assoc_to_string (a),
+                              s->prec_location, loc);
       else
         {
-          sym->prec = prec;
-          sym->assoc = a;
-          sym->prec_location = loc;
+          s->prec = prec;
+          s->assoc = a;
+          s->prec_location = loc;
         }
     }
 
@@ -347,29 +388,30 @@ symbol_precedence_set (symbol *sym, int prec, assoc a, 
location loc)
 `------------------------------------*/
 
 void
-symbol_class_set (symbol *sym, symbol_class class, location loc, bool 
declaring)
+symbol_class_set (symbol *sym, symbol_class class, location loc,
+                  bool declaring)
 {
   bool warned = false;
-  if (sym->class != unknown_sym && sym->class != class)
+  if (sym->content->class != unknown_sym && sym->content->class != class)
     {
       complain (&loc, complaint, _("symbol %s redefined"), sym->tag);
       /* Don't report both "redefined" and "redeclared".  */
       warned = true;
     }
 
-  if (class == nterm_sym && sym->class != nterm_sym)
-    sym->number = nvars++;
-  else if (class == token_sym && sym->number == NUMBER_UNDEFINED)
-    sym->number = ntokens++;
+  if (class == nterm_sym && sym->content->class != nterm_sym)
+    sym->content->number = nvars++;
+  else if (class == token_sym && sym->content->number == NUMBER_UNDEFINED)
+    sym->content->number = ntokens++;
 
-  sym->class = class;
+  sym->content->class = class;
 
   if (declaring)
     {
-      if (sym->status == declared && !warned)
+      if (sym->content->status == declared && !warned)
         complain (&loc, Wother, _("symbol %s redeclared"), sym->tag);
       else
-        sym->status = declared;
+        sym->content->status = declared;
     }
 }
 
@@ -379,29 +421,27 @@ symbol_class_set (symbol *sym, symbol_class class, 
location loc, bool declaring)
 `------------------------------------------------*/
 
 void
-symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
+symbol_user_token_number_set (sym_content *sym, int user_token_number,
+                              location loc)
 {
   int *user_token_numberp;
 
-  if (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS)
-    user_token_numberp = &sym->user_token_number;
-  else
-    user_token_numberp = &sym->alias->user_token_number;
+  user_token_numberp = &sym->user_token_number;
   if (*user_token_numberp != USER_NUMBER_UNDEFINED
       && *user_token_numberp != user_token_number)
     complain (&loc, complaint, _("redefining user token number of %s"),
-              sym->tag);
+              sym->symbol->tag);
 
   *user_token_numberp = user_token_number;
   /* User defined $end token? */
   if (user_token_number == 0)
     {
-      endtoken = sym;
+      endtoken = sym->symbol;
       /* It is always mapped to 0, so it was already counted in
          NTOKENS.  */
-      if (endtoken->number != NUMBER_UNDEFINED)
+      if (endtoken->content->number != NUMBER_UNDEFINED)
         --ntokens;
-      endtoken->number = 0;
+      endtoken->content->number = 0;
     }
 }
 
@@ -412,16 +452,17 @@ symbol_user_token_number_set (symbol *sym, int 
user_token_number, location loc)
 `----------------------------------------------------------*/
 
 static inline bool
-symbol_check_defined (symbol *sym)
+symbol_check_defined (symbol *s)
 {
+  sym_content *sym = s->content;
   if (sym->class == unknown_sym)
     {
       assert (sym->status != declared);
-      complain (&sym->location,
+      complain (&s->location,
                 sym->status == needed ? complaint : Wother,
                 _("symbol %s is used, but is not defined as a token"
                   " and has no rules"),
-                  sym->tag);
+                  s->tag);
       sym->class = nterm_sym;
       sym->number = nvars++;
     }
@@ -493,70 +534,15 @@ symbol_make_alias (symbol *sym, symbol *str, location loc)
               _("symbol %s given more than one literal string"), sym->tag);
   else
     {
-      str->class = token_sym;
-      str->user_token_number = sym->user_token_number;
-      sym->user_token_number = USER_NUMBER_HAS_STRING_ALIAS;
+      sym_content_free (str->content);
+      str->content = sym->content;
+      str->content->symbol = str;
+      str->is_alias = true;
       str->alias = sym;
       sym->alias = str;
-      str->number = sym->number;
-      symbol_type_set (str, sym->type_name, loc);
-    }
-}
-
-
-/*---------------------------------------------------------.
-| Check that THIS, and its alias, have same precedence and |
-| associativity.                                           |
-`---------------------------------------------------------*/
-
-static inline void
-symbol_check_alias_consistency (symbol *this)
-{
-  symbol *sym = this;
-  symbol *str = this->alias;
-
-  /* Check only the symbol in the symbol-string pair.  */
-  if (!(this->alias
-        && this->user_token_number == USER_NUMBER_HAS_STRING_ALIAS))
-    return;
-
-  if (str->type_name != sym->type_name)
-    {
-      if (str->type_name)
-        symbol_type_set (sym, str->type_name, str->type_location);
-      else
-        symbol_type_set (str, sym->type_name, sym->type_location);
-    }
-
-
-  {
-    int i;
-    for (i = 0; i < CODE_PROPS_SIZE; ++i)
-      if (str->props[i].code)
-        symbol_code_props_set (sym, i, &str->props[i]);
-      else if (sym->props[i].code)
-        symbol_code_props_set (str, i, &sym->props[i]);
-  }
-
-  if (sym->prec || str->prec)
-    {
-      if (str->prec)
-        symbol_precedence_set (sym, str->prec, str->assoc,
-                               str->prec_location);
-      else
-        symbol_precedence_set (str, sym->prec, sym->assoc,
-                               sym->prec_location);
     }
 }
 
-static bool
-symbol_check_alias_consistency_processor (void *this,
-                                          void *null ATTRIBUTE_UNUSED)
-{
-  symbol_check_alias_consistency (this);
-  return true;
-}
-
 
 /*-------------------------------------------------------------------.
 | Assign a symbol number, and write the definition of the token name |
@@ -564,15 +550,16 @@ symbol_check_alias_consistency_processor (void *this,
 `-------------------------------------------------------------------*/
 
 static inline bool
-symbol_pack (symbol *this)
+symbol_pack (symbol *s)
 {
+  sym_content *this = s->content;
   aver (this->number != NUMBER_UNDEFINED);
   if (this->class == nterm_sym)
     this->number += ntokens;
   else if (this->user_token_number == USER_NUMBER_HAS_STRING_ALIAS)
     return true;
 
-  symbols[this->number] = this;
+  symbols[this->number] = this->symbol;
   return true;
 }
 
@@ -582,16 +569,15 @@ symbol_pack_processor (void *this, void *null 
ATTRIBUTE_UNUSED)
   return symbol_pack (this);
 }
 
-
 static void
 user_token_number_redeclaration (int num, symbol *first, symbol *second)
 {
   unsigned i = 0;
-  /* User token numbers are not assigned during the parsing, but in a
+   /*User token numbers are not assigned during the parsing, but in a
      second step, via a traversal of the symbol table sorted on tag.
 
      However, error messages make more sense if we keep the first
-     declaration first.  */
+     declaration first.*/
   if (location_cmp (first->location, second->location) > 0)
     {
       symbol* tmp = first;
@@ -612,18 +598,20 @@ user_token_number_redeclaration (int num, symbol *first, 
symbol *second)
 `--------------------------------------------------*/
 
 static inline bool
-symbol_translation (symbol *this)
+symbol_translation (symbol *s)
 {
+  sym_content *this = s->content;
   /* Non-terminal? */
   if (this->class == token_sym
-      && this->user_token_number != USER_NUMBER_HAS_STRING_ALIAS)
+      && !s->is_alias)
     {
-      /* A token which translation has already been set? */
-      if (token_translations[this->user_token_number] != undeftoken->number)
+      /* A token which translation has already been set?*/
+      if (token_translations[this->user_token_number]
+          != undeftoken->content->number)
         user_token_number_redeclaration
           (this->user_token_number,
            symbols[token_translations[this->user_token_number]],
-           this);
+           this->symbol);
       else
         token_translations[this->user_token_number] = this->number;
     }
@@ -711,7 +699,7 @@ symbols_new (void)
                                   NULL,
                                   hash_symbol_hasher,
                                   hash_symbol_comparator,
-                                  free);
+                                  symbol_free);
   semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY,
                                          NULL,
                                          hash_semantic_type_hasher,
@@ -811,8 +799,8 @@ dummy_symbol_get (location loc)
 
   sprintf (buf, "address@hidden", ++dummy_count);
   sym = symbol_get (buf, loc);
-  sym->class = nterm_sym;
-  sym->number = nvars++;
+  sym->content->class = nterm_sym;
+  sym->content->number = nvars++;
   return sym;
 }
 
@@ -902,7 +890,7 @@ symbols_token_translations_init (void)
   max_user_token_number = 0;
   for (i = 0; i < ntokens; ++i)
     {
-      symbol *this = symbols[i];
+      sym_content *this = symbols[i]->content;
       if (this->user_token_number != USER_NUMBER_UNDEFINED)
         {
           if (this->user_token_number > max_user_token_number)
@@ -914,8 +902,8 @@ symbols_token_translations_init (void)
 
   /* 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;
+      && errtoken->content->user_token_number == USER_NUMBER_UNDEFINED)
+    errtoken->content->user_token_number = 256;
 
   /* Set the missing user numbers. */
   if (max_user_token_number < 256)
@@ -923,7 +911,7 @@ symbols_token_translations_init (void)
 
   for (i = 0; i < ntokens; ++i)
     {
-      symbol *this = symbols[i];
+      sym_content *this = symbols[i]->content;
       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)
@@ -936,7 +924,7 @@ symbols_token_translations_init (void)
   /* Initialize all entries for literal tokens to the internal token
      number for $undefined, which represents all invalid inputs.  */
   for (i = 0; i < max_user_token_number + 1; i++)
-    token_translations[i] = undeftoken->number;
+    token_translations[i] = undeftoken->content->number;
   symbols_do (symbol_translation_processor, NULL,
               symbol_table, &symbols_sorted);
 }
@@ -950,9 +938,6 @@ symbols_token_translations_init (void)
 void
 symbols_pack (void)
 {
-  symbols_do (symbol_check_alias_consistency_processor, NULL,
-              symbol_table, &symbols_sorted);
-
   symbols = xcalloc (nsyms, sizeof *symbols);
   symbols_do (symbol_pack_processor, NULL, symbol_table, &symbols_sorted);
 
@@ -971,9 +956,7 @@ symbols_pack (void)
         else
           {
             symbols[writei] = symbols[readi];
-            symbols[writei]->number = writei;
-            if (symbols[writei]->alias)
-              symbols[writei]->alias->number = writei;
+            symbols[writei]->content->number = writei;
             writei += 1;
           }
       }
@@ -982,11 +965,11 @@ symbols_pack (void)
 
   symbols_token_translations_init ();
 
-  if (startsymbol->class == unknown_sym)
+  if (startsymbol->content->class == unknown_sym)
     complain (&startsymbol_location, fatal,
               _("the start symbol %s is undefined"),
               startsymbol->tag);
-  else if (startsymbol->class == token_sym)
+  else if (startsymbol->content->class == token_sym)
     complain (&startsymbol_location, fatal,
               _("the start symbol %s is a token"),
               startsymbol->tag);
@@ -1123,9 +1106,9 @@ static inline bool
 is_assoc_useless (symbol *s)
 {
   return s
-      && s->assoc != undef_assoc
-      && s->assoc != precedence_assoc
-      && !used_assoc[s->number];
+      && s->content->assoc != undef_assoc
+      && s->content->assoc != precedence_assoc
+      && !used_assoc[s->content->number];
 }
 
 /*-------------------------------.
@@ -1157,19 +1140,19 @@ print_precedence_warnings (void)
     {
       symbol *s = symbols[i];
       if (s
-          && s->prec != 0
+          && s->content->prec != 0
           && !prec_nodes[i]->pred
           && !prec_nodes[i]->succ)
         {
           if (is_assoc_useless (s))
-            complain (&s->prec_location, Wprecedence,
+            complain (&s->content->prec_location, Wprecedence,
                       _("useless precedence and associativity for %s"), 
s->tag);
-          else if (s->assoc == precedence_assoc)
-            complain (&s->prec_location, Wprecedence,
+          else if (s->content->assoc == precedence_assoc)
+            complain (&s->content->prec_location, Wprecedence,
                       _("useless precedence for %s"), s->tag);
         }
       else if (is_assoc_useless (s))
-        complain (&s->prec_location, Wprecedence,
+        complain (&s->content->prec_location, Wprecedence,
                   _("useless associativity for %s, use %%precedence"), s->tag);
     }
   free (used_assoc);
diff --git a/src/symtab.h b/src/symtab.h
index bcc7495..477c235 100644
--- a/src/symtab.h
+++ b/src/symtab.h
@@ -50,6 +50,7 @@ typedef int symbol_number;
 
 
 typedef struct symbol symbol;
+typedef struct sym_content sym_content;
 
 /* Declaration status of a symbol.
 
@@ -82,8 +83,6 @@ enum code_props_type
 
 enum { CODE_PROPS_SIZE = 2 };
 
-/* When extending this structure, be sure to complete
-   symbol_check_alias_consistency.  */
 struct symbol
 {
   /** The key, name of the symbol.  */
@@ -91,6 +90,20 @@ struct symbol
   /** The location of its first occurrence.  */
   location location;
 
+  /* Points to the other in the symbol-string pair for an alias. */
+  symbol *alias;
+
+  /** Whether this symbol is the alias of another or not. */
+  bool is_alias;
+
+  /** All the info about the pointed symbol is there. */
+  sym_content *content;
+};
+
+struct sym_content
+{
+  symbol *symbol;
+
   /** Its \c \%type.
 
       Beware that this is the type_name as was entered by the user,
@@ -117,10 +130,6 @@ struct symbol
   assoc assoc;
   int user_token_number;
 
-  /* Points to the other in the symbol-string pair for an alias.
-     Special value USER_NUMBER_HAS_STRING_ALIAS in the symbol half of the
-     symbol-string pair for an alias.  */
-  symbol *alias;
   symbol_class class;
   status status;
 };
@@ -177,16 +186,16 @@ void symbol_make_alias (symbol *sym, symbol *str, 
location loc);
 /** Set the \c type_name associated with \c sym.
 
     Do nothing if passed 0 as \c type_name.  */
-void symbol_type_set (symbol *sym, uniqstr type_name, location loc);
+void symbol_type_set (sym_content *sym, uniqstr type_name, location loc);
 
 /** Set the \c \%destructor or \c \%printer associated with \c sym.  */
-void symbol_code_props_set (symbol *sym, code_props_type kind,
+void symbol_code_props_set (sym_content *sym, code_props_type kind,
                             code_props const *destructor);
 
 /** Get the computed \c \%destructor or \c %printer for \c sym, which was
     initialized with \c code_props_none_init if there's no \c \%destructor or
     \c %printer.  */
-code_props *symbol_code_props_get (symbol *sym, code_props_type kind);
+code_props *symbol_code_props_get (sym_content *sym, code_props_type kind);
 
 /** Set the \c precedence associated with \c sym.
 
@@ -199,7 +208,8 @@ void symbol_class_set (symbol *sym, symbol_class class, 
location loc,
                        bool declaring);
 
 /** Set the \c user_token_number associated with \c sym.  */
-void symbol_user_token_number_set (symbol *sym, int user_number, location loc);
+void symbol_user_token_number_set (sym_content *sym, int user_number,
+                                   location loc);
 
 
 
diff --git a/src/tables.c b/src/tables.c
index f06cba8..eb046f5 100644
--- a/src/tables.c
+++ b/src/tables.c
@@ -290,7 +290,7 @@ action_row (state *s)
 
       /* Do not use any default reduction if there is a shift for
          error */
-      if (sym == errtoken->number)
+      if (sym == errtoken->content->number)
         nodefault = true;
     }
 
@@ -300,7 +300,7 @@ action_row (state *s)
   for (i = 0; i < errp->num; i++)
     {
       symbol *sym = errp->symbols[i];
-      actrow[sym->number] = ACTION_NUMBER_MINIMUM;
+      actrow[sym->content->number] = ACTION_NUMBER_MINIMUM;
     }
 
   /* Turn off default reductions where requested by the user.  See
diff --git a/tests/input.at b/tests/input.at
index eb73bf9..1548f14 100644
--- a/tests/input.at
+++ b/tests/input.at
@@ -672,25 +672,25 @@ exp: foo;
 ]])
 
 AT_BISON_CHECK([-fcaret input.y], [1], [],
-[[input.y:8.7-11: error: %type redeclaration for foo
+[[input.y:8.7-11: error: %type redeclaration for "foo"
  %type <baz>       "foo"
        ^^^^^
 input.y:3.7-11:     previous declaration
  %type <bar>       foo
        ^^^^^
-input.y:10.13-17: error: %destructor redeclaration for foo
- %destructor {baz} "foo"
-             ^^^^^
-input.y:5.13-17:      previous declaration
- %destructor {bar} foo
-             ^^^^^
-input.y:9.10-14: error: %printer redeclaration for foo
+input.y:9.10-14: error: %printer redeclaration for "foo"
  %printer {baz}    "foo"
           ^^^^^
 input.y:4.10-14:     previous declaration
  %printer {bar}    foo
           ^^^^^
-input.y:11.1-5: error: %left redeclaration for foo
+input.y:10.13-17: error: %destructor redeclaration for "foo"
+ %destructor {baz} "foo"
+             ^^^^^
+input.y:5.13-17:      previous declaration
+ %destructor {bar} foo
+             ^^^^^
+input.y:11.1-5: error: %left redeclaration for "foo"
  %left             "foo"
  ^^^^^
 input.y:6.1-5:      previous declaration
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]