1 /* Symbol table manager for Bison, 
   2    Copyright (C) 1984, 1989, 2000, 2001, 2002 Free Software Foundation, Inc. 
   4    This file is part of Bison, the GNU Compiler Compiler. 
   6    Bison is free software; you can redistribute it and/or modify 
   7    it under the terms of the GNU General Public License as published by 
   8    the Free Software Foundation; either version 2, or (at your option) 
  11    Bison is distributed in the hope that it will be useful, 
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  14    GNU General Public License for more details. 
  16    You should have received a copy of the GNU General Public License 
  17    along with Bison; see the file COPYING.  If not, write to 
  18    the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
  19    Boston, MA 02111-1307, USA.  */ 
  29 /*------------------------. 
  30 | Distinguished symbols.  | 
  31 `------------------------*/ 
  33 symbol_t 
*errtoken 
= NULL
; 
  34 symbol_t 
*undeftoken 
= NULL
; 
  35 symbol_t 
*endtoken 
= NULL
; 
  36 symbol_t 
*accept 
= NULL
; 
  37 symbol_t 
*startsymbol 
= NULL
; 
  38 location_t startsymbol_location
; 
  40 /*---------------------------------. 
  41 | Create a new symbol, named TAG.  | 
  42 `---------------------------------*/ 
  45 symbol_new (const char *tag
, location_t location
) 
  47   symbol_t 
*res 
= XMALLOC (symbol_t
, 1); 
  49   res
->tag 
= xstrdup (tag
); 
  50   res
->location 
= location
; 
  52   res
->type_name 
= NULL
; 
  53   res
->destructor 
= NULL
; 
  56   res
->number 
= NUMBER_UNDEFINED
; 
  58   res
->assoc 
= undef_assoc
; 
  59   res
->user_token_number 
= USER_NUMBER_UNDEFINED
; 
  62   res
->class = unknown_sym
; 
  69 /*------------------------------------------------------------------. 
  70 | Set the TYPE_NAME associated to SYMBOL.  Does nothing if passed 0 | 
  72 `------------------------------------------------------------------*/ 
  75 symbol_type_set (symbol_t 
*symbol
, char *type_name
, location_t location
) 
  79       if (symbol
->type_name
) 
  80         complain_at (location
, 
  81                      _("type redeclaration for %s"), symbol
->tag
); 
  82       symbol
->type_name 
= type_name
; 
  87 /*-------------------------------------------------------------------. 
  88 | Set the DESTRUCTOR associated to SYMBOL.  Do nothing if passed 0.  | 
  89 `-------------------------------------------------------------------*/ 
  92 symbol_destructor_set (symbol_t 
*symbol
, char *destructor
, location_t location
) 
  96       if (symbol
->destructor
) 
  97         complain_at (location
, 
  98                      _("%s redeclaration for %s"), 
  99                      "%destructor", symbol
->tag
); 
 100       symbol
->destructor 
= destructor
; 
 101       symbol
->destructor_location 
= location
; 
 106 /*----------------------------------------------------------------. 
 107 | Set the PRITNER associated to SYMBOL.  Do nothing if passed 0.  | 
 108 `----------------------------------------------------------------*/ 
 111 symbol_printer_set (symbol_t 
*symbol
, char *printer
, location_t location
) 
 116         complain_at (location
, 
 117                      _("%s redeclaration for %s"), 
 118                      "%printer", symbol
->tag
); 
 119       symbol
->printer 
= printer
; 
 120       symbol
