]> git.saurik.com Git - bison.git/blame - src/symtab.c
Add copyright notice, and replace "filesystem" with "file system".
[bison.git] / src / symtab.c
CommitLineData
0fb1efaf
PE
1/* Symbol table manager for Bison.
2
073f9288
PE
3 Copyright (C) 1984, 1989, 2000, 2001, 2002, 2004, 2005, 2006 Free
4 Software 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
0fb669f9
PE
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
40675e7c 22
2cec9080 23#include <config.h>
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{
da2a7671 51 symbol *res = xmalloc (sizeof *res);
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;
073f9288 68 res->declared = false;
1e9798d5 69
3239db74
PE
70 if (nsyms == SYMBOL_NUMBER_MAXIMUM)
71 fatal (_("too many symbols in input grammar (limit is %d)"),
72 SYMBOL_NUMBER_MAXIMUM);
1e9798d5 73 nsyms++;
1e9798d5
AD
74 return res;
75}
76
40675e7c 77
867a3e00
AD
78/*-----------------.
79| Print a symbol. |
80`-----------------*/
81
82#define SYMBOL_ATTR_PRINT(Attr) \
83 if (s->Attr) \
ab703f2c 84 fprintf (f, " %s { %s }", #Attr, s->Attr)
867a3e00
AD
85
86void
22dda0f0 87symbol_print (symbol *s, FILE *f)
867a3e00 88{
affac613
AD
89 if (s)
90 {
91 fprintf (f, "\"%s\"", s->tag);
92 SYMBOL_ATTR_PRINT (type_name);
93 SYMBOL_ATTR_PRINT (destructor);
94 SYMBOL_ATTR_PRINT (printer);
95 }
96 else
97 fprintf (f, "<NULL>");
867a3e00
AD
98}
99
100#undef SYMBOL_ATTR_PRINT
101
df09ef2e
AD
102/*------------------------------------------------------------------.
103| Complain that S's WHAT is redeclared at SECOND, and was first set |
104| at FIRST. |
105`------------------------------------------------------------------*/
106
107static void
108redeclaration (symbol* s, const char *what, location first, location second)
109{
110 complain_at (second, _("%s redeclaration for %s"), what, s->tag);
111 complain_at (first, _("first declaration"));
112}
113
114
17ee7397
PE
115/*-----------------------------------------------------------------.
116| Set the TYPE_NAME associated with SYM. Does nothing if passed 0 |
117| as TYPE_NAME. |
118`-----------------------------------------------------------------*/
3ae2b51f
AD
119
120void
17ee7397 121symbol_type_set (symbol *sym, uniqstr type_name, location loc)
3ae2b51f 122{
e9955c83
AD
123 if (type_name)
124 {
17ee7397 125 if (sym->type_name)
df09ef2e 126 redeclaration (sym, "%type", sym->type_location, loc);
17ee7397
PE
127 uniqstr_assert (type_name);
128 sym->type_name = type_name;
df09ef2e 129 sym->type_location = loc;
e9955c83 130 }
3ae2b51f
AD
131}
132
133
17ee7397
PE
134/*------------------------------------------------------------------.
135| Set the DESTRUCTOR associated with SYM. Do nothing if passed 0. |
136`------------------------------------------------------------------*/
9280d3ef
AD
137
138void
c1432f65 139symbol_destructor_set (symbol *sym, const char *destructor, location loc)
9280d3ef
AD
140{
141 if (destructor)
142 {
17ee7397 143 if (sym->destructor)
df09ef2e 144 redeclaration (sym, "%destructor", sym->destructor_location, loc);
17ee7397
PE
145 sym->destructor = destructor;
146 sym->destructor_location = loc;
9280d3ef
AD
147 }
148}
149
150
17ee7397
PE
151/*---------------------------------------------------------------.
152| Set the PRINTER associated with SYM. Do nothing if passed 0. |
153`---------------------------------------------------------------*/
366eea36
AD
154
155void
c1432f65 156symbol_printer_set (symbol *sym, const char *printer, location loc)
366eea36
AD
157{
158 if (printer)
159 {
17ee7397 160 if (sym->printer)
df09ef2e 161 redeclaration (sym, "%printer", sym->destructor_location, loc);
17ee7397
PE
162 sym->printer = printer;
163 sym->printer_location = loc;
366eea36
AD
164 }
165}
166
167
17ee7397
PE
168/*-----------------------------------------------------------------.
169| Set the PRECEDENCE associated with SYM. Does nothing if invoked |
170| with UNDEF_ASSOC as ASSOC. |
171`-----------------------------------------------------------------*/
3ae2b51f
AD
172
173void
17ee7397 174symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
3ae2b51f 175{
17ee7397 176 if (a != undef_assoc)
e9955c83 177 {
17ee7397 178 if (sym->prec != 0)
df09ef2e 179 redeclaration (sym, assoc_to_string (a), sym->prec_location, loc);
17ee7397
PE
180 sym->prec = prec;
181 sym->assoc = a;
df09ef2e 182 sym->prec_location = loc;
e9955c83
AD
183 }
184
185 /* Only terminals have a precedence. */
073f9288 186 symbol_class_set (sym, token_sym, loc, false);
3ae2b51f
AD
187}
188
189
17ee7397
PE
190/*------------------------------------.
191| Set the CLASS associated with SYM. |
192`------------------------------------*/
44536b35
AD
193
194void
073f9288 195symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
44536b35 196{
17ee7397 197 if (sym->class != unknown_sym && sym->class != class)
073f9288
PE
198 {
199 complain_at (loc, _("symbol %s redefined"), sym->tag);
200 sym->declared = false;
201 }
44536b35 202
17ee7397
PE
203 if (class == nterm_sym && sym->class != nterm_sym)
204 sym->number = nvars++;
205 else if (class == token_sym && sym->number == NUMBER_UNDEFINED)
206 sym->number = ntokens++;
44536b35 207
17ee7397 208 sym->class = class;
073f9288
PE
209
210 if (declaring)
211 {
212 if (sym->declared)
213 warn_at (loc, _("symbol %s redeclared"), sym->tag);
214 sym->declared = true;
215 }
44536b35
AD
216}
217
218
17ee7397
PE
219/*------------------------------------------------.
220| Set the USER_TOKEN_NUMBER associated with SYM. |
221`------------------------------------------------*/
44536b35
AD
222
223void
17ee7397 224symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
44536b35 225{
17ee7397 226 if (sym->class != token_sym)
2f82502a 227 abort ();
44536b35 228
17ee7397
PE
229 if (sym->user_token_number != USER_NUMBER_UNDEFINED
230 && sym->user_token_number != user_token_number)
231 complain_at (loc, _("redefining user token number of %s"), sym->tag);
44536b35 232
17ee7397 233 sym->user_token_number = user_token_number;
88bce5a2 234 /* User defined $end token? */
44536b35
AD
235 if (user_token_number == 0)
236 {
17ee7397 237 endtoken = sym;
88bce5a2 238 endtoken->number = 0;
44536b35
AD
239 /* It is always mapped to 0, so it was already counted in
240 NTOKENS. */
241 --ntokens;
242 }
243}
244
245
17ee7397
PE
246/*----------------------------------------------------------.
247| If SYM is not defined, report an error, and consider it a |
248| nonterminal. |
249`----------------------------------------------------------*/
2f1afb73 250
0fb1efaf 251static inline bool
17ee7397 252symbol_check_defined (symbol *sym)
2f1afb73 253{
17ee7397 254 if (sym->class == unknown_sym)
2f1afb73 255 {
ee000ba4 256 complain_at
17ee7397 257 (sym->location,
ee000ba4 258 _("symbol %s is used, but is not defined as a token and has no rules"),
17ee7397
PE
259 sym->tag);
260 sym->class = nterm_sym;
261 sym->number = nvars++;
2f1afb73
AD
262 }
263
a3714bce 264 return true;
2f1afb73
AD
265}
266
0fb1efaf
PE
267static bool
268symbol_check_defined_processor (void *sym, void *null ATTRIBUTE_UNUSED)
269{
270 return symbol_check_defined (sym);
271}
272
2f1afb73 273
17ee7397
PE
274/*------------------------------------------------------------------.
275| Declare the new symbol SYM. Make it an alias of SYMVAL, and type |
527203e9 276| SYMVAL with SYM's type. |
17ee7397 277`------------------------------------------------------------------*/
2f1afb73
AD
278
279void
17ee7397 280symbol_make_alias (symbol *sym, symbol *symval, location loc)
2f1afb73
AD
281{
282 if (symval->alias)
a5d50994 283 warn_at (loc, _("symbol `%s' used more than once as a literal string"),
df09ef2e 284 symval->tag);
17ee7397 285 else if (sym->alias)
a5d50994 286 warn_at (loc, _("symbol `%s' given more than one literal string"),
df09ef2e 287 sym->tag);
2f1afb73
AD
288 else
289 {
290 symval->class = token_sym;
17ee7397
PE
291 symval->user_token_number = sym->user_token_number;
292 sym->user_token_number = USER_NUMBER_ALIAS;
293 symval->alias = sym;
294 sym->alias = symval;
295 /* sym and symval combined are only one symbol. */
2f1afb73
AD
296 nsyms--;
297 ntokens--;
17ee7397 298 if (ntokens != sym->number && ntokens != symval->number)
2f82502a 299 abort ();
17ee7397
PE
300 sym->number = symval->number =
301 (symval->number < sym->number) ? symval->number : sym->number;
e8fd72d5 302 symbol_type_set (symval, sym->type_name, loc);
2f1afb73
AD
303 }
304}
305
306
307/*---------------------------------------------------------.
308| Check that THIS, and its alias, have same precedence and |
309| associativity. |
310`---------------------------------------------------------*/
311
df09ef2e 312static inline void
0fb1efaf 313symbol_check_alias_consistency (symbol *this)
2f1afb73 314{
df09ef2e
AD
315 symbol *alias = this;
316 symbol *orig = this->alias;
317
318 /* Check only those that _are_ the aliases. */
319 if (!(this->alias && this->user_token_number == USER_NUMBER_ALIAS))
320 return;
321
e8fd72d5 322 if (orig->type_name != alias->type_name)
2f1afb73 323 {
df09ef2e
AD
324 if (orig->type_name)
325 symbol_type_set (alias, orig->type_name, orig->type_location);
326 else
327 symbol_type_set (orig, alias->type_name, alias->type_location);
328 }
2f1afb73 329
df09ef2e
AD
330
331 if (orig->destructor || alias->destructor)
332 {
333 if (orig->destructor)
334 symbol_destructor_set (alias, orig->destructor,
335 orig->destructor_location);
336 else
337 symbol_destructor_set (orig, alias->destructor,
338 alias->destructor_location);
339 }
340
341 if (orig->printer || alias->printer)
342 {
343 if (orig->printer)
344 symbol_printer_set (alias, orig->printer, orig->printer_location);
345 else
346 symbol_printer_set (orig, alias->printer, alias->printer_location);
347 }
348
349 if (alias->prec || orig->prec)
350 {
351 if (orig->prec)
352 symbol_precedence_set (alias, orig->prec, orig->assoc,
353 orig->prec_location);
354 else
355 symbol_precedence_set (orig, alias->prec, alias->assoc,
356 alias->prec_location);
2f1afb73 357 }
2f1afb73
AD
358}
359
0fb1efaf
PE
360static bool
361symbol_check_alias_consistency_processor (void *this,
362 void *null ATTRIBUTE_UNUSED)
363{
df09ef2e
AD
364 symbol_check_alias_consistency (this);
365 return true;
0fb1efaf
PE
366}
367
2f1afb73
AD
368
369/*-------------------------------------------------------------------.
370| Assign a symbol number, and write the definition of the token name |
371| into FDEFINES. Put in SYMBOLS. |
372`-------------------------------------------------------------------*/
373
0fb1efaf 374static inline bool
17ee7397 375symbol_pack (symbol *this)
2f1afb73
AD
376{
377 if (this->class == nterm_sym)
378 {
379 this->number += ntokens;
380 }
381 else if (this->alias)
382 {
383 /* This symbol and its alias are a single token defn.
384 Allocate a tokno, and assign to both check agreement of
385 prec and assoc fields and make both the same */
386 if (this->number == NUMBER_UNDEFINED)
387 {
88bce5a2 388 if (this == endtoken || this->alias == endtoken)
2f1afb73
AD
389 this->number = this->alias->number = 0;
390 else
391 {
2f82502a
PE
392 if (this->alias->number == NUMBER_UNDEFINED)
393 abort ();
2f1afb73
AD
394 this->number = this->alias->number;
395 }
396 }
b9e00562 397 /* Do not do processing below for USER_NUMBER_ALIASes. */
2f1afb73 398 if (this->user_token_number == USER_NUMBER_ALIAS)
a3714bce 399 return true;
2f1afb73
AD
400 }
401 else /* this->class == token_sym */
402 {
2f82502a
PE
403 if (this->number == NUMBER_UNDEFINED)
404 abort ();
2f1afb73
AD
405 }
406
407 symbols[this->number] = this;
a3714bce 408 return true;
2f1afb73
AD
409}
410
0fb1efaf
PE
411static bool
412symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
413{
414 return symbol_pack (this);
415}
416
2f1afb73
AD
417
418
419
420/*--------------------------------------------------.
421| Put THIS in TOKEN_TRANSLATIONS if it is a token. |
422`--------------------------------------------------*/
423
0fb1efaf 424static inline bool
17ee7397 425symbol_translation (symbol *this)
2f1afb73
AD
426{
427 /* Non-terminal? */
428 if (this->class == token_sym
429 && this->user_token_number != USER_NUMBER_ALIAS)
430 {
431 /* A token which translation has already been set? */
432 if (token_translations[this->user_token_number] != undeftoken->number)
a5d50994
AD
433 complain_at (this->location,
434 _("tokens %s and %s both assigned number %d"),
435 symbols[token_translations[this->user_token_number]]->tag,
436 this->tag, this->user_token_number);
2f1afb73
AD
437
438 token_translations[this->user_token_number] = this->number;
439 }
440
a3714bce 441 return true;
2f1afb73
AD
442}
443
0fb1efaf
PE
444static bool
445symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
446{
447 return symbol_translation (this);
448}
449
72a23c97
AD
450
451/*----------------------.
2f1afb73 452| A symbol hash table. |
72a23c97 453`----------------------*/
40675e7c 454
db8837cb 455/* Initial capacity of symbols hash table. */
72a23c97
AD
456#define HT_INITIAL_CAPACITY 257
457
db8837cb 458static struct hash_table *symbol_table = NULL;
72a23c97 459
0fb1efaf 460static inline bool
17ee7397 461hash_compare_symbol (const symbol *m1, const symbol *m2)
72a23c97 462{
95612cfa 463 /* Since tags are unique, we can compare the pointers themselves. */
17ee7397 464 return UNIQSTR_EQ (m1->tag, m2->tag);
72a23c97
AD
465}
466
0fb1efaf
PE
467static bool
468hash_symbol_comparator (void const *m1, void const *m2)
469{
470 return hash_compare_symbol (m1, m2);
471}
472
233a88ad
PE
473static inline size_t
474hash_symbol (const symbol *m, size_t tablesize)
72a23c97 475{
95612cfa 476 /* Since tags are unique, we can hash the pointer itself. */
0fb1efaf
PE
477 return ((uintptr_t) m->tag) % tablesize;
478}
479
233a88ad
PE
480static size_t
481hash_symbol_hasher (void const *m, size_t tablesize)
0fb1efaf
PE
482{
483 return hash_symbol (m, tablesize);
72a23c97
AD
484}
485
486
487/*-------------------------------.
2f1afb73 488| Create the symbol hash table. |
72a23c97
AD
489`-------------------------------*/
490
491void
db8837cb 492symbols_new (void)
72a23c97 493{
db8837cb 494 symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
72a23c97 495 NULL,
0fb1efaf
PE
496 hash_symbol_hasher,
497 hash_symbol_comparator,
498 free);
40675e7c
DM
499}
500
501
1e9798d5
AD
502/*----------------------------------------------------------------.
503| Find the symbol named KEY, and return it. If it does not exist |
504| yet, create it. |
505`----------------------------------------------------------------*/
506
17ee7397
PE
507symbol *
508symbol_get (const char *key, location loc)
40675e7c 509{
17ee7397
PE
510 symbol probe;
511 symbol *entry;
40675e7c 512
ca407bdf 513 key = uniqstr_new (key);
0fb1efaf 514 probe.tag = key;
db8837cb 515 entry = hash_lookup (symbol_table, &probe);
40675e7c 516
72a23c97 517 if (!entry)
40675e7c 518 {
72a23c97 519 /* First insertion in the hash. */
17ee7397 520 entry = symbol_new (key, loc);
db8837cb 521 hash_insert (symbol_table, entry);
40675e7c 522 }
72a23c97
AD
523 return entry;
524}
40675e7c 525
40675e7c 526
39f41916
AD
527/*------------------------------------------------------------------.
528| Generate a dummy nonterminal, whose name cannot conflict with the |
529| user's names. |
530`------------------------------------------------------------------*/
531
17ee7397
PE
532symbol *
533dummy_symbol_get (location loc)
39f41916
AD
534{
535 /* Incremented for each generated symbol. */
536 static int dummy_count = 0;
537 static char buf[256];
538
17ee7397 539 symbol *sym;
39f41916
AD
540
541 sprintf (buf, "@%d", ++dummy_count);
17ee7397 542 sym = symbol_get (buf, loc);
39f41916
AD
543 sym->class = nterm_sym;
544 sym->number = nvars++;
545 return sym;
546}
547
548
72a23c97 549/*-------------------.
db8837cb 550| Free the symbols. |
72a23c97
AD
551`-------------------*/
552
553void
db8837cb 554symbols_free (void)
72a23c97 555{
db8837cb 556 hash_free (symbol_table);
536545f3 557 free (symbols);
40675e7c
DM
558}
559
560
72a23c97 561/*---------------------------------------------------------------.
db8837cb 562| Look for undefined symbols, report an error, and consider them |
72a23c97
AD
563| terminals. |
564`---------------------------------------------------------------*/
565
0fb1efaf
PE
566static void
567symbols_do (Hash_processor processor, void *processor_data)
40675e7c 568{
0fb1efaf 569 hash_do_for_each (symbol_table, processor, processor_data);
40675e7c 570}
2f1afb73
AD
571
572
573/*--------------------------------------------------------------.
574| Check that all the symbols are defined. Report any undefined |
575| symbols and consider them nonterminals. |
576`--------------------------------------------------------------*/
577
578void
579symbols_check_defined (void)
580{
0fb1efaf 581 symbols_do (symbol_check_defined_processor, NULL);
2f1afb73
AD
582}
583
584/*------------------------------------------------------------------.
585| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
586| number. |
587`------------------------------------------------------------------*/
588
589static void
590symbols_token_translations_init (void)
591{
a3714bce 592 bool num_256_available_p = true;
2f1afb73
AD
593 int i;
594
595 /* Find the highest user token number, and whether 256, the POSIX
596 preferred user token number for the error token, is used. */
597 max_user_token_number = 0;
598 for (i = 0; i < ntokens; ++i)
599 {
17ee7397 600 symbol *this = symbols[i];
2f1afb73
AD
601 if (this->user_token_number != USER_NUMBER_UNDEFINED)
602 {
603 if (this->user_token_number > max_user_token_number)
604 max_user_token_number = this->user_token_number;
605 if (this->user_token_number == 256)
a3714bce 606 num_256_available_p = false;
2f1afb73
AD
607 }
608 }
609
610 /* If 256 is not used, assign it to error, to follow POSIX. */
611 if (num_256_available_p
612 && errtoken->user_token_number == USER_NUMBER_UNDEFINED)
613 errtoken->user_token_number = 256;
614
615 /* Set the missing user numbers. */
616 if (max_user_token_number < 256)
617 max_user_token_number = 256;
618
619 for (i = 0; i < ntokens; ++i)
620 {
17ee7397 621 symbol *this = symbols[i];
2f1afb73
AD
622 if (this->user_token_number == USER_NUMBER_UNDEFINED)
623 this->user_token_number = ++max_user_token_number;
624 if (this->user_token_number > max_user_token_number)
625 max_user_token_number = this->user_token_number;
626 }
627
da2a7671
PE
628 token_translations = xnmalloc (max_user_token_number + 1,
629 sizeof *token_translations);
2f1afb73
AD
630
631 /* Initialize all entries for literal tokens to 2, the internal
88bce5a2
AD
632 token number for $undefined, which represents all invalid inputs.
633 */
2f1afb73
AD
634 for (i = 0; i < max_user_token_number + 1; i++)
635 token_translations[i] = undeftoken->number;
0fb1efaf 636 symbols_do (symbol_translation_processor, NULL);
2f1afb73
AD
637}
638
639
640/*----------------------------------------------------------------.
641| Assign symbol numbers, and write definition of token names into |
642| FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. |
643`----------------------------------------------------------------*/
644
645void
646symbols_pack (void)
647{
da2a7671 648 symbols = xcalloc (nsyms, sizeof *symbols);
2f1afb73 649
0fb1efaf
PE
650 symbols_do (symbol_check_alias_consistency_processor, NULL);
651 symbols_do (symbol_pack_processor, NULL);
2f1afb73
AD
652
653 symbols_token_translations_init ();
654
655 if (startsymbol->class == unknown_sym)
ee000ba4 656 fatal_at (startsymbol_location,
dafdc66f 657 _("the start symbol %s is undefined"),
97650f4e 658 startsymbol->tag);
2f1afb73 659 else if (startsymbol->class == token_sym)
ee000ba4 660 fatal_at (startsymbol_location,
dafdc66f 661 _("the start symbol %s is a token"),
97650f4e 662 startsymbol->tag);
2f1afb73 663}