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