]> git.saurik.com Git - bison.git/blame - src/symtab.c
Don't include c.m4, as "include" doesn't do what we want.
[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 |
224| them with TYPENAME. |
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;
2f1afb73
AD
250 }
251}
252
253
254/*---------------------------------------------------------.
255| Check that THIS, and its alias, have same precedence and |
256| associativity. |
257`---------------------------------------------------------*/
258
0fb1efaf
PE
259static inline bool
260symbol_check_alias_consistency (symbol *this)
2f1afb73
AD
261{
262 /* Check only those who _are_ the aliases. */
263 if (this->alias && this->user_token_number == USER_NUMBER_ALIAS)
264 {
265 if (this->prec != this->alias->prec)
266 {
267 if (this->prec != 0 && this->alias->prec != 0)
a5d50994
AD
268 complain_at (this->alias->location,
269 _("conflicting precedences for %s and %s"),
270 this->tag, this->alias->tag);
2f1afb73
AD
271 if (this->prec != 0)
272 this->alias->prec = this->prec;
273 else
274 this->prec = this->alias->prec;
275 }
276
277 if (this->assoc != this->alias->assoc)
278 {
a945ec39 279 if (this->assoc != undef_assoc && this->alias->assoc != undef_assoc)
a5d50994 280 complain_at (this->alias->location,
a945ec39
AD
281 _("conflicting associativities for %s (%s) and %s (%s)"),
282 this->tag, assoc_to_string (this->assoc),
283 this->alias->tag, assoc_to_string (this->alias->assoc));
284 if (this->assoc != undef_assoc)
2f1afb73
AD
285 this->alias->assoc = this->assoc;
286 else
287 this->assoc = this->alias->assoc;
288 }
289 }
a3714bce 290 return true;
2f1afb73
AD
291}
292
0fb1efaf
PE
293static bool
294symbol_check_alias_consistency_processor (void *this,
295 void *null ATTRIBUTE_UNUSED)
296{
297 return symbol_check_alias_consistency (this);
298}
299
2f1afb73
AD
300
301/*-------------------------------------------------------------------.
302| Assign a symbol number, and write the definition of the token name |
303| into FDEFINES. Put in SYMBOLS. |
304`-------------------------------------------------------------------*/
305
0fb1efaf 306static inline bool
17ee7397 307symbol_pack (symbol *this)
2f1afb73
AD
308{
309 if (this->class == nterm_sym)
310 {
311 this->number += ntokens;
312 }
313 else if (this->alias)
314 {
315 /* This symbol and its alias are a single token defn.
316 Allocate a tokno, and assign to both check agreement of
317 prec and assoc fields and make both the same */
318 if (this->number == NUMBER_UNDEFINED)
319 {
88bce5a2 320 if (this == endtoken || this->alias == endtoken)
2f1afb73
AD
321 this->number = this->alias->number = 0;
322 else
323 {
2f82502a
PE
324 if (this->alias->number == NUMBER_UNDEFINED)
325 abort ();
2f1afb73
AD
326 this->number = this->alias->number;
327 }
328 }
b9e00562 329 /* Do not do processing below for USER_NUMBER_ALIASes. */
2f1afb73 330 if (this->user_token_number == USER_NUMBER_ALIAS)
a3714bce 331 return true;
2f1afb73
AD
332 }
333 else /* this->class == token_sym */
334 {
2f82502a
PE
335 if (this->number == NUMBER_UNDEFINED)
336 abort ();
2f1afb73
AD
337 }
338
339 symbols[this->number] = this;
a3714bce 340 return true;
2f1afb73
AD
341}
342
0fb1efaf
PE
343static bool
344symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
345{
346 return symbol_pack (this);
347}
348
2f1afb73
AD
349
350
351
352/*--------------------------------------------------.
353| Put THIS in TOKEN_TRANSLATIONS if it is a token. |
354`--------------------------------------------------*/
355
0fb1efaf 356static inline bool
17ee7397 357symbol_translation (symbol *this)
2f1afb73
AD
358{
359 /* Non-terminal? */
360 if (this->class == token_sym
361 && this->user_token_number != USER_NUMBER_ALIAS)
362 {
363 /* A token which translation has already been set? */
364 if (token_translations[this->user_token_number] != undeftoken->number)
a5d50994
AD
365 complain_at (this->location,
366 _("tokens %s and %s both assigned number %d"),
367 symbols[token_translations[this->user_token_number]]->tag,
368 this->tag, this->user_token_number);
2f1afb73
AD
369
370 token_translations[this->user_token_number] = this->number;
371 }
372
a3714bce 373 return true;
2f1afb73
AD
374}
375
0fb1efaf
PE
376static bool
377symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
378{
379 return symbol_translation (this);
380}
381
72a23c97
AD
382
383/*----------------------.
2f1afb73 384| A symbol hash table. |
72a23c97 385`----------------------*/
40675e7c 386
db8837cb 387/* Initial capacity of symbols hash table. */
72a23c97
AD
388#define HT_INITIAL_CAPACITY 257
389
db8837cb 390static struct hash_table *symbol_table = NULL;
72a23c97 391
0fb1efaf 392static inline bool
17ee7397 393hash_compare_symbol (const symbol *m1, const symbol *m2)
72a23c97 394{
95612cfa 395 /* Since tags are unique, we can compare the pointers themselves. */
17ee7397 396 return UNIQSTR_EQ (m1->tag, m2->tag);
72a23c97
AD
397}
398
0fb1efaf
PE
399static bool
400hash_symbol_comparator (void const *m1, void const *m2)
401{
402 return hash_compare_symbol (m1, m2);
403}
404
405static inline unsigned int
17ee7397 406hash_symbol (const symbol *m, unsigned int tablesize)
72a23c97 407{
95612cfa 408 /* Since tags are unique, we can hash the pointer itself. */
0fb1efaf
PE
409 return ((uintptr_t) m->tag) % tablesize;
410}
411
412static unsigned int
413hash_symbol_hasher (void const *m, unsigned int tablesize)
414{
415 return hash_symbol (m, tablesize);
72a23c97
AD
416}
417
418
419/*-------------------------------.
2f1afb73 420| Create the symbol hash table. |
72a23c97
AD
421`-------------------------------*/
422
423void
db8837cb 424symbols_new (void)
72a23c97 425{
db8837cb 426 symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
72a23c97 427 NULL,
0fb1efaf
PE
428 hash_symbol_hasher,
429 hash_symbol_comparator,
430 free);
40675e7c
DM
431}
432
433
1e9798d5
AD
434/*----------------------------------------------------------------.
435| Find the symbol named KEY, and return it. If it does not exist |
436| yet, create it. |
437`----------------------------------------------------------------*/
438
17ee7397
PE
439symbol *
440symbol_get (const char *key, location loc)
40675e7c 441{
17ee7397
PE
442 symbol probe;
443 symbol *entry;
40675e7c 444
97650f4e 445 /* Keep the symbol in a printable form. */
17ee7397 446 key = uniqstr_new (quotearg_style (escape_quoting_style, key));
0fb1efaf 447 probe.tag = key;
db8837cb 448 entry = hash_lookup (symbol_table, &probe);
40675e7c 449
72a23c97 450 if (!entry)
40675e7c 451 {
72a23c97 452 /* First insertion in the hash. */
17ee7397 453 entry = symbol_new (key, loc);
db8837cb 454 hash_insert (symbol_table, entry);
40675e7c 455 }
72a23c97
AD
456 return entry;
457}
40675e7c 458
40675e7c 459
39f41916
AD
460/*------------------------------------------------------------------.
461| Generate a dummy nonterminal, whose name cannot conflict with the |
462| user's names. |
463`------------------------------------------------------------------*/
464
17ee7397
PE
465symbol *
466dummy_symbol_get (location loc)
39f41916
AD
467{
468 /* Incremented for each generated symbol. */
469 static int dummy_count = 0;
470 static char buf[256];
471
17ee7397 472 symbol *sym;
39f41916
AD
473
474 sprintf (buf, "@%d", ++dummy_count);
17ee7397 475 sym = symbol_get (buf, loc);
39f41916
AD
476 sym->class = nterm_sym;
477 sym->number = nvars++;
478 return sym;
479}
480
481
72a23c97 482/*-------------------.
db8837cb 483| Free the symbols. |
72a23c97
AD
484`-------------------*/
485
486void
db8837cb 487symbols_free (void)
72a23c97 488{
db8837cb 489 hash_free (symbol_table);
536545f3 490 free (symbols);
40675e7c
DM
491}
492
493
72a23c97 494/*---------------------------------------------------------------.
db8837cb 495| Look for undefined symbols, report an error, and consider them |
72a23c97
AD
496| terminals. |
497`---------------------------------------------------------------*/
498
0fb1efaf
PE
499static void
500symbols_do (Hash_processor processor, void *processor_data)
40675e7c 501{
0fb1efaf 502 hash_do_for_each (symbol_table, processor, processor_data);
40675e7c 503}
2f1afb73
AD
504
505
506/*--------------------------------------------------------------.
507| Check that all the symbols are defined. Report any undefined |
508| symbols and consider them nonterminals. |
509`--------------------------------------------------------------*/
510
511void
512symbols_check_defined (void)
513{
0fb1efaf 514 symbols_do (symbol_check_defined_processor, NULL);
2f1afb73
AD
515}
516
517/*------------------------------------------------------------------.
518| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
519| number. |
520`------------------------------------------------------------------*/
521
522static void
523symbols_token_translations_init (void)
524{
a3714bce 525 bool num_256_available_p = true;
2f1afb73
AD
526 int i;
527
528 /* Find the highest user token number, and whether 256, the POSIX
529 preferred user token number for the error token, is used. */
530 max_user_token_number = 0;
531 for (i = 0; i < ntokens; ++i)
532 {
17ee7397 533 symbol *this = symbols[i];
2f1afb73
AD
534 if (this->user_token_number != USER_NUMBER_UNDEFINED)
535 {
536 if (this->user_token_number > max_user_token_number)
537 max_user_token_number = this->user_token_number;
538 if (this->user_token_number == 256)
a3714bce 539 num_256_available_p = false;
2f1afb73
AD
540 }
541 }
542
543 /* If 256 is not used, assign it to error, to follow POSIX. */
544 if (num_256_available_p
545 && errtoken->user_token_number == USER_NUMBER_UNDEFINED)
546 errtoken->user_token_number = 256;
547
548 /* Set the missing user numbers. */
549 if (max_user_token_number < 256)
550 max_user_token_number = 256;
551
552 for (i = 0; i < ntokens; ++i)
553 {
17ee7397 554 symbol *this = symbols[i];
2f1afb73
AD
555 if (this->user_token_number == USER_NUMBER_UNDEFINED)
556 this->user_token_number = ++max_user_token_number;
557 if (this->user_token_number > max_user_token_number)
558 max_user_token_number = this->user_token_number;
559 }
560
0fb1efaf 561 CALLOC (token_translations, max_user_token_number + 1);
2f1afb73
AD
562
563 /* Initialize all entries for literal tokens to 2, the internal
88bce5a2
AD
564 token number for $undefined, which represents all invalid inputs.
565 */
2f1afb73
AD
566 for (i = 0; i < max_user_token_number + 1; i++)
567 token_translations[i] = undeftoken->number;
0fb1efaf 568 symbols_do (symbol_translation_processor, NULL);
2f1afb73
AD
569}
570
571
572/*----------------------------------------------------------------.
573| Assign symbol numbers, and write definition of token names into |
574| FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. |
575`----------------------------------------------------------------*/
576
577void
578symbols_pack (void)
579{
0fb1efaf 580 CALLOC (symbols, nsyms);
2f1afb73 581
0fb1efaf
PE
582 symbols_do (symbol_check_alias_consistency_processor, NULL);
583 symbols_do (symbol_pack_processor, NULL);
2f1afb73
AD
584
585 symbols_token_translations_init ();
586
587 if (startsymbol->class == unknown_sym)
ee000ba4 588 fatal_at (startsymbol_location,
dafdc66f 589 _("the start symbol %s is undefined"),
97650f4e 590 startsymbol->tag);
2f1afb73 591 else if (startsymbol->class == token_sym)
ee000ba4 592 fatal_at (startsymbol_location,
dafdc66f 593 _("the start symbol %s is a token"),
97650f4e 594 startsymbol->tag);
2f1afb73 595}