]> git.saurik.com Git - bison.git/blame - src/symtab.c
* src/vcg.h (enum layoutalgorithm): Remove. All uses removed.
[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{
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;
2f1afb73
AD
267 }
268}
269
270
271/*---------------------------------------------------------.
272| Check that THIS, and its alias, have same precedence and |
273| associativity. |
274`---------------------------------------------------------*/
275
df09ef2e 276static inline void
0fb1efaf 277symbol_check_alias_consistency (symbol *this)
2f1afb73 278{
df09ef2e
AD
279 symbol *alias = this;
280 symbol *orig = this->alias;
281
282 /* Check only those that _are_ the aliases. */
283 if (!(this->alias && this->user_token_number == USER_NUMBER_ALIAS))
284 return;
285
286 if (orig->type_name || alias->type_name)
2f1afb73 287 {
df09ef2e
AD
288 if (orig->type_name)
289 symbol_type_set (alias, orig->type_name, orig->type_location);
290 else
291 symbol_type_set (orig, alias->type_name, alias->type_location);
292 }
2f1afb73 293
df09ef2e
AD
294
295 if (orig->destructor || alias->destructor)
296 {
297 if (orig->destructor)
298 symbol_destructor_set (alias, orig->destructor,
299 orig->destructor_location);
300 else
301 symbol_destructor_set (orig, alias->destructor,
302 alias->destructor_location);
303 }
304
305 if (orig->printer || alias->printer)
306 {
307 if (orig->printer)
308 symbol_printer_set (alias, orig->printer, orig->printer_location);
309 else
310 symbol_printer_set (orig, alias->printer, alias->printer_location);
311 }
312
313 if (alias->prec || orig->prec)
314 {
315 if (orig->prec)
316 symbol_precedence_set (alias, orig->prec, orig->assoc,
317 orig->prec_location);
318 else
319 symbol_precedence_set (orig, alias->prec, alias->assoc,
320 alias->prec_location);
2f1afb73 321 }
2f1afb73
AD
322}
323
0fb1efaf
PE
324static bool
325symbol_check_alias_consistency_processor (void *this,
326 void *null ATTRIBUTE_UNUSED)
327{
df09ef2e
AD
328 symbol_check_alias_consistency (this);
329 return true;
0fb1efaf
PE
330}
331
2f1afb73
AD
332
333/*-------------------------------------------------------------------.
334| Assign a symbol number, and write the definition of the token name |
335| into FDEFINES. Put in SYMBOLS. |
336`-------------------------------------------------------------------*/
337
0fb1efaf 338static inline bool
17ee7397 339symbol_pack (symbol *this)
2f1afb73
AD
340{
341 if (this->class == nterm_sym)
342 {
343 this->number += ntokens;
344 }
345 else if (this->alias)
346 {
347 /* This symbol and its alias are a single token defn.
348 Allocate a tokno, and assign to both check agreement of
349 prec and assoc fields and make both the same */
350 if (this->number == NUMBER_UNDEFINED)
351 {
88bce5a2 352 if (this == endtoken || this->alias == endtoken)
2f1afb73
AD
353 this->number = this->alias->number = 0;
354 else
355 {
2f82502a
PE
356 if (this->alias->number == NUMBER_UNDEFINED)
357 abort ();
2f1afb73
AD
358 this->number = this->alias->number;
359 }
360 }
b9e00562 361 /* Do not do processing below for USER_NUMBER_ALIASes. */
2f1afb73 362 if (this->user_token_number == USER_NUMBER_ALIAS)
a3714bce 363 return true;
2f1afb73
AD
364 }
365 else /* this->class == token_sym */
366 {
2f82502a
PE
367 if (this->number == NUMBER_UNDEFINED)
368 abort ();
2f1afb73
AD
369 }
370
371 symbols[this->number] = this;
a3714bce 372 return true;
2f1afb73
AD
373}
374
0fb1efaf
PE
375static bool
376symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
377{
378 return symbol_pack (this);
379}
380
2f1afb73
AD
381
382
383
384/*--------------------------------------------------.
385| Put THIS in TOKEN_TRANSLATIONS if it is a token. |
386`--------------------------------------------------*/
387
0fb1efaf 388static inline bool
17ee7397 389symbol_translation (symbol *this)
2f1afb73
AD
390{
391 /* Non-terminal? */
392 if (this->class == token_sym
393 && this->user_token_number != USER_NUMBER_ALIAS)
394 {
395 /* A token which translation has already been set? */
396 if (token_translations[this->user_token_number] != undeftoken->number)
a5d50994
AD
397 complain_at (this->location,
398 _("tokens %s and %s both assigned number %d"),
399 symbols[token_translations[this->user_token_number]]->tag,
400 this->tag, this->user_token_number);
2f1afb73
AD
401
402 token_translations[this->user_token_number] = this->number;
403 }
404
a3714bce 405 return true;
2f1afb73
AD
406}
407
0fb1efaf
PE
408static bool
409symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
410{
411 return symbol_translation (this);
412}
413
72a23c97
AD
414
415/*----------------------.
2f1afb73 416| A symbol hash table. |
72a23c97 417`----------------------*/
40675e7c 418
db8837cb 419/* Initial capacity of symbols hash table. */
72a23c97
AD
420#define HT_INITIAL_CAPACITY 257
421
db8837cb 422static struct hash_table *symbol_table = NULL;
72a23c97 423
0fb1efaf 424static inline bool
17ee7397 425hash_compare_symbol (const symbol *m1, const symbol *m2)
72a23c97 426{
95612cfa 427 /* Since tags are unique, we can compare the pointers themselves. */
17ee7397 428 return UNIQSTR_EQ (m1->tag, m2->tag);
72a23c97
AD
429}
430
0fb1efaf
PE
431static bool
432hash_symbol_comparator (void const *m1, void const *m2)
433{
434 return hash_compare_symbol (m1, m2);
435}
436
233a88ad
PE
437static inline size_t
438hash_symbol (const symbol *m, size_t tablesize)
72a23c97 439{
95612cfa 440 /* Since tags are unique, we can hash the pointer itself. */
0fb1efaf
PE
441 return ((uintptr_t) m->tag) % tablesize;
442}
443
233a88ad
PE
444static size_t
445hash_symbol_hasher (void const *m, size_t tablesize)
0fb1efaf
PE
446{
447 return hash_symbol (m, tablesize);
72a23c97
AD
448}
449
450
451/*-------------------------------.
2f1afb73 452| Create the symbol hash table. |
72a23c97
AD
453`-------------------------------*/
454
455void
db8837cb 456symbols_new (void)
72a23c97 457{
db8837cb 458 symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
72a23c97 459 NULL,
0fb1efaf
PE
460 hash_symbol_hasher,
461 hash_symbol_comparator,
462 free);
40675e7c
DM
463}
464
465
1e9798d5
AD
466/*----------------------------------------------------------------.
467| Find the symbol named KEY, and return it. If it does not exist |
468| yet, create it. |
469`----------------------------------------------------------------*/
470
17ee7397
PE
471symbol *
472symbol_get (const char *key, location loc)
40675e7c 473{
17ee7397
PE
474 symbol probe;
475 symbol *entry;
40675e7c 476
97650f4e 477 /* Keep the symbol in a printable form. */
17ee7397 478 key = uniqstr_new (quotearg_style (escape_quoting_style, 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}