1 /* Symbol table manager for Bison. 
   3    Copyright (C) 1984, 1989, 2000, 2001, 2002 Free Software Foundation, Inc. 
   5    This file is part of Bison, the GNU Compiler Compiler. 
   7    Bison is free software; you can redistribute it and/or modify 
   8    it under the terms of the GNU General Public License as published by 
   9    the Free Software Foundation; either version 2, or (at your option) 
  12    Bison is distributed in the hope that it will be useful, 
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15    GNU General Public License for more details. 
  17    You should have received a copy of the GNU General Public License 
  18    along with Bison; see the file COPYING.  If not, write to 
  19    the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
  20    Boston, MA 02111-1307, USA.  */ 
  32 /*------------------------. 
  33 | Distinguished symbols.  | 
  34 `------------------------*/ 
  36 symbol 
*errtoken 
= NULL
; 
  37 symbol 
*undeftoken 
= NULL
; 
  38 symbol 
*endtoken 
= NULL
; 
  39 symbol 
*accept 
= NULL
; 
  40 symbol 
*startsymbol 
= NULL
; 
  41 location startsymbol_location
; 
  43 /*---------------------------------. 
  44 | Create a new symbol, named TAG.  | 
  45 `---------------------------------*/ 
  48 symbol_new (uniqstr tag
, location loc
) 
  50   symbol 
*res 
= MALLOC (res
, 1); 
  56   res
->type_name 
= NULL
; 
  57   res
->destructor 
= NULL
; 
  60   res
->number 
= NUMBER_UNDEFINED
; 
  62   res
->assoc 
= undef_assoc
; 
  63   res
->user_token_number 
= USER_NUMBER_UNDEFINED
; 
  66   res
->class = unknown_sym
; 
  73 /*-----------------------------------------------------------------. 
  74 | Set the TYPE_NAME associated with SYM.  Does nothing if passed 0 | 
  76 `-----------------------------------------------------------------*/ 
  79 symbol_type_set (symbol 
*sym
, uniqstr type_name
, location loc
) 
  84         complain_at (loc
, _("type redeclaration for %s"), sym
->tag
); 
  85       uniqstr_assert (type_name
); 
  86       sym
->type_name 
= type_name
; 
  91 /*------------------------------------------------------------------. 
  92 | Set the DESTRUCTOR associated with SYM.  Do nothing if passed 0.  | 
  93 `------------------------------------------------------------------*/ 
  96 symbol_destructor_set (symbol 
*sym
, char *destructor
, location loc
) 
 101         complain_at (loc
, _("%s redeclaration for %s"), 
 102                      "%destructor", sym
->tag
); 
 103       sym
->destructor 
= destructor
; 
 104       sym
->destructor_location 
= loc
; 
 109 /*---------------------------------------------------------------. 
 110 | Set the PRINTER associated with SYM.  Do nothing if passed 0.  | 
 111 `---------------------------------------------------------------*/ 
 114 symbol_printer_set (symbol 
*sym
, char *printer
, location loc
) 
 119         complain_at (loc
, _("%s redeclaration for %s"), 
 120                      "%printer", sym
->tag
); 
 121       sym
->printer 
= printer
; 
 122       sym
->printer_location 
= loc
; 
 127 /*-----------------------------------------------------------------. 
 128 | Set the PRECEDENCE associated with SYM.  Does nothing if invoked | 
 129 | with UNDEF_ASSOC as ASSOC.                                       | 
 130 `-----------------------------------------------------------------*/ 
 133 symbol_precedence_set (symbol 
*sym
, int prec
, assoc a
, location loc
) 
 135   if (a 
!= undef_assoc
) 
 138         complain_at (loc
, _("redefining precedence of %s"), sym
->tag
); 
 143   /* Only terminals have a precedence. */ 
 144   symbol_class_set (sym
, token_sym
, loc
); 
 148 /*------------------------------------. 
 149 | Set the CLASS associated with SYM.  | 
 150 `------------------------------------*/ 
 153 symbol_class_set (symbol 
*sym
, symbol_class 
class, location loc
) 
 155   if (sym
->class != unknown_sym 
&& sym
->class != class) 
 156     complain_at (loc
, _("symbol %s redefined"), sym
->tag
); 
 158   if (class == nterm_sym 
&& sym
->class != nterm_sym
) 
 159     sym
