]> git.saurik.com Git - bison.git/blobdiff - src/symtab.c
2007-02-07 Paolo Bonzini <bonzini@gnu.org>
[bison.git] / src / symtab.c
index 37677ed72f8f823a760e14fe99a99f33f002f761..8910f09c4ee0e4744f848b1aad4ec655c24e5dfe 100644 (file)
@@ -1,6 +1,6 @@
 /* Symbol table manager for Bison.
 
 /* Symbol table manager for Bison.
 
-   Copyright (C) 1984, 1989, 2000, 2001, 2002, 2004, 2005, 2006 Free
+   Copyright (C) 1984, 1989, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free
    Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
    Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
@@ -41,14 +41,14 @@ symbol *accept = NULL;
 symbol *startsymbol = NULL;
 location startsymbol_location;
 
 symbol *startsymbol = NULL;
 location startsymbol_location;
 
-/*-----------------------------------.
-| Default %destructor and %printer.  |
-`-----------------------------------*/
+/*---------------------------------------.
+| Default %destructor's and %printer's.  |
+`---------------------------------------*/
 
 
-static const char *default_destructor = NULL;
-static location default_destructor_location;
-static const char *default_printer = NULL;
-static location default_printer_location;
+static code_props default_tagged_destructor = CODE_PROPS_NONE_INIT;
+static code_props default_tagless_destructor = CODE_PROPS_NONE_INIT;
+static code_props default_tagged_printer = CODE_PROPS_NONE_INIT;
+static code_props default_tagless_printer = CODE_PROPS_NONE_INIT;
 
 /*---------------------------------.
 | Create a new symbol, named TAG.  |
 
 /*---------------------------------.
 | Create a new symbol, named TAG.  |
@@ -64,8 +64,8 @@ symbol_new (uniqstr tag, location loc)
   res->location = loc;
 
   res->type_name = NULL;
   res->location = loc;
 
   res->type_name = NULL;
-  res->destructor = NULL;
-  res->printer = NULL;
+  code_props_none_init (&res->destructor);
+  code_props_none_init (&res->printer);
 
   res->number = NUMBER_UNDEFINED;
   res->prec = 0;
 
   res->number = NUMBER_UNDEFINED;
   res->prec = 0;
@@ -83,6 +83,23 @@ symbol_new (uniqstr tag, location loc)
   return res;
 }
 
   return res;
 }
 
+/*----------------------------------------.
+| Create a new semantic type, named TAG.  |
+`----------------------------------------*/
+
+static semantic_type *
+semantic_type_new (uniqstr tag)
+{
+  semantic_type *res = xmalloc (sizeof *res);
+
+  uniqstr_assert (tag);
+  res->tag = tag;
+  code_props_none_init (&res->destructor);
+  code_props_none_init (&res->printer);
+
+  return res;
+}
+
 
 /*-----------------.
 | Print a symbol.  |
 
 /*-----------------.
 | Print a symbol.  |
@@ -92,6 +109,10 @@ symbol_new (uniqstr tag, location loc)
   if (s->Attr)                                         \
     fprintf (f, " %s { %s }", #Attr, s->Attr)
 
   if (s->Attr)                                         \
     fprintf (f, " %s { %s }", #Attr, s->Attr)
 
+#define SYMBOL_CODE_PRINT(Attr)                         \
+  if (s->Attr.code)                                     \
+    fprintf (f, " %s { %s }", #Attr, s->Attr.code)
+
 void
 symbol_print (symbol *s, FILE *f)
 {
 void
 symbol_print (symbol *s, FILE *f)
 {
@@ -99,14 +120,15 @@ symbol_print (symbol *s, FILE *f)
     {
       fprintf (f, "\"%s\"", s->tag);
       SYMBOL_ATTR_PRINT (type_name);
     {
       fprintf (f, "\"%s\"", s->tag);
       SYMBOL_ATTR_PRINT (type_name);
-      SYMBOL_ATTR_PRINT (destructor);
-      SYMBOL_ATTR_PRINT (printer);
+      SYMBOL_CODE_PRINT (destructor);
+      SYMBOL_CODE_PRINT (printer);
     }
   else
     fprintf (f, "<NULL>");
 }
 
 #undef SYMBOL_ATTR_PRINT
     }
   else
     fprintf (f, "<NULL>");
 }
 
 #undef SYMBOL_ATTR_PRINT
+#undef SYMBOL_CODE_PRINT
 
 /*------------------------------------------------------------------.
 | Complain that S's WHAT is redeclared at SECOND, and was first set |
 
 /*------------------------------------------------------------------.
 | Complain that S's WHAT is redeclared at SECOND, and was first set |
@@ -114,12 +136,21 @@ symbol_print (symbol *s, FILE *f)
 `------------------------------------------------------------------*/
 
 static void
 `------------------------------------------------------------------*/
 
 static void
-redeclaration (symbol* s, const char *what, location first, location second)
+symbol_redeclaration (symbol *s, const char *what, location first,
+                      location second)
 {
   complain_at (second, _("%s redeclaration for %s"), what, s->tag);
   complain_at (first, _("previous declaration"));
 }
 
 {
   complain_at (second, _("%s redeclaration for %s"), what, s->tag);
   complain_at (first, _("previous declaration"));
 }
 
+static void
+semantic_type_redeclaration (semantic_type *s, const char *what, location first,
+                             location second)
+{
+  complain_at (second, _("%s redeclaration for <%s>"), what, s->tag);
+  complain_at (first, _("previous declaration"));
+}
+
 
 /*-----------------------------------------------------------------.
 | Set the TYPE_NAME associated with SYM.  Does nothing if passed 0 |
 
 /*-----------------------------------------------------------------.
 | Set the TYPE_NAME associated with SYM.  Does nothing if passed 0 |
@@ -132,7 +163,7 @@ symbol_type_set (symbol *sym, uniqstr type_name, location loc)
   if (type_name)
     {
       if (sym->type_name)
   if (type_name)
     {
       if (sym->type_name)
-       redeclaration (sym, "%type", sym->type_location, loc);
+       symbol_redeclaration (sym, "%type", sym->type_location, loc);
       uniqstr_assert (type_name);
       sym->type_name = type_name;
       sym->type_location = loc;
       uniqstr_assert (type_name);
       sym->type_name = type_name;
       sym->type_location = loc;
@@ -140,95 +171,117 @@ symbol_type_set (symbol *sym, uniqstr type_name, location loc)
 }
 
 
 }
 
 
-/*------------------------------------------------------------------.
-| Set the DESTRUCTOR associated with SYM.  Do nothing if passed 0.  |
-`------------------------------------------------------------------*/
+/*-----------------------------------------.
+| Set the DESTRUCTOR associated with SYM.  |
+`-----------------------------------------*/
 
 void
 
 void
