]> git.saurik.com Git - bison.git/blobdiff - src/symtab.c
tests: syntax-check
[bison.git] / src / symtab.c
index fd2a8b36d0582e37e81473154e98250c28696d5c..002f6e37f84e346b274813eaaf77fcd28923ba12 100644 (file)
@@ -1,8 +1,7 @@
 /* Symbol table manager for Bison.
 
-   Copyright (C) 1984, 1989, 2000, 2001, 2002, 2004, 2005, 2006, 2007,
-   2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 2000-2002, 2004-2012 Free Software
+   Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 #include "system.h"
 
 #include <hash.h>
-#include <quotearg.h>
 
 #include "complain.h"
 #include "gram.h"
 #include "symtab.h"
 
+/*-------------------------------------------------------------------.
+| Symbols sorted by tag.  Allocated by the first invocation of       |
+| symbols_do, after which no more symbols should be created.         |
+`-------------------------------------------------------------------*/
+
+static symbol **symbols_sorted = NULL;
+
 /*------------------------.
 | Distinguished symbols.  |
 `------------------------*/
@@ -62,7 +67,7 @@ symbol_new (uniqstr tag, location loc)
 
   /* If the tag is not a string (starts with a double quote), check
      that it is valid for Yacc. */
-  if (tag[0] != '\"' && tag[0] != '\'' && strchr (tag, '-'))
+  if (tag[0] != '\"' && tag[0] != '\'' && mbschr (tag, '-'))
     yacc_at (loc, _("POSIX Yacc forbids dashes in symbol names: %s"),
              tag);
 
@@ -177,24 +182,6 @@ symbol_type_set (symbol *sym, uniqstr type_name, location loc)
     }
 }
 
-/*-----------------------------------.
-| Get the CLASS associated with SYM. |
-`-----------------------------------*/
-
-const char *
-symbol_class_get_string (symbol *sym)
-{
-  if (sym->class)
-    {
-      if (sym->class == token_sym)
-       return "terminal";
-      else if (sym->class == nterm_sym)
-       return "nonterminal";
-    }
-  return "unknown";
-}
-
-
 /*-----------------------------------------.
 | Set the DESTRUCTOR associated with SYM.  |
 `-----------------------------------------*/
@@ -380,10 +367,11 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
   if (user_token_number == 0)
     {
       endtoken = sym;
-      endtoken->number = 0;
       /* It is always mapped to 0, so it was already counted in
         NTOKENS.  */
-      --ntokens;
+      if (endtoken->number != NUMBER_UNDEFINED)
+        --ntokens;
+      endtoken->number = 0;
     }
 }
 
@@ -420,11 +408,11 @@ void
 symbol_make_alias (symbol *sym, symbol *str, location loc)
 {
   if (str->alias)
-    warn_at (loc, _("symbol `%s' used more than once as a literal string"),
-            str->tag);
+    warn_at (loc, _("symbol %s used more than once as a literal string"),
+             str->tag);
   else if (sym->alias)
-    warn_at (loc, _("symbol `%s' given more than one literal string"),
-            sym->tag);
+    warn_at (loc, _("symbol %s given more than one literal string"),
+             sym->tag);
   else
     {
       str->class = token_sym;
@@ -447,7 +435,7 @@ static inline void
 symbol_check_alias_consistency (symbol *this)
 {
   symbol *sym = this;
-  symbol *str  = this->alias;
+  symbol *str = this->alias;
 
   /* Check only the symbol in the symbol-string pair.  */
   if (!(this->alias
@@ -507,31 +495,11 @@ symbol_check_alias_consistency_processor (void *this,
 static inline bool
 symbol_pack (symbol *this)
 {
+  aver (this->number != NUMBER_UNDEFINED);
   if (this->class == nterm_sym)
-    {
-      this->number += ntokens;
-    }
-  else if (this->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 (this->number == NUMBER_UNDEFINED)
-       {
-         if (this == endtoken || this->alias == endtoken)
-           this->number = this->alias->number = 0;
-         else
-           {
-             aver (this->alias->number != NUMBER_UNDEFINED);
-             this->number = this->alias->number;
-           }
-       }
-      /* Do not do processing below for USER_NUMBER_HAS_STRING_ALIASes.  */
-      if (this->user_token_number == USER_NUMBER_HAS_STRING_ALIAS)
-       return true;
-    }
-  else /* this->class == token_sym */
-    aver (this->number != NUMBER_UNDEFINED);
+    this->number += ntokens;
+  else if (this->user_token_number == USER_NUMBER_HAS_STRING_ALIAS)
+    return true;
 
   symbols[this->number] = this;
   return true;
@@ -548,10 +516,10 @@ static void
 user_token_number_redeclaration (int num, symbol *first, symbol *second)
 {
   /* User token numbers are not assigned during the parsing, but in a
-     second step, via a (nondeterministic) traversal of the symbol
-     hash table.
+     second step, via a traversal of the symbol table sorted on tag.
 
-     Make errors deterministic: keep the first declaration first.  */
+     However, error messages make more sense if we keep the first
+     declaration first.  */
   if (location_cmp (first->location, second->location) > 0)
     {
       symbol* tmp = first;
@@ -695,6 +663,7 @@ symbol_from_uniqstr (const uniqstr key, location loc)
   if (!entry)
     {
       /* First insertion in the hash. */
+      aver (!symbols_sorted);
       entry = symbol_new (key, loc);
       if (!hash_insert (symbol_table, entry))
         xalloc_die ();
@@ -789,6 +758,7 @@ symbols_free (void)
   hash_free (symbol_table);
   hash_free (semantic_type_table);
   free (symbols);
+  free (symbols_sorted);
 }
 
 
@@ -797,13 +767,36 @@ symbols_free (void)
 | terminals.                                                     |
 `---------------------------------------------------------------*/
 
+static int
+symbols_cmp (symbol const *a, symbol const *b)
+{
+  return strcmp (a->tag, b->tag);
+}
+
+static int
+symbols_cmp_qsort (void const *a, void const *b)
+{
+  return symbols_cmp (*(symbol * const *)a, *(symbol * const *)b);
+}
+
 static void
 symbols_do (Hash_processor processor, void *processor_data)
 {
-  hash_do_for_each (symbol_table, processor, processor_data);
+  size_t count = hash_get_n_entries (symbol_table);
+  if (!symbols_sorted)
+    {
+      symbols_sorted = xnmalloc (count, sizeof *symbols_sorted);
+      hash_get_entries (symbol_table, (void**)symbols_sorted, count);
+      qsort (symbols_sorted, count, sizeof *symbols_sorted,
+             symbols_cmp_qsort);
+    }
+  {
+    size_t i;
+    for (i = 0; i < count; ++i)
+      processor (symbols_sorted[i], processor_data);
+  }
 }
 
-
 /*--------------------------------------------------------------.
 | Check that all the symbols are defined.  Report any undefined |
 | symbols and consider them nonterminals.                       |