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