]> git.saurik.com Git - bison.git/blame_incremental - src/symtab.c
* ro.po: New.
[bison.git] / src / symtab.c
... / ...
CommitLineData
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
36symbol *errtoken = NULL;
37symbol *undeftoken = NULL;
38symbol *endtoken = NULL;
39symbol *accept = NULL;
40symbol *startsymbol = NULL;
41location startsymbol_location;
42
43/*---------------------------------.
44| Create a new symbol, named TAG. |
45`---------------------------------*/
46
47static symbol *
48symbol_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
78void
79symbol_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
95void
96symbol_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
113void
114symbol_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
132void
133symbol_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
152void
153symbol_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
171void
172symbol_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
199static inline bool
200symbol_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
215static bool
216symbol_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
227void
228symbol_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
260static inline bool
261symbol_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
294static bool
295symbol_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
307static inline bool
308symbol_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
344static bool
345symbol_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
357static inline bool
358symbol_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
377static bool
378symbol_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
391static struct hash_table *symbol_table = NULL;
392
393static inline bool
394hash_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
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
407hash_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
413static unsigned int
414hash_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
424void
425symbols_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
440symbol *
441symbol_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
466symbol *
467dummy_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
487void
488symbols_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
500static void
501symbols_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
512void
513symbols_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
523static void
524symbols_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
578void
579symbols_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}