-symbol_destructor_set (symbol *sym, const char *destructor, location loc)
+symbol_destructor_set (symbol *sym, code_props const *destructor)
 {
 {
-  if (destructor)
-    {
-      if (sym->destructor)
-       redeclaration (sym, "%destructor", sym->destructor_location, loc);
-      sym->destructor = destructor;
-      sym->destructor_location = loc;
-    }
+  if (sym->destructor.code)
+    symbol_redeclaration (sym, "%destructor", sym->destructor.location,
+                          destructor->location);
+  sym->destructor = *destructor;
+}
+
+/*------------------------------------------.
+| Set the DESTRUCTOR associated with TYPE.  |
+`------------------------------------------*/
+
+void
+semantic_type_destructor_set (semantic_type *type,
+                              code_props const *destructor)
+{
+  if (type->destructor.code)
+    semantic_type_redeclaration (type, "%destructor",
+                                 type->destructor.location,
+                                 destructor->location);
+  type->destructor = *destructor;
 }
 
 /*---------------------------------------.
 | Get the computed %destructor for SYM.  |
 `---------------------------------------*/
 
 }
 
 /*---------------------------------------.
 | Get the computed %destructor for SYM.  |
 `---------------------------------------*/
 
-const char *
-symbol_destructor_get (symbol *sym)
+code_props const *
+symbol_destructor_get (symbol const *sym)
 {
 {
-  /* Token 0 cannot have a %destructor unless the user renames it.  */
-  if (UNIQSTR_EQ (sym->tag, uniqstr_new ("$end")))
-    return NULL;
+  /* Per-symbol %destructor.  */
+  if (sym->destructor.code)
+    return &sym->destructor;
+
+  /* Per-type %destructor.  */
+  if (sym->type_name)
+    {
+      code_props const *destructor =
+        &semantic_type_get (sym->type_name)->destructor;
+      if (destructor->code)
+        return destructor;
+    }
+
+  /* Apply default %destructor's only to user-defined symbols.  */
+  if (sym->tag[0] == '$' || sym == errtoken)
+    return &code_props_none;
 
 
-  if (sym->destructor != NULL)
-    return sym->destructor;
-  return default_destructor;
+  if (sym->type_name)
+    return &default_tagged_destructor;
+  return &default_tagless_destructor;
 }
 
 }
 
