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