->number 
= nvars
++; 
 160   else if (class == token_sym 
&& sym
->number 
== NUMBER_UNDEFINED
) 
 161     sym
->number 
= ntokens
++; 
 167 /*------------------------------------------------. 
 168 | Set the USER_TOKEN_NUMBER associated with SYM.  | 
 169 `------------------------------------------------*/ 
 172 symbol_user_token_number_set (symbol 
*sym
, int user_token_number
, location loc
) 
 174   if (sym
->class != token_sym
) 
 177   if (sym
->user_token_number 
!= USER_NUMBER_UNDEFINED
 
 178       && sym
->user_token_number 
!= user_token_number
) 
 179     complain_at (loc
, _("redefining user token number of %s"), sym
->tag
); 
 181   sym
->user_token_number 
= user_token_number
; 
 182   /* User defined $end token? */ 
 183   if (user_token_number 
== 0) 
 186       endtoken
->number 
= 0; 
 187       /* It is always mapped to 0, so it was already counted in 
 194 /*----------------------------------------------------------. 
 195 | If SYM is not defined, report an error, and consider it a | 
 197 `----------------------------------------------------------*/ 
 200 symbol_check_defined (symbol 
*sym
) 
 202   if (sym
->class == unknown_sym
) 
 206          _("symbol %s is used, but is not defined as a token and has no rules"), 
 208       sym
->class = nterm_sym
; 
 209       sym
->number 
= nvars
++; 
 216 symbol_check_defined_processor (void *sym
, void *null ATTRIBUTE_UNUSED
) 
 218   return symbol_check_defined (sym
); 
 222 /*------------------------------------------------------------------. 
 223 | Declare the new symbol SYM.  Make it an alias of SYMVAL, and type | 
 224 | SYMVAL with SYM's type.                                           | 
 225 `------------------------------------------------------------------*/ 
 228 symbol_make_alias (symbol 
*sym
, symbol 
*symval
, location loc
) 
 231     warn_at (loc
, _("symbol `%s' used more than once as a literal string"), 
 234     warn_at (loc
, _("symbol `%s' given more than one literal string"), 
 238       symval
->class = token_sym
; 
 239       symval
->user_token_number 
= sym
->user_token_number
; 
 240       sym
->user_token_number 
= USER_NUMBER_ALIAS
; 
 243       /* sym and symval combined are only one symbol.  */ 
 246       if (ntokens 
!= sym
->number 
&& ntokens 
!= symval
->number
) 
 248       sym
->number 
= symval
->number 
= 
 249         (symval
->number 
< sym
->number
) ? symval
->number 
: sym
->number
; 
 250       symbol_type_set (symval
, sym
->type_name
, loc
); 
 255 /*---------------------------------------------------------. 
 256 | Check that THIS, and its alias, have same precedence and | 
 258 `---------------------------------------------------------*/ 
 261 symbol_check_alias_consistency (symbol 
*this) 
 263   /* Check only those who _are_ the aliases. */ 
 264   if (this->alias 
&& this->user_token_number 
== USER_NUMBER_ALIAS
) 
 266       if (this->prec 
!= this->alias
->prec
) 
 268           if (this->prec 
!= 0 && this->alias
->prec 
!= 0) 
 269             complain_at (this->alias
->location
, 
 270                          _("conflicting precedences for %s and %s"), 
 271                          this->tag
, this->alias
->tag
); 
 273             this->alias
->prec 
= this->prec
; 
 275             this->prec 
= this->alias
->prec
; 
 278       if (this->assoc 
!= this->alias
->assoc
) 
 280           if (this->assoc 
!= undef_assoc 
&& this->alias
->assoc 
!= undef_assoc
) 
 281             complain_at (this->alias
->location
, 
 282                          _("conflicting associativities for %s (%s) and %s (%s)"), 
 283                          this->tag
, assoc_to_string (this->assoc
), 
 284                          this->alias
->tag
, assoc_to_string (this->alias
->assoc
)); 
 285           if (this->assoc 
!= undef_assoc
) 
 286             this->alias
->assoc 
= this->assoc
; 
 288             this->assoc 
= this->alias
->assoc
; 
 295 symbol_check_alias_consistency_processor (void *this, 
 296                                           void *null ATTRIBUTE_UNUSED
) 
 298   return symbol_check_alias_consistency (this); 
 302 /*-------------------------------------------------------------------. 
 303 | Assign a symbol number, and write the definition of the token name | 
 304 | into FDEFINES.  Put in SYMBOLS.                                    | 
 305 `-------------------------------------------------------------------*/ 
 308 symbol_pack (symbol 
*this) 
 310   if (this->class == nterm_sym
) 
 312       this->number 
+= ntokens
; 
 314   else if (this->alias
) 
 316       /* This symbol and its alias are a single token defn. 
 317          Allocate a tokno, and assign to both check agreement of 
 318          prec and assoc fields and make both the same */ 
 319       if (this->number 
== NUMBER_UNDEFINED
) 
 321           if (this == endtoken 
|| this->alias 
== endtoken
) 
 322             this->number 
= this->alias
->number 
= 0; 
 325               if (this->alias
->number 
== NUMBER_UNDEFINED
) 
 327               this->number 
= this->alias
->number
; 
 330       /* Do not do processing below for USER_NUMBER_ALIASes.  */ 
 331       if (this->user_token_number 
== USER_NUMBER_ALIAS
) 
 334   else /* this->class == token_sym */ 
 336       if (this->number 
== NUMBER_UNDEFINED
) 
 340   symbols
[this->number
] = this; 
 345 symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED
) 
 347   return symbol_pack (this); 
 353 /*--------------------------------------------------. 
 354 | Put THIS in TOKEN_TRANSLATIONS if it is a token.  | 
 355 `--------------------------------------------------*/ 
 358 symbol_translation (symbol 
*this) 
 361   if (this->class == token_sym
 
 362       && this->user_token_number 
!= USER_NUMBER_ALIAS
) 
 364       /* A token which translation has already been set? */ 
 365       if (token_translations
[this->user_token_number
] != undeftoken
->number
) 
 366         complain_at (this->location
, 
 367                      _("tokens %s and %s both assigned number %d"), 
 368                      symbols
[token_translations
[this->user_token_number
]]->tag
, 
 369                      this->tag
, this->user_token_number
); 
 371       token_translations
[this->user_token_number
] = this->number
; 
 378 symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED
) 
 380   return symbol_translation (this); 
 384 /*----------------------. 
 385 | A symbol hash table.  | 
 386 `----------------------*/ 
 388 /* Initial capacity of symbols hash table.  */ 
 389 #define HT_INITIAL_CAPACITY 257 
 391 static struct hash_table 