->printer_location 
= location
; 
 125 /*------------------------------------------------------------------. 
 126 | Set the PRECEDENCE associated to SYMBOL.  Does nothing if invoked | 
 127 | with UNDEF_ASSOC as ASSOC.                                        | 
 128 `------------------------------------------------------------------*/ 
 131 symbol_precedence_set (symbol_t 
*symbol
, 
 132                        int prec
, assoc_t assoc
, location_t location
) 
 134   if (assoc 
!= undef_assoc
) 
 136       if (symbol
->prec 
!= 0) 
 137         complain_at (location
, 
 138                      _("redefining precedence of %s"), 
 141       symbol
->assoc 
= assoc
; 
 144   /* Only terminals have a precedence. */ 
 145   symbol_class_set (symbol
, token_sym
, location
); 
 149 /*-------------------------------------. 
 150 | Set the CLASS associated to SYMBOL.  | 
 151 `-------------------------------------*/ 
 154 symbol_class_set (symbol_t 
*symbol
, symbol_class 
class, location_t location
) 
 156   if (symbol
->class != unknown_sym 
&& symbol
->class != class) 
 157     complain_at (location
, _("symbol %s redefined"), symbol
->tag
); 
 159   if (class == nterm_sym 
&& symbol
->class != nterm_sym
) 
 160     symbol
->number 
= nvars
++; 
 161   else if (class == token_sym 
&& symbol
->number 
== NUMBER_UNDEFINED
) 
 162     symbol
->number 
= ntokens
++; 
 164   symbol
->class = class; 
 168 /*-------------------------------------------------. 
 169 | Set the USER_TOKEN_NUMBER associated to SYMBOL.  | 
 170 `-------------------------------------------------*/ 
 173 symbol_user_token_number_set (symbol_t 
*symbol
, 
 174                               int user_token_number
, location_t location
) 
 176   assert (symbol
->class == token_sym
); 
 178   if (symbol
->user_token_number 
!= USER_NUMBER_UNDEFINED
 
 179       && symbol
->user_token_number 
!= user_token_number
) 
 180     complain_at (location
, _("redefining user token number of %s"), 
 183   symbol
->user_token_number 
= user_token_number
; 
 184   /* User defined $end token? */ 
 185   if (user_token_number 
== 0) 
 188       endtoken
->number 
= 0; 
 189       /* It is always mapped to 0, so it was already counted in 
 201 symbol_free (symbol_t 
*this) 
 204   /* This causes crashes because one string can appear more 
 206   XFREE (this->type_name
); 
 213 /*-----------------------------------------------------------. 
 214 | If THIS is not defined, report an error, and consider it a | 
 216 `-----------------------------------------------------------*/ 
 219 symbol_check_defined (symbol_t 
*this) 
 221   if (this->class == unknown_sym
) 
 225          _("symbol %s is used, but is not defined as a token and has no rules"), 
 227       this->class = nterm_sym
; 
 228       this->number 
= nvars
++; 
 235 /*-------------------------------------------------------------------. 
 236 | Declare the new SYMBOL.  Make it an alias of SYMVAL, and type them | 
 238 `-------------------------------------------------------------------*/ 
 241 symbol_make_alias (symbol_t 
*symbol
, symbol_t 
*symval
, location_t loc
) 
 244     warn_at (loc
, _("symbol `%s' used more than once as a literal string"), 
 246   else if (symbol
->alias
) 
 247     warn_at (loc
, _("symbol `%s' given more than one literal string"), 
 251       symval
->class = token_sym
; 
 252       symval
->user_token_number 
= symbol
->user_token_number
; 
 253       symbol
->user_token_number 
= USER_NUMBER_ALIAS
; 
 254       symval
->alias 
= symbol
; 
 255       symbol
->alias 
= symval
; 
 256       /* symbol and symval combined are only one symbol */ 
 259       assert (ntokens 
== symbol
->number 
|| ntokens 
== symval
->number
); 
 260       symbol
->number 
= symval
->number 
= 
 261         (symval
->number 
< symbol
->number
) ? symval
->number 
: symbol
->number
; 
 266 /*---------------------------------------------------------. 
 267 | Check that THIS, and its alias, have same precedence and | 
 269 `---------------------------------------------------------*/ 
 272 symbol_check_alias_consistence (symbol_t 
*this) 
 274   /* Check only those who _are_ the aliases. */ 
 275   if (this->alias 
&& this->user_token_number 
== USER_NUMBER_ALIAS
) 
 277       if (this->prec 
!= this->alias
->prec
) 
 279           if (this->prec 
!= 0 && this->alias
->prec 
!= 0) 
 280             complain_at (this->alias
->location
, 
 281                          _("conflicting precedences for %s and %s"), 
 282                          this->tag
, this->alias
->tag
); 
 284             this->alias
->prec 
= this->prec
; 
 286             this->prec 
= this->alias
->prec
; 
 289       if (this->assoc 
!= this->alias
->assoc
) 
 291           if (this->assoc 
!= undef_assoc 
&& this->alias
->assoc 
!= undef_assoc
) 
 292             complain_at (this->alias
->location
, 
 293                          _("conflicting associativities for %s (%s) and %s (%s)"), 
 294                          this->tag
, assoc_to_string (this->assoc
), 
 295                          this->alias
->tag
, assoc_to_string (this->alias
->assoc
)); 
 296           if (this->assoc 
!= undef_assoc
) 
 297             this->alias
->assoc 
= this->assoc
; 
 299             this->assoc 
= this->alias
->assoc
; 
 306 /*-------------------------------------------------------------------. 
 307 | Assign a symbol number, and write the definition of the token name | 
 308 | into FDEFINES.  Put in SYMBOLS.                                    | 
 309 `-------------------------------------------------------------------*/ 
 312 symbol_pack (symbol_t 
*this) 
 314   if (this->class == nterm_sym
) 
 316       this->number 
+= ntokens
; 
 318   else if (this->alias
) 
 320       /* This symbol and its alias are a single token defn. 
 321          Allocate a tokno, and assign to both check agreement of 
 322          prec and assoc fields and make both the same */ 
 323       if (this->number 
== NUMBER_UNDEFINED
) 
 325           if (this == endtoken 
|| this->alias 
== endtoken
) 
 326             this->number 
= this->alias
->number 
= 0; 
 329               assert (this->alias
->number 
!= NUMBER_UNDEFINED
); 
 330               this->number 
= this->alias
->number
; 
 333       /* Do not do processing below for USER_NUMBER_ALIASs.  */ 
 334       if (this->user_token_number 
== USER_NUMBER_ALIAS
) 
 337   else /* this->class == token_sym */ 
 339       assert (this->number 
!= NUMBER_UNDEFINED
); 
 342   symbols
[this->number
] = this; 
 349 /*--------------------------------------------------. 
 350 | Put THIS in TOKEN_TRANSLATIONS if it is a token.  | 
 351 `--------------------------------------------------*/ 
 354 symbol_translation (symbol_t 
*this) 
 357   if (this->class == token_sym
 
 358       && this->user_token_number 
!= USER_NUMBER_ALIAS
) 
 360       /* A token which translation has already been set? */ 
 361       if (token_translations
[this->user_token_number
] != undeftoken
->number
) 
 362         complain_at (this->location
, 
 363                      _("tokens %s and %s both assigned number %d"), 
 364                      symbols
[token_translations
[this->user_token_number
]]->tag
, 
 365                      this->tag
, this->user_token_number
); 
 367       token_translations
[this->user_token_number
] = this->number
; 
 374 /*----------------------. 
 375 | A symbol hash table.  | 
 376 `----------------------*/ 
 378 /* Initial capacity of symbols hash table.  */ 
 379 #define HT_INITIAL_CAPACITY 257 
 381 static struct hash_table 
*symbol_table 
= NULL
; 
 384 hash_compare_symbol_t (const symbol_t 
*m1
, const symbol_t 
*m2
) 
 386   return strcmp (m1
->tag
, m2
->tag
) == 0; 
 390 hash_symbol_t (const symbol_t 
*m
, unsigned int tablesize
) 
 392   return hash_string (m
->tag
, tablesize
); 
 396 /*-------------------------------. 
 397 | Create the symbol hash table.  | 
 398 `-------------------------------*/ 
 403   symbol_table 
= hash_initialize (HT_INITIAL_CAPACITY
, 
 405                                   (Hash_hasher
) hash_symbol_t
, 
 406                                   (Hash_comparator
) hash_compare_symbol_t
, 
 407                                   (Hash_data_freer
) symbol_free
); 
 411 /*----------------------------------------------------------------. 
 412 | Find the symbol named KEY, and return it.  If it does not exist | 
 414 `----------------------------------------------------------------*/ 
 417 symbol_get (const char *key
, location_t location
) 
 422   /* Keep the symbol in a printable form.  */ 
 423   key 
= quotearg_style (escape_quoting_style
, key
); 
 424   *(char const **) &probe
.tag 
= key
; 
 425   entry 
= hash_lookup (symbol_table
, &probe
); 
 429       /* First insertion in the hash. */ 
 430       entry 
= symbol_new (key
, location
); 
 431       hash_insert (symbol_table
, entry
); 
 437 /*------------------------------------------------------------------. 
 438 | Generate a dummy nonterminal, whose name cannot conflict with the | 
 440 `------------------------------------------------------------------*/ 
 443 dummy_symbol_get (location_t location
) 
 445   /* Incremented for each generated symbol.  */ 
 446   static int dummy_count 
= 0; 
 447   static char buf
[256]; 
 451   sprintf (buf
, "@%d", ++dummy_count
); 
 452   sym 
= symbol_get (buf
, location
); 
 453   sym
->class = nterm_sym
; 
 454   sym
->number 
= nvars
++; 
 459 /*-------------------. 
 460 | Free the symbols.  | 
 461 `-------------------*/ 
 466   hash_free (symbol_table
); 
 471 /*---------------------------------------------------------------. 
 472 | Look for undefined symbols, report an error, and consider them | 
 474 `---------------------------------------------------------------*/ 
 477 symbols_do (symbol_processor processor
, void *processor_data
) 
 479   hash_do_for_each (symbol_table
, 
 480                     (Hash_processor
) processor
, 
 485 /*--------------------------------------------------------------. 
 486 | Check that all the symbols are defined.  Report any undefined | 
 487 | symbols and consider them nonterminals.                       | 
 488 `--------------------------------------------------------------*/ 
 491 symbols_check_defined (void) 
 493   symbols_do (symbol_check_defined
, NULL
); 
 496 /*------------------------------------------------------------------. 
 497 | Set TOKEN_TRANSLATIONS.  Check that no two symbols share the same | 
 499 `------------------------------------------------------------------*/ 
 502 symbols_token_translations_init (void) 
 504   bool num_256_available_p 
= true; 
 507   /* Find the highest user token number, and whether 256, the POSIX 
 508      preferred user token number for the error token, is used.  */ 
 509   max_user_token_number 
= 0; 
 510   for (i 
= 0; i 
< ntokens
; ++i
) 
 512       symbol_t 
*this = symbols
[i
]; 
 513       if (this->user_token_number 
!= USER_NUMBER_UNDEFINED
) 
 515           if (this->user_token_number 
> max_user_token_number
) 
 516             max_user_token_number 
= this->user_token_number
; 
 517           if (this->user_token_number 
== 256) 
 518             num_256_available_p 
= false; 
 522   /* If 256 is not used, assign it to error, to follow POSIX.  */ 
 523   if (num_256_available_p
 
 524       && errtoken
->user_token_number 
== USER_NUMBER_UNDEFINED
) 
 525     errtoken
->user_token_number 
= 256; 
 527   /* Set the missing user numbers. */ 
 528   if (max_user_token_number 
< 256) 
 529     max_user_token_number 
= 256; 
 531   for (i 
= 0; i 
< ntokens
; ++i
) 
 533       symbol_t 
*this = symbols
[i
]; 
 534       if (this->user_token_number 
== USER_NUMBER_UNDEFINED
) 
 535         this->user_token_number 
= ++max_user_token_number
; 
 536       if (this->user_token_number 
> max_user_token_number
) 
 537         max_user_token_number 
= this->user_token_number
; 
 540   token_translations 
= XCALLOC (symbol_number_t
, max_user_token_number 
+ 1); 
 542   /* Initialize all entries for literal tokens to 2, the internal 
 543      token number for $undefined, which represents all invalid inputs. 
 545   for (i 
= 0; i 
< max_user_token_number 
+ 1; i
++) 
 546     token_translations
[i
] = undeftoken
->number
; 
 547   symbols_do (symbol_translation
, NULL
); 
 551 /*----------------------------------------------------------------. 
 552 | Assign symbol numbers, and write definition of token names into | 
 553 | FDEFINES.  Set up vectors SYMBOL_TABLE, TAGS of symbols.        | 
 554 `----------------------------------------------------------------*/ 
 559   symbols 
= XCALLOC (symbol_t 
*, nsyms
); 
 561   symbols_do (symbol_check_alias_consistence
, NULL
); 
 562   symbols_do (symbol_pack
, NULL
); 
 564   symbols_token_translations_init (); 
 566   if (startsymbol
->class == unknown_sym
) 
 567     fatal_at (startsymbol_location
, 
 568               _("the start symbol %s is undefined"), 
 570   else if (startsymbol
->class == token_sym
) 
 571     fatal_at (startsymbol_location
, 
 572               _("the start symbol %s is a token"),