]> git.saurik.com Git - bison.git/blame - src/symtab.c
* src/symtab.c, src/symtab.c (symbol_class_set)
[bison.git] / src / symtab.c
CommitLineData
40675e7c 1/* Symbol table manager for Bison,
72a23c97 2 Copyright (C) 1984, 1989, 2000, 2001, 2002 Free Software Foundation, Inc.
40675e7c 3
95e36146 4 This file is part of Bison, the GNU Compiler Compiler.
40675e7c 5
95e36146
AD
6 Bison is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
40675e7c 10
95e36146
AD
11 Bison is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
40675e7c 15
95e36146
AD
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
40675e7c
DM
20
21
40675e7c 22#include "system.h"
72a23c97 23#include "hash.h"
2f1afb73 24#include "complain.h"
40675e7c
DM
25#include "symtab.h"
26#include "gram.h"
27
2f1afb73
AD
28/*------------------------.
29| Distinguished symbols. |
30`------------------------*/
31
32symbol_t *errtoken = NULL;
33symbol_t *undeftoken = NULL;
34symbol_t *eoftoken = NULL;
35symbol_t *axiom = NULL;
36symbol_t *startsymbol = NULL;
37
72a23c97
AD
38/*---------------------------------.
39| Create a new symbol, named TAG. |
40`---------------------------------*/
1e9798d5 41
db8837cb
AD
42static symbol_t *
43symbol_new (const char *tag)
1e9798d5 44{
db8837cb 45 symbol_t *res = XMALLOC (symbol_t, 1);
1e9798d5 46
1e9798d5
AD
47 res->tag = xstrdup (tag);
48 res->type_name = NULL;
5fbb0954 49 res->number = NUMBER_UNDEFINED;
1e9798d5
AD
50 res->prec = 0;
51 res->assoc = right_assoc;
b87f8b21 52 res->user_token_number = USER_NUMBER_UNDEFINED;
1e9798d5
AD
53 res->alias = NULL;
54 res->class = unknown_sym;
55
56 nsyms++;
57
58 return res;
59}
60
40675e7c 61
3ae2b51f
AD
62/*-----------------------------------------.
63| Set the TYPE_NAME associated to SYMBOL. |
64`-----------------------------------------*/
65
66void
67symbol_type_set (symbol_t *symbol, char *type_name)
68{
69 if (symbol->type_name)
70 complain (_("type redeclaration for %s"), symbol->tag);
71 symbol->type_name = type_name;
72}
73
74
75/*------------------------------------------.
76| Set the PRECEDENCE associated to SYMBOL. |
77`------------------------------------------*/
78
79void
80symbol_precedence_set (symbol_t *symbol,
81 int prec, associativity assoc)
82{
83 if (symbol->prec != 0)
84 complain (_("redefining precedence of %s"), symbol->tag);
85 symbol->prec = prec;
86 symbol->assoc = assoc;
87}
88
89
44536b35
AD
90/*-------------------------------------.
91| Set the CLASS associated to SYMBOL. |
92`-------------------------------------*/
93
94void
95symbol_class_set (symbol_t *symbol, symbol_class class)
96{
97 if (symbol->class != unknown_sym && symbol->class != class)
98 complain (_("symbol %s redefined"), symbol->tag);
99
100 if (class == nterm_sym && symbol->class != nterm_sym)
101 symbol->number = nvars++;
102 else if (class == token_sym && symbol->number == NUMBER_UNDEFINED)
103 symbol->number = ntokens++;
104
105 symbol->class = class;
106}
107
108
109/*-------------------------------------------------.
110| Set the USER_TOKEN_NUMBER associated to SYMBOL. |
111`-------------------------------------------------*/
112
113void
114symbol_user_token_number_set (symbol_t *symbol, int user_token_number)
115{
116 assert (symbol->class == token_sym);
117
118 if (symbol->user_token_number != USER_NUMBER_UNDEFINED)
119 complain (_("redefining user token number of %s"), symbol->tag);
120
121 symbol->user_token_number = user_token_number;
122 /* User defined EOF token? */
123 if (user_token_number == 0)
124 {
125 eoftoken = symbol;
126 eoftoken->number = 0;
127 /* It is always mapped to 0, so it was already counted in
128 NTOKENS. */
129 --ntokens;
130 }
131}
132
133
72a23c97
AD
134/*------------.
135| Free THIS. |
136`------------*/
137
138static void
db8837cb 139symbol_free (symbol_t *this)
40675e7c 140{
72a23c97
AD
141#if 0
142 /* This causes crashes because one string can appear more
143 than once. */
144 XFREE (this->type_name);
145#endif
146 XFREE (this->tag);
147 XFREE (this);
148}
149
150
2f1afb73
AD
151/*-----------------------------------------------------------.
152| If THIS is not defined, report an error, and consider it a |
153| nonterminal. |
154`-----------------------------------------------------------*/
155
156static bool
157symbol_check_defined (symbol_t *this)
158{
159 if (this->class == unknown_sym)
160 {
161 complain
162 (_("symbol %s is used, but is not defined as a token and has no rules"),
163 this->tag);
164 this->class = nterm_sym;
165 this->number = nvars++;
166 }
167
168 return TRUE;
169}
170
171
172/*-------------------------------------------------------------------.
173| Declare the new SYMBOL. Make it an alias of SYMVAL, and type them |
174| with TYPENAME. |
175`-------------------------------------------------------------------*/
176
177void
178symbol_make_alias (symbol_t *symbol, symbol_t *symval, char *typename)
179{
180 if (symval->alias)
181 warn (_("symbol `%s' used more than once as a literal string"),
182 symval->tag);
183 else if (symbol->alias)
184 warn (_("symbol `%s' given more than one literal string"),
185 symbol->tag);
186 else
187 {
188 symval->class = token_sym;
189 symval->type_name = typename;
190 symval->user_token_number = symbol->user_token_number;
191 symbol->user_token_number = USER_NUMBER_ALIAS;
192 symval->alias = symbol;
193 symbol->alias = symval;
194 /* symbol and symval combined are only one symbol */
195 nsyms--;
196 ntokens--;
197 assert (ntokens == symbol->number || ntokens == symval->number);
198 symbol->number = symval->number =
199 (symval->number < symbol->number) ? symval->number : symbol->number;
200 }
201}
202
203
204/*---------------------------------------------------------.
205| Check that THIS, and its alias, have same precedence and |
206| associativity. |
207`---------------------------------------------------------*/
208
209static bool
210symbol_check_alias_consistence (symbol_t *this)
211{
212 /* Check only those who _are_ the aliases. */
213 if (this->alias && this->user_token_number == USER_NUMBER_ALIAS)
214 {
215 if (this->prec != this->alias->prec)
216 {
217 if (this->prec != 0 && this->alias->prec != 0)
218 complain (_("conflicting precedences for %s and %s"),
219 this->tag, this->alias->tag);
220 if (this->prec != 0)
221 this->alias->prec = this->prec;
222 else
223 this->prec = this->alias->prec;
224 }
225
226 if (this->assoc != this->alias->assoc)
227 {
228 if (this->assoc != 0 && this->alias->assoc != 0)
229 complain (_("conflicting assoc values for %s and %s"),
230 this->tag, this->alias->tag);
231 if (this->assoc != 0)
232 this->alias->assoc = this->assoc;
233 else
234 this->assoc = this->alias->assoc;
235 }
236 }
237 return TRUE;
238}
239
240
241/*-------------------------------------------------------------------.
242| Assign a symbol number, and write the definition of the token name |
243| into FDEFINES. Put in SYMBOLS. |
244`-------------------------------------------------------------------*/
245
246static bool
247symbol_pack (symbol_t *this)
248{
249 if (this->class == nterm_sym)
250 {
251 this->number += ntokens;
252 }
253 else if (this->alias)
254 {
255 /* This symbol and its alias are a single token defn.
256 Allocate a tokno, and assign to both check agreement of
257 prec and assoc fields and make both the same */
258 if (this->number == NUMBER_UNDEFINED)
259 {
260 if (this == eoftoken || this->alias == eoftoken)
261 this->number = this->alias->number = 0;
262 else
263 {
264 assert (this->alias->number != NUMBER_UNDEFINED);
265 this->number = this->alias->number;
266 }
267 }
268 /* Do not do processing below for USER_NUMBER_ALIASs. */
269 if (this->user_token_number == USER_NUMBER_ALIAS)
270 return TRUE;
271 }
272 else /* this->class == token_sym */
273 {
274 assert (this->number != NUMBER_UNDEFINED);
275 }
276
277 symbols[this->number] = this;
278 return TRUE;
279}
280
281
282
283
284/*--------------------------------------------------.
285| Put THIS in TOKEN_TRANSLATIONS if it is a token. |
286`--------------------------------------------------*/
287
288static bool
289symbol_translation (symbol_t *this)
290{
291 /* Non-terminal? */
292 if (this->class == token_sym
293 && this->user_token_number != USER_NUMBER_ALIAS)
294 {
295 /* A token which translation has already been set? */
296 if (token_translations[this->user_token_number] != undeftoken->number)
297 complain (_("tokens %s and %s both assigned number %d"),
298 symbols[token_translations[this->user_token_number]]->tag,
299 this->tag, this->user_token_number);
300
301 token_translations[this->user_token_number] = this->number;
302 }
303
304 return TRUE;
305}
306
72a23c97
AD
307
308/*----------------------.
2f1afb73 309| A symbol hash table. |
72a23c97 310`----------------------*/
40675e7c 311
db8837cb 312/* Initial capacity of symbols hash table. */
72a23c97
AD
313#define HT_INITIAL_CAPACITY 257
314
db8837cb 315static struct hash_table *symbol_table = NULL;
72a23c97
AD
316
317static bool
db8837cb 318hash_compare_symbol_t (const symbol_t *m1, const symbol_t *m2)
72a23c97
AD
319{
320 return strcmp (m1->tag, m2->tag) ? FALSE : TRUE;
321}
322
323static unsigned int
db8837cb 324hash_symbol_t (const symbol_t *m, unsigned int tablesize)
72a23c97
AD
325{
326 return hash_string (m->tag, tablesize);
327}
328
329
330/*-------------------------------.
2f1afb73 331| Create the symbol hash table. |
72a23c97
AD
332`-------------------------------*/
333
334void
db8837cb 335symbols_new (void)
72a23c97 336{
db8837cb 337 symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
72a23c97 338 NULL,
db8837cb
AD
339 (Hash_hasher) hash_symbol_t,
340 (Hash_comparator) hash_compare_symbol_t,
341 (Hash_data_freer) symbol_free);
40675e7c
DM
342}
343
344
1e9798d5
AD
345/*----------------------------------------------------------------.
346| Find the symbol named KEY, and return it. If it does not exist |
347| yet, create it. |
348`----------------------------------------------------------------*/
349
db8837cb 350symbol_t *
4a120d45 351getsym (const char *key)
40675e7c 352{
db8837cb
AD
353 symbol_t probe;
354 symbol_t *entry;
40675e7c 355
72a23c97 356 (const char *) probe.tag = key;
db8837cb 357 entry = hash_lookup (symbol_table, &probe);
40675e7c 358
72a23c97 359 if (!entry)
40675e7c 360 {
72a23c97 361 /* First insertion in the hash. */
db8837cb
AD
362 entry = symbol_new (key);
363 hash_insert (symbol_table, entry);
40675e7c 364 }
72a23c97
AD
365 return entry;
366}
40675e7c 367
40675e7c 368
72a23c97 369/*-------------------.
db8837cb 370| Free the symbols. |
72a23c97
AD
371`-------------------*/
372
373void
db8837cb 374symbols_free (void)
72a23c97 375{
db8837cb 376 hash_free (symbol_table);
40675e7c
DM
377}
378
379
72a23c97 380/*---------------------------------------------------------------.
db8837cb 381| Look for undefined symbols, report an error, and consider them |
72a23c97
AD
382| terminals. |
383`---------------------------------------------------------------*/
384
40675e7c 385void
db8837cb 386symbols_do (symbol_processor processor, void *processor_data)
40675e7c 387{
db8837cb 388 hash_do_for_each (symbol_table,
72a23c97
AD
389 (Hash_processor) processor,
390 processor_data);
40675e7c 391}
2f1afb73
AD
392
393
394/*--------------------------------------------------------------.
395| Check that all the symbols are defined. Report any undefined |
396| symbols and consider them nonterminals. |
397`--------------------------------------------------------------*/
398
399void
400symbols_check_defined (void)
401{
402 symbols_do (symbol_check_defined, NULL);
403}
404
405/*------------------------------------------------------------------.
406| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
407| number. |
408`------------------------------------------------------------------*/
409
410static void
411symbols_token_translations_init (void)
412{
413 int num_256_available_p = TRUE;
414 int i;
415
416 /* Find the highest user token number, and whether 256, the POSIX
417 preferred user token number for the error token, is used. */
418 max_user_token_number = 0;
419 for (i = 0; i < ntokens; ++i)
420 {
421 symbol_t *this = symbols[i];
422 if (this->user_token_number != USER_NUMBER_UNDEFINED)
423 {
424 if (this->user_token_number > max_user_token_number)
425 max_user_token_number = this->user_token_number;
426 if (this->user_token_number == 256)
427 num_256_available_p = FALSE;
428 }
429 }
430
431 /* If 256 is not used, assign it to error, to follow POSIX. */
432 if (num_256_available_p
433 && errtoken->user_token_number == USER_NUMBER_UNDEFINED)
434 errtoken->user_token_number = 256;
435
436 /* Set the missing user numbers. */
437 if (max_user_token_number < 256)
438 max_user_token_number = 256;
439
440 for (i = 0; i < ntokens; ++i)
441 {
442 symbol_t *this = symbols[i];
443 if (this->user_token_number == USER_NUMBER_UNDEFINED)
444 this->user_token_number = ++max_user_token_number;
445 if (this->user_token_number > max_user_token_number)
446 max_user_token_number = this->user_token_number;
447 }
448
449 token_translations = XCALLOC (symbol_number_t, max_user_token_number + 1);
450
451 /* Initialize all entries for literal tokens to 2, the internal
452 token number for $undefined., which represents all invalid
453 inputs. */
454 for (i = 0; i < max_user_token_number + 1; i++)
455 token_translations[i] = undeftoken->number;
456 symbols_do (symbol_translation, NULL);
457}
458
459
460/*----------------------------------------------------------------.
461| Assign symbol numbers, and write definition of token names into |
462| FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. |
463`----------------------------------------------------------------*/
464
465void
466symbols_pack (void)
467{
468 symbols = XCALLOC (symbol_t *, nsyms);
469
470 symbols_do (symbol_check_alias_consistence, NULL);
471 symbols_do (symbol_pack, NULL);
472
473 symbols_token_translations_init ();
474
475 if (startsymbol->class == unknown_sym)
476 fatal (_("the start symbol %s is undefined"), startsymbol->tag);
477 else if (startsymbol->class == token_sym)
478 fatal (_("the start symbol %s is a token"), startsymbol->tag);
479}