]> git.saurik.com Git - bison.git/blame - src/symtab.c
Use size_t (not unsigned int) for hashes, since the gnulib hash module
[bison.git] / src / symtab.c
CommitLineData
0fb1efaf
PE
1/* Symbol table manager for Bison.
2
233a88ad
PE
3 Copyright (C) 1984, 1989, 2000, 2001, 2002, 2004 Free Software
4 Foundation, Inc.
40675e7c 5
95e36146 6 This file is part of Bison, the GNU Compiler Compiler.
40675e7c 7
95e36146
AD
8 Bison is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
40675e7c 12
95e36146
AD
13 Bison is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
40675e7c 17
95e36146
AD
18 You should have received a copy of the GNU General Public License
19 along with Bison; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
40675e7c
DM
22
23
40675e7c 24#include "system.h"
17ee7397
PE
25
26#include <hash.h>
27#include <quotearg.h>
28
2f1afb73 29#include "complain.h"
40675e7c 30#include "gram.h"
17ee7397 31#include "symtab.h"
40675e7c 32
2f1afb73
AD
33/*------------------------.
34| Distinguished symbols. |
35`------------------------*/
36
17ee7397
PE
37symbol *errtoken = NULL;
38symbol *undeftoken = NULL;
39symbol *endtoken = NULL;
40symbol *accept = NULL;
41symbol *startsymbol = NULL;
42location startsymbol_location;
2f1afb73 43
72a23c97
AD
44/*---------------------------------.
45| Create a new symbol, named TAG. |
46`---------------------------------*/
1e9798d5 47
17ee7397
PE
48static symbol *
49symbol_new (uniqstr tag, location loc)
1e9798d5 50{
0fb1efaf 51 symbol *res = MALLOC (res, 1);
1e9798d5 52
17ee7397 53 uniqstr_assert (tag);
95612cfa 54 res->tag = tag;
17ee7397 55 res->location = loc;
24c0aad7 56
1e9798d5 57 res->type_name = NULL;
9280d3ef 58 res->destructor = NULL;
260008e5 59 res->printer = NULL;
24c0aad7 60
5fbb0954 61 res->number = NUMBER_UNDEFINED;
1e9798d5 62 res->prec = 0;
a945ec39 63 res->assoc = undef_assoc;
b87f8b21 64 res->user_token_number = USER_NUMBER_UNDEFINED;
260008e5 65
1e9798d5
AD
66 res->alias = NULL;
67 res->class = unknown_sym;
68
69 nsyms++;
1e9798d5
AD
70 return res;
71}
72
40675e7c 73
17ee7397
PE
74/*-----------------------------------------------------------------.
75| Set the TYPE_NAME associated with SYM. Does nothing if passed 0 |
76| as TYPE_NAME. |
77`-----------------------------------------------------------------*/
3ae2b51f
AD
78
79void
17ee7397 80symbol_type_set (symbol *sym, uniqstr type_name, location loc)
3ae2b51f 81{
e9955c83
AD
82 if (type_name)
83 {
17ee7397
PE
84 if (sym->type_name)
85 complain_at (loc, _("type redeclaration for %s"), sym->tag);
86 uniqstr_assert (type_name);
87 sym->type_name = type_name;
e9955c83 88 }
3ae2b51f
AD
89}
90
91
17ee7397
PE
92/*------------------------------------------------------------------.
93| Set the DESTRUCTOR associated with SYM. Do nothing if passed 0. |
94`------------------------------------------------------------------*/
9280d3ef
AD
95
96void
17ee7397 97symbol_destructor_set (symbol *sym, char *destructor, location loc)
9280d3ef
AD
98{
99 if (destructor)
100 {
17ee7397
PE
101 if (sym->destructor)
102 complain_at (loc, _("%s redeclaration for %s"),
103 "%destructor", sym->tag);
104 sym->destructor = destructor;
105 sym->destructor_location = loc;
9280d3ef
AD
106 }
107}
108
109
17ee7397
PE
110/*---------------------------------------------------------------.
111| Set the PRINTER associated with SYM. Do nothing if passed 0. |
112`---------------------------------------------------------------*/
366eea36
AD
113
114void
17ee7397 115symbol_printer_set (symbol *sym, char *printer, location loc)
366eea36
AD
116{
117 if (printer)
118 {
17ee7397
PE
119 if (sym->printer)
120 complain_at (loc, _("%s redeclaration for %s"),
121 "%printer", sym->tag);
122 sym->printer = printer;
123 sym->printer_location = loc;
366eea36
AD
124 }
125}
126
127
17ee7397
PE
128/*-----------------------------------------------------------------.
129| Set the PRECEDENCE associated with SYM. Does nothing if invoked |
130| with UNDEF_ASSOC as ASSOC. |
131`-----------------------------------------------------------------*/
3ae2b51f
AD
132
133void
17ee7397 134symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
3ae2b51f 135{
17ee7397 136 if (a != undef_assoc)
e9955c83 137 {
17ee7397
PE
138 if (sym->prec != 0)
139 complain_at (loc, _("redefining precedence of %s"), sym->tag);
140 sym->prec = prec;
141 sym->assoc = a;
e9955c83
AD
142 }
143
144 /* Only terminals have a precedence. */
17ee7397 145 symbol_class_set (sym, token_sym, loc);
3ae2b51f
AD
146}
147
148
17ee7397
PE
149/*------------------------------------.
150| Set the CLASS associated with SYM. |
151`------------------------------------*/
44536b35
AD
152
153void
17ee7397 154symbol_class_set (symbol *sym, symbol_class class, location loc)
44536b35 155{
17ee7397
PE
156 if (sym->class != unknown_sym && sym->class != class)
157 complain_at (loc, _("symbol %s redefined"), sym->tag);
44536b35 158
17ee7397
PE
159 if (class == nterm_sym && sym->class != nterm_sym)
160 sym->number = nvars++;
161 else if (class == token_sym && sym->number == NUMBER_UNDEFINED)
162 sym->number = ntokens++;
44536b35 163
17ee7397 164 sym->class = class;
44536b35
AD
165}
166
167
17ee7397
PE
168/*------------------------------------------------.
169| Set the USER_TOKEN_NUMBER associated with SYM. |
170`------------------------------------------------*/
44536b35
AD
171
172void
17ee7397 173symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
44536b35 174{
17ee7397 175 if (sym->class != token_sym)
2f82502a 176 abort ();
44536b35 177
17ee7397
PE
178 if (sym->user_token_number != USER_NUMBER_UNDEFINED
179 && sym->user_token_number != user_token_number)
180 complain_at (loc, _("redefining user token number of %s"), sym->tag);
44536b35 181
17ee7397 182 sym->user_token_number = user_token_number;
88bce5a2 183 /* User defined $end token? */
44536b35
AD
184 if (user_token_number == 0)
185 {
17ee7397 186 endtoken = sym;
88bce5a2 187 endtoken->number = 0;
44536b35
AD
188 /* It is always mapped to 0, so it was already counted in
189 NTOKENS. */
190 --ntokens;
191 }
192}
193
194
17ee7397
PE
195/*----------------------------------------------------------.
196| If SYM is not defined, report an error, and consider it a |
197| nonterminal. |
198`----------------------------------------------------------*/
2f1afb73 199
0fb1efaf 200static inline bool
17ee7397 201symbol_check_defined (symbol *sym)
2f1afb73 202{
17ee7397 203 if (sym->class == unknown_sym)
2f1afb73 204 {
ee000ba4 205 complain_at
17ee7397 206 (sym->location,
ee000ba4 207 _("symbol %s is used, but is not defined as a token and has no rules"),
17ee7397
PE
208 sym->tag);
209 sym->class = nterm_sym;
210 sym->number = nvars++;
2f1afb73
AD
211 }
212
a3714bce 213 return true;
2f1afb73
AD
214}
215
0fb1efaf
PE
216static bool
217symbol_check_defined_processor (void *sym, void *null ATTRIBUTE_UNUSED)
218{
219 return symbol_check_defined (sym);
220}
221
2f1afb73 222
17ee7397
PE
223/*------------------------------------------------------------------.
224| Declare the new symbol SYM. Make it an alias of SYMVAL, and type |
527203e9 225| SYMVAL with SYM's type. |
17ee7397 226`------------------------------------------------------------------*/
2f1afb73
AD
227
228void
17ee7397 229symbol_make_alias (symbol *sym, symbol *symval, location loc)
2f1afb73
AD
230{
231 if (symval->alias)
a5d50994 232 warn_at (loc, _("symbol `%s' used more than once as a literal string"),
97650f4e 233 symval->tag);
17ee7397 234 else if (sym->alias)
a5d50994 235 warn_at (loc, _("symbol `%s' given more than one literal string"),
17ee7397 236 sym->tag);
2f1afb73
AD
237 else
238 {
239 symval->class = token_sym;
17ee7397
PE
240 symval->user_token_number = sym->user_token_number;
241 sym->user_token_number = USER_NUMBER_ALIAS;
242 symval->alias = sym;
243 sym->alias = symval;
244 /* sym and symval combined are only one symbol. */
2f1afb73
AD
245 nsyms--;
246 ntokens--;
17ee7397 247 if (ntokens != sym->number && ntokens != symval->number)
2f82502a 248 abort ();
17ee7397
PE
249 sym->number = symval->number =
250 (symval->number < sym->number) ? symval->number : sym->number;
527203e9 251 symbol_type_set (symval, sym->type_name, loc);
2f1afb73
AD
252 }
253}
254
255
256/*---------------------------------------------------------.
257| Check that THIS, and its alias, have same precedence and |
258| associativity. |
259`---------------------------------------------------------*/
260
0fb1efaf
PE
261static inline bool
262symbol_check_alias_consistency (symbol *this)
2f1afb73
AD
263{
264 /* Check only those who _are_ the aliases. */
265 if (this->alias && this->user_token_number == USER_NUMBER_ALIAS)
266 {
267 if (this->prec != this->alias->prec)
268 {
269 if (this->prec != 0 && this->alias->prec != 0)
a5d50994
AD
270 complain_at (this->alias->location,
271 _("conflicting precedences for %s and %s"),
272 this->tag, this->alias->tag);
2f1afb73
AD
273 if (this->prec != 0)
274 this->alias->prec = this->prec;
275 else
276 this->prec = this->alias->prec;
277 }
278
279 if (this->assoc != this->alias->assoc)
280 {
a945ec39 281 if (this->assoc != undef_assoc && this->alias->assoc != undef_assoc)
a5d50994 282 complain_at (this->alias->location,
a945ec39
AD
283 _("conflicting associativities for %s (%s) and %s (%s)"),
284 this->tag, assoc_to_string (this->assoc),
285 this->alias->tag, assoc_to_string (this->alias->assoc));
286 if (this->assoc != undef_assoc)
2f1afb73
AD
287 this->alias->assoc = this->assoc;
288 else
289 this->assoc = this->alias->assoc;
290 }
291 }
a3714bce 292 return true;
2f1afb73
AD
293}
294
0fb1efaf
PE
295static bool
296symbol_check_alias_consistency_processor (void *this,
297 void *null ATTRIBUTE_UNUSED)
298{
299 return symbol_check_alias_consistency (this);
300}
301
2f1afb73
AD
302
303/*-------------------------------------------------------------------.
304| Assign a symbol number, and write the definition of the token name |
305| into FDEFINES. Put in SYMBOLS. |
306`-------------------------------------------------------------------*/
307
0fb1efaf 308static inline bool
17ee7397 309symbol_pack (symbol *this)
2f1afb73
AD
310{
311 if (this->class == nterm_sym)
312 {
313 this->number += ntokens;
314 }
315 else if (this->alias)
316 {
317 /* This symbol and its alias are a single token defn.
318 Allocate a tokno, and assign to both check agreement of
319 prec and assoc fields and make both the same */
320 if (this->number == NUMBER_UNDEFINED)
321 {
88bce5a2 322 if (this == endtoken || this->alias == endtoken)
2f1afb73
AD
323 this->number = this->alias->number = 0;
324 else
325 {
2f82502a
PE
326 if (this->alias->number == NUMBER_UNDEFINED)
327 abort ();
2f1afb73
AD
328 this->number = this->alias->number;
329 }
330 }
b9e00562 331 /* Do not do processing below for USER_NUMBER_ALIASes. */
2f1afb73 332 if (this->user_token_number == USER_NUMBER_ALIAS)
a3714bce 333 return true;
2f1afb73
AD
334 }
335 else /* this->class == token_sym */
336 {
2f82502a
PE
337 if (this->number == NUMBER_UNDEFINED)
338 abort ();
2f1afb73
AD
339 }
340
341 symbols[this->number] = this;
a3714bce 342 return true;
2f1afb73
AD
343}
344
0fb1efaf
PE
345static bool
346symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
347{
348 return symbol_pack (this);
349}
350
2f1afb73
AD
351
352
353
354/*--------------------------------------------------.
355| Put THIS in TOKEN_TRANSLATIONS if it is a token. |
356`--------------------------------------------------*/
357
0fb1efaf 358static inline bool
17ee7397 359symbol_translation (symbol *this)
2f1afb73
AD
360{
361 /* Non-terminal? */
362 if (this->class == token_sym
363 && this->user_token_number != USER_NUMBER_ALIAS)
364 {
365 /* A token which translation has already been set? */
366 if (token_translations[this->user_token_number] != undeftoken->number)
a5d50994
AD
367 complain_at (this->location,
368 _("tokens %s and %s both assigned number %d"),
369 symbols[token_translations[this->user_token_number]]->tag,
370 this->tag, this->user_token_number);
2f1afb73
AD
371
372 token_translations[this->user_token_number] = this->number;
373 }
374
a3714bce 375 return true;
2f1afb73
AD
376}
377
0fb1efaf
PE
378static bool
379symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
380{
381 return symbol_translation (this);
382}
383
72a23c97
AD
384
385/*----------------------.
2f1afb73 386| A symbol hash table. |
72a23c97 387`----------------------*/
40675e7c 388
db8837cb 389/* Initial capacity of symbols hash table. */
72a23c97
AD
390#define HT_INITIAL_CAPACITY 257
391
db8837cb 392static struct hash_table *symbol_table = NULL;
72a23c97 393
0fb1efaf 394static inline bool
17ee7397 395hash_compare_symbol (const symbol *m1, const symbol *m2)
72a23c97 396{
95612cfa 397 /* Since tags are unique, we can compare the pointers themselves. */
17ee7397 398 return UNIQSTR_EQ (m1->tag, m2->tag);
72a23c97
AD
399}
400
0fb1efaf
PE
401static bool
402hash_symbol_comparator (void const *m1, void const *m2)
403{
404 return hash_compare_symbol (m1, m2);
405}
406
233a88ad
PE
407static inline size_t
408hash_symbol (const symbol *m, size_t tablesize)
72a23c97 409{
95612cfa 410 /* Since tags are unique, we can hash the pointer itself. */
0fb1efaf
PE
411 return ((uintptr_t) m->tag) % tablesize;
412}
413
233a88ad
PE
414static size_t
415hash_symbol_hasher (void const *m, size_t tablesize)
0fb1efaf
PE
416{
417 return hash_symbol (m, tablesize);
72a23c97
AD
418}
419
420
421/*-------------------------------.
2f1afb73 422| Create the symbol hash table. |
72a23c97
AD
423`-------------------------------*/
424
425void
db8837cb 426symbols_new (void)
72a23c97 427{
db8837cb 428 symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
72a23c97 429 NULL,
0fb1efaf
PE
430 hash_symbol_hasher,
431 hash_symbol_comparator,
432 free);
40675e7c
DM
433}
434
435
1e9798d5
AD
436/*----------------------------------------------------------------.
437| Find the symbol named KEY, and return it. If it does not exist |
438| yet, create it. |
439`----------------------------------------------------------------*/
440
17ee7397
PE
441symbol *
442symbol_get (const char *key, location loc)
40675e7c 443{
17ee7397
PE
444 symbol probe;
445 symbol *entry;
40675e7c 446
97650f4e 447 /* Keep the symbol in a printable form. */
17ee7397 448 key = uniqstr_new (quotearg_style (escape_quoting_style, key));
0fb1efaf 449 probe.tag = key;
db8837cb 450 entry = hash_lookup (symbol_table, &probe);
40675e7c 451
72a23c97 452 if (!entry)
40675e7c 453 {
72a23c97 454 /* First insertion in the hash. */
17ee7397 455 entry = symbol_new (key, loc);
db8837cb 456 hash_insert (symbol_table, entry);
40675e7c 457 }
72a23c97
AD
458 return entry;
459}
40675e7c 460
40675e7c 461
39f41916
AD
462/*------------------------------------------------------------------.
463| Generate a dummy nonterminal, whose name cannot conflict with the |
464| user's names. |
465`------------------------------------------------------------------*/
466
17ee7397
PE
467symbol *
468dummy_symbol_get (location loc)
39f41916
AD
469{
470 /* Incremented for each generated symbol. */
471 static int dummy_count = 0;
472 static char buf[256];
473
17ee7397 474 symbol *sym;
39f41916
AD
475
476 sprintf (buf, "@%d", ++dummy_count);
17ee7397 477 sym = symbol_get (buf, loc);
39f41916
AD
478 sym->class = nterm_sym;
479 sym->number = nvars++;
480 return sym;
481}
482
483
72a23c97 484/*-------------------.
db8837cb 485| Free the symbols. |
72a23c97
AD
486`-------------------*/
487
488void
db8837cb 489symbols_free (void)
72a23c97 490{
db8837cb 491 hash_free (symbol_table);
536545f3 492 free (symbols);
40675e7c
DM
493}
494
495
72a23c97 496/*---------------------------------------------------------------.
db8837cb 497| Look for undefined symbols, report an error, and consider them |
72a23c97
AD
498| terminals. |
499`---------------------------------------------------------------*/
500
0fb1efaf
PE
501static void
502symbols_do (Hash_processor processor, void *processor_data)
40675e7c 503{
0fb1efaf 504 hash_do_for_each (symbol_table, processor, processor_data);
40675e7c 505}
2f1afb73
AD
506
507
508/*--------------------------------------------------------------.
509| Check that all the symbols are defined. Report any undefined |
510| symbols and consider them nonterminals. |
511`--------------------------------------------------------------*/
512
513void
514symbols_check_defined (void)
515{
0fb1efaf 516 symbols_do (symbol_check_defined_processor, NULL);
2f1afb73
AD
517}
518
519/*------------------------------------------------------------------.
520| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
521| number. |
522`------------------------------------------------------------------*/
523
524static void
525symbols_token_translations_init (void)
526{
a3714bce 527 bool num_256_available_p = true;
2f1afb73
AD
528 int i;
529
530 /* Find the highest user token number, and whether 256, the POSIX
531 preferred user token number for the error token, is used. */
532 max_user_token_number = 0;
533 for (i = 0; i < ntokens; ++i)
534 {
17ee7397 535 symbol *this = symbols[i];
2f1afb73
AD
536 if (this->user_token_number != USER_NUMBER_UNDEFINED)
537 {
538 if (this->user_token_number > max_user_token_number)
539 max_user_token_number = this->user_token_number;
540 if (this->user_token_number == 256)
a3714bce 541 num_256_available_p = false;
2f1afb73
AD
542 }
543 }
544
545 /* If 256 is not used, assign it to error, to follow POSIX. */
546 if (num_256_available_p
547 && errtoken->user_token_number == USER_NUMBER_UNDEFINED)
548 errtoken->user_token_number = 256;
549
550 /* Set the missing user numbers. */
551 if (max_user_token_number < 256)
552 max_user_token_number = 256;
553
554 for (i = 0; i < ntokens; ++i)
555 {
17ee7397 556 symbol *this = symbols[i];
2f1afb73
AD
557 if (this->user_token_number == USER_NUMBER_UNDEFINED)
558 this->user_token_number = ++max_user_token_number;
559 if (this->user_token_number > max_user_token_number)
560 max_user_token_number = this->user_token_number;
561 }
562
0fb1efaf 563 CALLOC (token_translations, max_user_token_number + 1);
2f1afb73
AD
564
565 /* Initialize all entries for literal tokens to 2, the internal
88bce5a2
AD
566 token number for $undefined, which represents all invalid inputs.
567 */
2f1afb73
AD
568 for (i = 0; i < max_user_token_number + 1; i++)
569 token_translations[i] = undeftoken->number;
0fb1efaf 570 symbols_do (symbol_translation_processor, NULL);
2f1afb73
AD
571}
572
573
574/*----------------------------------------------------------------.
575| Assign symbol numbers, and write definition of token names into |
576| FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. |
577`----------------------------------------------------------------*/
578
579void
580symbols_pack (void)
581{
0fb1efaf 582 CALLOC (symbols, nsyms);
2f1afb73 583
0fb1efaf
PE
584 symbols_do (symbol_check_alias_consistency_processor, NULL);
585 symbols_do (symbol_pack_processor, NULL);
2f1afb73
AD
586
587 symbols_token_translations_init ();
588
589 if (startsymbol->class == unknown_sym)
ee000ba4 590 fatal_at (startsymbol_location,
dafdc66f 591 _("the start symbol %s is undefined"),
97650f4e 592 startsymbol->tag);
2f1afb73 593 else if (startsymbol->class == token_sym)
ee000ba4 594 fatal_at (startsymbol_location,
dafdc66f 595 _("the start symbol %s is a token"),
97650f4e 596 startsymbol->tag);
2f1afb73 597}