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