]> git.saurik.com Git - bison.git/blob - src/symtab.c
(conflict_report):
[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 | them with TYPENAME. |
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 }
251 }
252
253
254 /*---------------------------------------------------------.
255 | Check that THIS, and its alias, have same precedence and |
256 | associativity. |
257 `---------------------------------------------------------*/
258
259 static inline bool
260 symbol_check_alias_consistency (symbol *this)
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)
268 complain_at (this->alias->location,
269 _("conflicting precedences for %s and %s"),
270 this->tag, this->alias->tag);
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 {
279 if (this->assoc != undef_assoc && this->alias->assoc != undef_assoc)
280 complain_at (this->alias->location,
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)
285 this->alias->assoc = this->assoc;
286 else
287 this->assoc = this->alias->assoc;
288 }
289 }
290 return true;
291 }
292
293 static bool
294 symbol_check_alias_consistency_processor (void *this,
295 void *null ATTRIBUTE_UNUSED)
296 {
297 return symbol_check_alias_consistency (this);
298 }
299
300
301 /*-------------------------------------------------------------------.
302 | Assign a symbol number, and write the definition of the token name |
303 | into FDEFINES. Put in SYMBOLS. |
304 `-------------------------------------------------------------------*/
305
306 static inline bool
307 symbol_pack (symbol *this)
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 {
320 if (this == endtoken || this->alias == endtoken)
321 this->number = this->alias->number = 0;
322 else
323 {
324 if (this->alias->number == NUMBER_UNDEFINED)
325 abort ();
326 this->number = this->alias->number;
327 }
328 }
329 /* Do not do processing below for USER_NUMBER_ALIASes. */
330 if (this->user_token_number == USER_NUMBER_ALIAS)
331 return true;
332 }
333 else /* this->class == token_sym */
334 {
335 if (this->number == NUMBER_UNDEFINED)
336 abort ();
337 }
338
339 symbols[this->number] = this;
340 return true;
341 }
342
343 static bool
344 symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
345 {
346 return symbol_pack (this);
347 }
348
349
350
351
352 /*--------------------------------------------------.
353 | Put THIS in TOKEN_TRANSLATIONS if it is a token. |
354 `--------------------------------------------------*/
355
356 static inline bool
357 symbol_translation (symbol *this)
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)
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);
369
370 token_translations[this->user_token_number] = this->number;
371 }
372
373 return true;
374 }
375
376 static bool
377 symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
378 {
379 return symbol_translation (this);
380 }
381
382
383 /*----------------------.
384 | A symbol hash table. |
385 `----------------------*/
386
387 /* Initial capacity of symbols hash table. */
388 #define HT_INITIAL_CAPACITY 257
389
390 static struct hash_table *symbol_table = NULL;
391
392 static inline bool
393 hash_compare_symbol (const symbol *m1, const symbol *m2)
394 {
395 /* Since tags are unique, we can compare the pointers themselves. */
396 return UNIQSTR_EQ (m1->tag, m2->tag);
397 }
398
399 static bool
400 hash_symbol_comparator (void const *m1, void const *m2)
401 {
402 return hash_compare_symbol (m1, m2);
403 }
404
405 static inline unsigned int
406 hash_symbol (const symbol *m, unsigned int tablesize)
407 {
408 /* Since tags are unique, we can hash the pointer itself. */
409 return ((uintptr_t) m->tag) % tablesize;
410 }
411
412 static unsigned int
413 hash_symbol_hasher (void const *m, unsigned int tablesize)
414 {
415 return hash_symbol (m, tablesize);
416 }
417
418
419 /*-------------------------------.
420 | Create the symbol hash table. |
421 `-------------------------------*/
422
423 void
424 symbols_new (void)
425 {
426 symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
427 NULL,
428 hash_symbol_hasher,
429 hash_symbol_comparator,
430 free);
431 }
432
433
434 /*----------------------------------------------------------------.
435 | Find the symbol named KEY, and return it. If it does not exist |
436 | yet, create it. |
437 `----------------------------------------------------------------*/
438
439 symbol *
440 symbol_get (const char *key, location loc)
441 {
442 symbol probe;
443 symbol *entry;
444
445 /* Keep the symbol in a printable form. */
446 key = uniqstr_new (quotearg_style (escape_quoting_style, key));
447 probe.tag = key;
448 entry = hash_lookup (symbol_table, &probe);
449
450 if (!entry)
451 {
452 /* First insertion in the hash. */
453 entry = symbol_new (key, loc);
454 hash_insert (symbol_table, entry);
455 }
456 return entry;
457 }
458
459
460 /*------------------------------------------------------------------.
461 | Generate a dummy nonterminal, whose name cannot conflict with the |
462 | user's names. |
463 `------------------------------------------------------------------*/
464
465 symbol *
466 dummy_symbol_get (location loc)
467 {
468 /* Incremented for each generated symbol. */
469 static int dummy_count = 0;
470 static char buf[256];
471
472 symbol *sym;
473
474 sprintf (buf, "@%d", ++dummy_count);
475 sym = symbol_get (buf, loc);
476 sym->class = nterm_sym;
477 sym->number = nvars++;
478 return sym;
479 }
480
481
482 /*-------------------.
483 | Free the symbols. |
484 `-------------------*/
485
486 void
487 symbols_free (void)
488 {
489 hash_free (symbol_table);
490 free (symbols);
491 }
492
493
494 /*---------------------------------------------------------------.
495 | Look for undefined symbols, report an error, and consider them |
496 | terminals. |
497 `---------------------------------------------------------------*/
498
499 static void
500 symbols_do (Hash_processor processor, void *processor_data)
501 {
502 hash_do_for_each (symbol_table, processor, processor_data);
503 }
504
505
506 /*--------------------------------------------------------------.
507 | Check that all the symbols are defined. Report any undefined |
508 | symbols and consider them nonterminals. |
509 `--------------------------------------------------------------*/
510
511 void
512 symbols_check_defined (void)
513 {
514 symbols_do (symbol_check_defined_processor, NULL);
515 }
516
517 /*------------------------------------------------------------------.
518 | Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
519 | number. |
520 `------------------------------------------------------------------*/
521
522 static void
523 symbols_token_translations_init (void)
524 {
525 bool num_256_available_p = true;
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 {
533 symbol *this = symbols[i];
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)
539 num_256_available_p = false;
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 {
554 symbol *this = symbols[i];
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
561 CALLOC (token_translations, max_user_token_number + 1);
562
563 /* Initialize all entries for literal tokens to 2, the internal
564 token number for $undefined, which represents all invalid inputs.
565 */
566 for (i = 0; i < max_user_token_number + 1; i++)
567 token_translations[i] = undeftoken->number;
568 symbols_do (symbol_translation_processor, NULL);
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
577 void
578 symbols_pack (void)
579 {
580 CALLOC (symbols, nsyms);
581
582 symbols_do (symbol_check_alias_consistency_processor, NULL);
583 symbols_do (symbol_pack_processor, NULL);
584
585 symbols_token_translations_init ();
586
587 if (startsymbol->class == unknown_sym)
588 fatal_at (startsymbol_location,
589 _("the start symbol %s is undefined"),
590 startsymbol->tag);
591 else if (startsymbol->class == token_sym)
592 fatal_at (startsymbol_location,
593 _("the start symbol %s is a token"),
594 startsymbol->tag);
595 }