-/*---------------------------------------------------------------.
-| Get the grammar location of the %destructor computed for SYM.  |
-`---------------------------------------------------------------*/
+/*--------------------------------------.
+| Set the PRINTER associated with SYM.  |
+`--------------------------------------*/
 
 
-location
-symbol_destructor_location_get (symbol *sym)
+void
+symbol_printer_set (symbol *sym, code_props const *printer)
 {
 {
-  if (sym->destructor != NULL)
-    return sym->destructor_location;
-  return default_destructor_location;
+  if (sym->printer.code)
+    symbol_redeclaration (sym, "%printer",
+                          sym->printer.location, printer->location);
+  sym->printer = *printer;
 }
 
 }
 
-/*---------------------------------------------------------------.
-| Set the PRINTER associated with SYM.  Do nothing if passed 0.  |
-`---------------------------------------------------------------*/
+/*---------------------------------------.
+| Set the PRINTER associated with TYPE.  |
+`---------------------------------------*/
 
 void
 
 void
-symbol_printer_set (symbol *sym, const char *printer, location loc)
+semantic_type_printer_set (semantic_type *type, code_props const *printer)
 {
 {
-  if (printer)
-    {
-      if (sym->printer)
-       redeclaration (sym, "%printer", sym->printer_location, loc);
-      sym->printer = printer;
-      sym->printer_location = loc;
-    }
+  if (type->printer.code)
+    semantic_type_redeclaration (type, "%printer",
+                                 type->printer.location, printer->location);
+  type->printer = *printer;
 }
 
 /*------------------------------------.
 | Get the computed %printer for SYM.  |
 `------------------------------------*/
 
 }
 
 /*------------------------------------.
 | Get the computed %printer for SYM.  |
 `------------------------------------*/
 
-const char *
-symbol_printer_get (symbol *sym)
+code_props const *
+symbol_printer_get (symbol const *sym)
 {
 {
-  /* Token 0 cannot have a %printer unless the user renames it.  */
-  if (UNIQSTR_EQ (sym->tag, uniqstr_new ("$end")))
-    return NULL;
+  /* Per-symbol %printer.  */
+  if (sym->printer.code)
+    return &sym->printer;
 
 
-  if (sym->printer != NULL)
-    return sym->printer;
-  return default_printer;
-}
+  /* Per-type %printer.  */
+  if (sym->type_name)
+    {
+      code_props const *printer = &semantic_type_get (sym->type_name)->printer;
+      if (printer->code)
+        return printer;
+    }
 
 
-/*------------------------------------------------------------.
-| Get the grammar location of the %printer computed for SYM.  |
-`------------------------------------------------------------*/
+  /* Apply the default %printer only to user-defined symbols.  */
+  if (sym->tag[0] == '$' || sym == errtoken)
+    return &code_props_none;
 
 
-location
-symbol_printer_location_get (symbol *sym)
-{
-  if (sym->printer != NULL)
-    return sym->printer_location;
-  return default_printer_location;
+  if (sym->type_name)
+    return &default_tagged_printer;
+  return &default_tagless_printer;
 }
 
 }
 
