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