]> git.saurik.com Git - bison.git/blob - src/symtab.c
Avoid gcc -Wundef warnings reported by Gerald Pfeifer in
[bison.git] / src / symtab.c
1 /* Symbol table manager for Bison.
2
3 Copyright (C) 1984, 1989, 2000, 2001, 2002 Free Software Foundation, Inc.
4
5 This file is part of Bison, the GNU Compiler Compiler.
6
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.
11
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.
16
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. */
21
22
23 #include "system.h"
24
25 #include <hash.h>
26 #include <quotearg.h>
27
28 #include "complain.h"
29 #include "gram.h"
30 #include "symtab.h"
31
32 /*------------------------.
33 | Distinguished symbols. |
34 `------------------------*/
35
36 symbol *errtoken = NULL;
37 symbol *undeftoken = NULL;
38 symbol *endtoken = NULL;
39 symbol *accept = NULL;
40 symbol *startsymbol = NULL;
41 location startsymbol_location;
42
43 /*---------------------------------.
44 | Create a new symbol, named TAG. |
45 `---------------------------------*/
46
47 static symbol *
48 symbol_new (uniqstr tag, location loc)
49 {
50 symbol *res = MALLOC (res, 1);
51
52 uniqstr_assert (tag);
53 res->tag = tag;
54 res->location = loc;
55
56 res->type_name = NULL;
57 res->destructor = NULL;
58 res->printer = NULL;
59
60 res->number = NUMBER_UNDEFINED;
61 res->prec = 0;
62 res->assoc = undef_assoc;
63 res->user_token_number = USER_NUMBER_UNDEFINED;
64
65 res->alias = NULL;
66 res->class = unknown_sym;
67
68 nsyms++;
69 return res;
70 }
71
72
73 /*-----------------------------------------------------------------.
74 | Set the TYPE_NAME associated with SYM. Does nothing if passed 0 |
75 | as TYPE_NAME. |
76 `-----------------------------------------------------------------*/
77
78 void
79 symbol_type_set (symbol *sym, uniqstr type_name, location loc)
80 {
81 if (type_name)
82 {
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;
87 }
88 }
89
90
91 /*------------------------------------------------------------------.
92 | Set the DESTRUCTOR associated with SYM. Do nothing if passed 0. |
93 `------------------------------------------------------------------*/
94
95 void
96 symbol_destructor_set (symbol *sym, char *destructor, location loc)
97 {
98 if (destructor)
99 {
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;
105 }
106 }
107
108
109 /*---------------------------------------------------------------.
110 | Set the PRINTER associated with SYM. Do nothing if passed 0. |
111 `---------------------------------------------------------------*/
112
113 void
114 symbol_printer_set (symbol *sym, char *printer, location loc)
115 {
116 if (printer)
117 {
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;
123 }
124 }
125
126
127 /*-----------------------------------------------------------------.
128 | Set the PRECEDENCE associated with SYM. Does nothing if invoked |
129 | with UNDEF_ASSOC as ASSOC. |
130 `-----------------------------------------------------------------*/
131
132 void
133 symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
134 {
135 if (a != undef_assoc)
136 {
137 if (sym->prec != 0)
138 complain_at (loc, _("redefining precedence of %s"), sym->tag);
139 sym->prec = prec;
140 sym->assoc = a;
141 }
142
143 /* Only terminals have a precedence. */
144 symbol_class_set (sym, token_sym, loc);
145 }
146
147
148 /*------------------------------------.
149 | Set the CLASS associated with SYM. |
150 `------------------------------------*/
151
152 void
153 symbol_class_set (symbol *sym, symbol_class class, location loc)
154 {
155 if (sym->class != unknown_sym && sym->class != class)
156 complain_at (loc, _("symbol %s redefined"), sym->tag);
157
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++;
162
163 sym->class = class;
164 }
165
166
167 /*------------------------------------------------.
168 | Set the USER_TOKEN_NUMBER associated with SYM. |
169 `------------------------------------------------*/
170
171 void
172 symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
173 {
174 if (sym->class != token_sym)
175 abort ();
176
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);
180
181 sym->user_token_number = user_token_number;
182 /* User defined $end token? */
183 if (user_token_number == 0)
184 {
185 endtoken = sym;
186 endtoken->number = 0;
187 /* It is always mapped to 0, so it was already counted in
188 NTOKENS. */
189 --ntokens;
190 }
191 }
192
193
194 /*----------------------------------------------------------.
195 | If SYM is not defined, report an error, and consider it a |
196 | nonterminal. |
197 `----------------------------------------------------------*/
198
199 static inline bool
200 symbol_check_defined (symbol *sym)
201 {
202 if (sym->class == unknown_sym)
203 {
204 complain_at
205 (sym->location,
206 _("symbol %s is used, but is not defined as a token and has no rules"),
207 sym->tag);
208 sym->class = nterm_sym;
209 sym->number = nvars++;
210 }
211
212 return true;
213 }
214
215 static bool
216 symbol_check_defined_processor (void *sym, void *null ATTRIBUTE_UNUSED)
217 {
218 return symbol_check_defined (sym);
219 }
220
221
222 /*------------------------------------------------------------------.
223 | Declare the new symbol SYM. Make it an alias of SYMVAL, and type |
224 | SYMVAL with SYM's type. |
225 `------------------------------------------------------------------*/
226
227 void
228 symbol_make_alias (symbol *sym, symbol *symval, location loc)
229 {
230 if (symval->alias)
231 warn_at (loc, _("symbol `%s' used more than once as a literal string"),
232 symval->tag);
233 else if (sym->alias)
234 warn_at (loc, _("symbol `%s' given more than one literal string"),
235 sym->tag);
236 else
237 {
238 symval->class = token_sym;
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. */
244 nsyms--;
245 ntokens--;
246 if (ntokens != sym->number && ntokens != symval->number)
247 abort ();
248 sym->number = symval->number =
249 (symval->number < sym->number) ? symval->number : sym->number;
250 symbol_type_set (symval, sym->type_name, loc);
251 }
252 }
253
254
255 /*---------------------------------------------------------.
256 | Check that THIS, and its alias, have same precedence and |
257 | associativity. |
258 `---------------------------------------------------------*/
259
260 static inline bool
261 symbol_check_alias_consistency (symbol *this)
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)
269 complain_at (this->alias->location,
270 _("conflicting precedences for %s and %s"),
271 this->tag, this->alias->tag);
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 {
280 if (this->assoc != undef_assoc && this->alias->assoc != undef_assoc)
281 complain_at (this->alias->location,
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)
286 this->alias->assoc = this->assoc;
287 else
288 this->assoc = this->alias->assoc;
289 }
290 }
291 return true;
292 }
293
294 static bool
295 symbol_check_alias_consistency_processor (void *this,
296 void *null ATTRIBUTE_UNUSED)
297 {
298 return symbol_check_alias_consistency (this);
299 }
300
301
302 /*-------------------------------------------------------------------.
303 | Assign a symbol number, and write the definition of the token name |
304 | into FDEFINES. Put in SYMBOLS. |
305 `-------------------------------------------------------------------*/
306
307 static inline bool
308 symbol_pack (symbol *this)
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 {
321 if (this == endtoken || this->alias == endtoken)
322 this->number = this->alias->number = 0;
323 else
324 {
325 if (this->alias->number == NUMBER_UNDEFINED)
326 abort ();
327 this->number = this->alias->number;
328 }
329 }
330 /* Do not do processing below for USER_NUMBER_ALIASes. */
331 if (this->user_token_number == USER_NUMBER_ALIAS)
332 return true;
333 }
334 else /* this->class == token_sym */
335 {
336 if (this->number == NUMBER_UNDEFINED)
337 abort ();
338 }
339
340 symbols[this->number] = this;
341 return true;
342 }
343
344 static bool
345 symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
346 {
347 return symbol_pack (this);
348 }
349
350
351
352
353 /*--------------------------------------------------.
354 | Put THIS in TOKEN_TRANSLATIONS if it is a token. |
355 `--------------------------------------------------*/
356
357 static inline bool
358 symbol_translation (symbol *this)
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)
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);
370
371 token_translations[this->user_token_number] = this->number;
372 }
373
374 return true;
375 }
376
377 static bool
378 symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
379 {
380 return symbol_translation (this);
381 }
382
383
384 /*----------------------.
385 | A symbol hash table. |
386 `----------------------*/
387
388 /* Initial capacity of symbols hash table. */
389 #define HT_INITIAL_CAPACITY 257
390
391 static struct hash_table *symbol_table = NULL;
392
393 static inline bool
394 hash_compare_symbol (const symbol *m1, const symbol *m2)
395 {
396 /* Since tags are unique, we can compare the pointers themselves. */
397 return UNIQSTR_EQ (m1->tag, m2->tag);
398 }
399
400 static bool
401 hash_symbol_comparator (void const *m1, void const *m2)
402 {
403 return hash_compare_symbol (m1, m2);
404 }
405
406 static inline unsigned int
407 hash_symbol (const symbol *m, unsigned int tablesize)
408 {
409 /* Since tags are unique, we can hash the pointer itself. */
410 return ((uintptr_t) m->tag) % tablesize;
411 }
412
413 static unsigned int
414 hash_symbol_hasher (void const *m, unsigned int tablesize)
415 {
416 return hash_symbol (m, tablesize);
417 }
418
419
420 /*-------------------------------.
421 | Create the symbol hash table. |
422 `-------------------------------*/
423
424 void
425 symbols_new (void)
426 {
427 symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
428 NULL,
429 hash_symbol_hasher,
430 hash_symbol_comparator,
431 free);
432 }
433
434
435 /*----------------------------------------------------------------.
436 | Find the symbol named KEY, and return it. If it does not exist |
437 | yet, create it. |
438 `----------------------------------------------------------------*/
439
440 symbol *
441 symbol_get (const char *key, location loc)
442 {
443 symbol probe;
444 symbol *entry;
445
446 /* Keep the symbol in a printable form. */
447 key = uniqstr_new (quotearg_style (escape_quoting_style, key));
448 probe.tag = key;
449 entry = hash_lookup (symbol_table, &probe);
450
451 if (!entry)
452 {
453 /* First insertion in the hash. */
454 entry = symbol_new (key, loc);
455 hash_insert (symbol_table, entry);
456 }
457 return entry;
458 }
459
460
461 /*------------------------------------------------------------------.
462 | Generate a dummy nonterminal, whose name cannot conflict with the |
463 | user's names. |
464 `------------------------------------------------------------------*/
465
466 symbol *
467 dummy_symbol_get (location loc)
468 {
469 /* Incremented for each generated symbol. */
470 static int dummy_count = 0;
471 static char buf[256];
472
473 symbol *sym;
474
475 sprintf (buf, "@%d", ++dummy_count);
476 sym = symbol_get (buf, loc);
477 sym->class = nterm_sym;
478 sym->number = nvars++;
479 return sym;
480 }
481
482
483 /*-------------------.
484 | Free the symbols. |
485 `-------------------*/
486
487 void
488 symbols_free (void)
489 {
490 hash_free (symbol_table);
491 free (symbols);
492 }
493
494
495 /*---------------------------------------------------------------.
496 | Look for undefined symbols, report an error, and consider them |
497 | terminals. |
498 `---------------------------------------------------------------*/
499
500 static void
501 symbols_do (Hash_processor processor, void *processor_data)
502 {
503 hash_do_for_each (symbol_table, processor, processor_data);
504 }
505
506
507 /*--------------------------------------------------------------.
508 | Check that all the symbols are defined. Report any undefined |
509 | symbols and consider them nonterminals. |
510 `--------------------------------------------------------------*/
511
512 void
513 symbols_check_defined (void)
514 {
515 symbols_do (symbol_check_defined_processor, NULL);
516 }
517
518 /*------------------------------------------------------------------.
519 | Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
520 | number. |
521 `------------------------------------------------------------------*/
522
523 static void
524 symbols_token_translations_init (void)
525 {
526 bool num_256_available_p = true;
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 {
534 symbol *this = symbols[i];
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)
540 num_256_available_p = false;
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 {
555 symbol *this = symbols[i];
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
562 CALLOC (token_translations, max_user_token_number + 1);
563
564 /* Initialize all entries for literal tokens to 2, the internal
565 token number for $undefined, which represents all invalid inputs.
566 */
567 for (i = 0; i < max_user_token_number + 1; i++)
568 token_translations[i] = undeftoken->number;
569 symbols_do (symbol_translation_processor, NULL);
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
578 void
579 symbols_pack (void)
580 {
581 CALLOC (symbols, nsyms);
582
583 symbols_do (symbol_check_alias_consistency_processor, NULL);
584 symbols_do (symbol_pack_processor, NULL);
585
586 symbols_token_translations_init ();
587
588 if (startsymbol->class == unknown_sym)
589 fatal_at (startsymbol_location,
590 _("the start symbol %s is undefined"),
591 startsymbol->tag);
592 else if (startsymbol->class == token_sym)
593 fatal_at (startsymbol_location,
594 _("the start symbol %s is a token"),
595 startsymbol->tag);
596 }