-
 /*-----------------------------------------------------------------.
 | Set the PRECEDENCE associated with SYM.  Does nothing if invoked |
 | with UNDEF_ASSOC as ASSOC.                                       |
 /*-----------------------------------------------------------------.
 | Set the PRECEDENCE associated with SYM.  Does nothing if invoked |
 | with UNDEF_ASSOC as ASSOC.                                       |
@@ -240,7 +293,8 @@ symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
   if (a != undef_assoc)
     {
       if (sym->prec != 0)
   if (a != undef_assoc)
     {
       if (sym->prec != 0)
-       redeclaration (sym, assoc_to_string (a), sym->prec_location, loc);
+       symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
+                              loc);
       sym->prec = prec;
       sym->assoc = a;
       sym->prec_location = loc;
       sym->prec = prec;
       sym->assoc = a;
       sym->prec_location = loc;
@@ -289,7 +343,7 @@ symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
 {
   int *user_token_numberp;
 
 {
   int *user_token_numberp;
 
-  assert (sym->class == token_sym);
+  aver (sym->class == token_sym);
 
   if (sym->user_token_number != USER_NUMBER_ALIAS)
     user_token_numberp = &sym->user_token_number;
 
   if (sym->user_token_number != USER_NUMBER_ALIAS)
     user_token_numberp = &sym->user_token_number;
@@ -391,22 +445,20 @@ symbol_check_alias_consistency (symbol *this)
     }
 
 
     }
 
 
-  if (orig->destructor || alias->destructor)
+  if (orig->destructor.code || alias->destructor.code)
     {
     {
-      if (orig->destructor)
-       symbol_destructor_set (alias, orig->destructor,
-                              orig->destructor_location);
+      if (orig->destructor.code)
+       symbol_destructor_set (alias, &orig->destructor);
       else
       else
-       symbol_destructor_set (orig, alias->destructor,
-                              alias->destructor_location);
+       symbol_destructor_set (orig, &alias->destructor);
     }
 
     }
 
-  if (orig->printer || alias->printer)
+  if (orig->printer.code || alias->printer.code)
     {
     {
-      if (orig->printer)
-       symbol_printer_set (alias, orig->printer, orig->printer_location);
+      if (orig->printer.code)
+       symbol_printer_set (alias, &orig->printer);
       else
       else
-       symbol_printer_set (orig, alias->printer, alias->printer_location);
+       symbol_printer_set (orig, &alias->printer);
     }
 
   if (alias->prec || orig->prec)
     }
 
   if (alias->prec || orig->prec)
@@ -452,7 +504,7 @@ symbol_pack (symbol *this)
            this->number = this->alias->number = 0;
          else
            {
            this->number = this->alias->number = 0;
          else
            {
-             assert (this->alias->number != NUMBER_UNDEFINED);
+             aver (this->alias->number != NUMBER_UNDEFINED);
              this->number = this->alias->number;
            }
        }
              this->number = this->alias->number;
            }
        }
@@ -461,7 +513,7 @@ symbol_pack (symbol *this)
        return true;
     }
   else /* this->class == token_sym */
        return true;
     }
   else /* this->class == token_sym */
-    assert (this->number != NUMBER_UNDEFINED);
+    aver (this->number != NUMBER_UNDEFINED);
 
   symbols[this->number] = this;
   return true;
 
   symbols[this->number] = this;
   return true;
@@ -507,14 +559,15 @@ symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
 }
 
 
 }
 
 
-/*----------------------.
-| A symbol hash table.  |
-`----------------------*/
+/*---------------------------------------.
+| Symbol and semantic type hash tables.  |
+`---------------------------------------*/
 
 
-/* Initial capacity of symbols hash table.  */
+/* Initial capacity of symbol and semantic type hash table.  */
 #define HT_INITIAL_CAPACITY 257
 
 static struct hash_table *symbol_table = NULL;
 #define HT_INITIAL_CAPACITY 257
 
 static struct hash_table *symbol_table = NULL;