*symbol_table 
= NULL
; 
 394 hash_compare_symbol (const symbol 
*m1
, const symbol 
*m2
) 
 396   /* Since tags are unique, we can compare the pointers themselves.  */ 
 397   return UNIQSTR_EQ (m1
->tag
, m2
->tag
); 
 401 hash_symbol_comparator (void const *m1
, void const *m2
) 
 403   return hash_compare_symbol (m1
, m2
); 
 406 static inline unsigned int 
 407 hash_symbol (const symbol 
*m
, unsigned int tablesize
) 
 409   /* Since tags are unique, we can hash the pointer itself.  */ 
 410   return ((uintptr_t) m
->tag
) % tablesize
; 
 414 hash_symbol_hasher (void const *m
, unsigned int tablesize
) 
 416   return hash_symbol (m
, tablesize
); 
 420 /*-------------------------------. 
 421 | Create the symbol hash table.  | 
 422 `-------------------------------*/ 
 427   symbol_table 
= hash_initialize (HT_INITIAL_CAPACITY
, 
 430                                   hash_symbol_comparator
, 
 435 /*----------------------------------------------------------------. 
 436 | Find the symbol named KEY, and return it.  If it does not exist | 
 438 `----------------------------------------------------------------*/ 
 441 symbol_get (const char *key
, location loc
) 
 446   /* Keep the symbol in a printable form.  */ 
 447   key 
= uniqstr_new (quotearg_style (escape_quoting_style
, key
)); 
 449   entry 
= hash_lookup (symbol_table
, &probe
); 
 453       /* First insertion in the hash. */ 
 454       entry 
= symbol_new (key
, loc
); 
 455       hash_insert (symbol_table
, entry
); 
 461 /*------------------------------------------------------------------. 
 462 | Generate a dummy nonterminal, whose name cannot conflict with the | 
 464 `------------------------------------------------------------------*/ 
 467 dummy_symbol_get (location loc
) 
 469   /* Incremented for each generated symbol.  */ 
 470   static int dummy_count 
= 0; 
 471   static char buf
[256]; 
 475   sprintf (buf
, "@%d", ++dummy_count
); 
 476   sym 
= symbol_get (buf
, loc
); 
 477   sym
->class = nterm_sym
; 
 478   sym
->number 
= nvars
++; 
 483 /*-------------------. 
 484 | Free the symbols.  | 
 485 `-------------------*/ 
 490   hash_free (symbol_table
); 
 495 /*---------------------------------------------------------------. 
 496 | Look for undefined symbols, report an error, and consider them | 
 498 `---------------------------------------------------------------*/ 
 501 symbols_do (Hash_processor processor
, void *processor_data
) 
 503   hash_do_for_each (symbol_table
, processor
, processor_data
); 
 507 /*--------------------------------------------------------------. 
 508 | Check that all the symbols are defined.  Report any undefined | 
 509 | symbols and consider them nonterminals.                       | 
 510 `--------------------------------------------------------------*/ 
 513 symbols_check_defined (void) 
 515   symbols_do (symbol_check_defined_processor
, NULL
); 
 518 /*------------------------------------------------------------------. 
 519 | Set TOKEN_TRANSLATIONS.  Check that no two symbols share the same | 
 521 `------------------------------------------------------------------*/ 
 524 symbols_token_translations_init (void) 
 526   bool num_256_available_p 
= true; 
 529   /* Find the highest user token number, and whether 256, the POSIX 
 530      preferred user token number for the error token, is used.  */ 
 531   max_user_token_number 
= 0; 
 532   for (i 
= 0; i 
< ntokens
; ++i
) 
 534       symbol 
*this = symbols
[i
]; 
 535       if (this->user_token_number 
!= USER_NUMBER_UNDEFINED
) 
 537           if (this->user_token_number 
> max_user_token_number
) 
 538             max_user_token_number 
= this->user_token_number
; 
 539           if (this->user_token_number 
== 256) 
 540             num_256_available_p 
= false; 
 544   /* If 256 is not used, assign it to error, to follow POSIX.  */ 
 545   if (num_256_available_p
 
 546       && errtoken
->user_token_number 
== USER_NUMBER_UNDEFINED
) 
 547     errtoken
->user_token_number 
= 256; 
 549   /* Set the missing user numbers. */ 
 550   if (max_user_token_number 
< 256) 
 551     max_user_token_number 
= 256; 
 553   for (i 
= 0; i 
< ntokens
; ++i
) 
 555       symbol 
*this = symbols
[i
]; 
 556       if (this->user_token_number 
== USER_NUMBER_UNDEFINED
) 
 557         this->user_token_number 
= ++max_user_token_number
; 
 558       if (this->user_token_number 
> max_user_token_number
) 
 559         max_user_token_number 
= this->user_token_number
; 
 562   CALLOC (token_translations
, max_user_token_number 
+ 1); 
 564   /* Initialize all entries for literal tokens to 2, the internal 
 565      token number for $undefined, which represents all invalid inputs. 
 567   for (i 
= 0; i 
< max_user_token_number 
+ 1; i
++) 
 568     token_translations
[i
] = undeftoken
->number
; 
 569   symbols_do (symbol_translation_processor
, NULL
); 
 573 /*----------------------------------------------------------------. 
 574 | Assign symbol numbers, and write definition of token names into | 
 575 | FDEFINES.  Set up vectors SYMBOL_TABLE, TAGS of symbols.        | 
 576 `----------------------------------------------------------------*/ 
 581   CALLOC (symbols
, nsyms
); 
 583   symbols_do (symbol_check_alias_consistency_processor
, NULL
); 
 584   symbols_do (symbol_pack_processor
, NULL
); 
 586   symbols_token_translations_init (); 
 588   if (startsymbol
->class == unknown_sym
) 
 589     fatal_at (startsymbol_location
, 
 590               _("the start symbol %s is undefined"), 
 592   else if (startsymbol
->class == token_sym
) 
 593     fatal_at (startsymbol_location
, 
 594               _("the start symbol %s is a token"),