+static struct hash_table *semantic_type_table = NULL;
 
 static inline bool
 hash_compare_symbol (const symbol *m1, const symbol *m2)
 
 static inline bool
 hash_compare_symbol (const symbol *m1, const symbol *m2)
@@ -523,12 +576,25 @@ hash_compare_symbol (const symbol *m1, const symbol *m2)
   return UNIQSTR_EQ (m1->tag, m2->tag);
 }
 
   return UNIQSTR_EQ (m1->tag, m2->tag);
 }
 
+static inline bool
+hash_compare_semantic_type (const semantic_type *m1, const semantic_type *m2)
+{
+  /* Since names are unique, we can compare the pointers themselves.  */
+  return UNIQSTR_EQ (m1->tag, m2->tag);
+}
+
 static bool
 hash_symbol_comparator (void const *m1, void const *m2)
 {
   return hash_compare_symbol (m1, m2);
 }
 
 static bool
 hash_symbol_comparator (void const *m1, void const *m2)
 {
   return hash_compare_symbol (m1, m2);
 }
 
+static bool
+hash_semantic_type_comparator (void const *m1, void const *m2)
+{
+  return hash_compare_semantic_type (m1, m2);
+}
+
 static inline size_t
 hash_symbol (const symbol *m, size_t tablesize)
 {
 static inline size_t
 hash_symbol (const symbol *m, size_t tablesize)
 {
@@ -536,12 +602,24 @@ hash_symbol (const symbol *m, size_t tablesize)
   return ((uintptr_t) m->tag) % tablesize;
 }
 
   return ((uintptr_t) m->tag) % tablesize;
 }
 
+static inline size_t
+hash_semantic_type (const semantic_type *m, size_t tablesize)
+{
+  /* Since names are unique, we can hash the pointer itself.  */
+  return ((uintptr_t) m->tag) % tablesize;
+}
+
 static size_t
 hash_symbol_hasher (void const *m, size_t tablesize)
 {
   return hash_symbol (m, tablesize);
 }
 
 static size_t
 hash_symbol_hasher (void const *m, size_t tablesize)
 {
   return hash_symbol (m, tablesize);
 }
 
+static size_t
+hash_semantic_type_hasher (void const *m, size_t tablesize)
+{
+  return hash_semantic_type (m, tablesize);
+}
 
 /*-------------------------------.
 | Create the symbol hash table.  |
 
 /*-------------------------------.
 | Create the symbol hash table.  |
@@ -555,6 +633,11 @@ symbols_new (void)
                                  hash_symbol_hasher,
                                  hash_symbol_comparator,
                                  free);
                                  hash_symbol_hasher,
                                  hash_symbol_comparator,
                                  free);
+  semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY,
+                                        NULL,
+                                        hash_semantic_type_hasher,
+                                        hash_semantic_type_comparator,
+                                        free);
 }
 
 
 }
 
 
@@ -582,6 +665,30 @@ symbol_from_uniqstr (const uniqstr key, location loc)
 }
 
 
 }
 
 
+/*-----------------------------------------------------------------------.
+| Find the semantic type named KEY, and return it.  If it does not exist |
+| yet, create it.                                                        |
+`-----------------------------------------------------------------------*/
+
+semantic_type *
+semantic_type_from_uniqstr (const uniqstr key)
+{
+  semantic_type probe;
+  semantic_type *entry;
+
+  probe.tag = key;
+  entry = hash_lookup (semantic_type_table, &probe);
+
+  if (!entry)
+    {
+      /* First insertion in the hash. */
+      entry = semantic_type_new (key);
+      hash_insert (semantic_type_table, entry);
+    }
+  return entry;
+}
+
+
 /*----------------------------------------------------------------.
 | Find the symbol named KEY, and return it.  If it does not exist |
 | yet, create it.                                                 |
 /*----------------------------------------------------------------.
 | Find the symbol named KEY, and return it.  If it does not exist |
 | yet, create it.                                                 |
@@ -594,6 +701,18 @@ symbol_get (const char *key, location loc)
 }
 
 
 }
 
 
+/*-----------------------------------------------------------------------.
+| Find the semantic type named KEY, and return it.  If it does not exist |
+| yet, create it.                                                        |
+`-----------------------------------------------------------------------*/
+
+semantic_type *
+semantic_type_get (const char *key)
+{
+  return semantic_type_from_uniqstr (uniqstr_new (key));
+}
+
+
 /*------------------------------------------------------------------.
 | Generate a dummy nonterminal, whose name cannot conflict with the |
 | user's names.                                                     |
 /*------------------------------------------------------------------.
 | Generate a dummy nonterminal, whose name cannot conflict with the |
 | user's names.                                                     |
@@ -608,13 +727,18 @@ dummy_symbol_get (location loc)
 
   symbol *sym;
 
 
   symbol *sym;
 
-  sprintf (buf, "@%d", ++dummy_count);
+  sprintf (buf, "$@%d", ++dummy_count);
   sym = symbol_get (buf, loc);
   sym->class = nterm_sym;
   sym->number = nvars++;
   return sym;
 }
 
   sym = symbol_get (buf, loc);
   sym->class = nterm_sym;
   sym->number = nvars++;
   return sym;
 }
 
+bool
+symbol_is_dummy (const symbol *sym)
+{
+  return sym->tag[0] == '@' || (sym->tag[0] == '$' && sym->tag[1] == '@');
+}
 
 /*-------------------.
 | Free the symbols.  |
 
 /*-------------------.
 | Free the symbols.  |
@@ -624,6 +748,7 @@ void
 symbols_free (void)
 {
   hash_free (symbol_table);
 symbols_free (void)
 {
   hash_free (symbol_table);
+  hash_free (semantic_type_table);
   free (symbols);
 }
 
   free (symbols);
 }
 
@@ -757,30 +882,59 @@ symbols_pack (void)
 }
 
 
 }
 
 
-/*-----------------------------------.
-| Set default %destructor/%printer.  |
-`-----------------------------------*/
+/*--------------------------------------------------.
+| Set default tagged/tagless %destructor/%printer.  |
+`--------------------------------------------------*/
+
+void
+default_tagged_destructor_set (code_props const *destructor)
+{
+  if (default_tagged_destructor.code)
+    {
+      complain_at (destructor->location,
+                   _("redeclaration for default tagged %%destructor"));
+      complain_at (default_tagged_destructor.location,
+                  _("previous declaration"));
+    }
+  default_tagged_destructor = *destructor;
+}
+
+void
+default_tagless_destructor_set (code_props const *destructor)
+{
+  if (default_tagless_destructor.code)
+    {
+      complain_at (destructor->location,
+                   _("redeclaration for default tagless %%destructor"));
+      complain_at (default_tagless_destructor.location,
+                  _("previous declaration"));
+    }
+  default_tagless_destructor = *destructor;
+}
 
 void
 
 void
-default_destructor_set (const char *destructor, location loc)
+default_tagged_printer_set (code_props const *printer)
 {
 {
-  if (default_destructor != NULL)
+  if (default_tagged_printer.code)
     {
     {
-      complain_at (loc, _("redeclaration for default %%destructor"));
-      complain_at (default_destructor_location, _("previous declaration"));
+      complain_at (printer->location,
+                   _("redeclaration for default tagged %%printer"));
+      complain_at (default_tagged_printer.location,
+                  _("previous declaration"));
     }
     }
-  default_destructor = destructor;
-  default_destructor_location = loc;
+  default_tagged_printer = *printer;
 }
 
 void
 }
 
 void
-default_printer_set (const char *printer, location loc)
+default_tagless_printer_set (code_props const *printer)
 {
 {
-  if (default_printer != NULL)
+  if (default_tagless_printer.code)
     {
     {
-      complain_at (loc, _("redeclaration for default %%printer"));
-      complain_at (default_printer_location, _("previous declaration"));
+      complain_at (printer->location,
+                   _("redeclaration for default tagless %%printer"));
+      complain_at (default_tagless_printer.location,
+                  _("previous declaration"));
     }
     }
-  default_printer = printer;
-  default_printer_location = loc;
+  default_tagless_printer = *printer;
 }
 }
+