]> git.saurik.com Git - bison.git/blame_incremental - src/symtab.c
Credit Satya for the graphviz change.
[bison.git] / src / symtab.c
... / ...
CommitLineData
1/* Symbol table manager for Bison.
2
3 Copyright (C) 1984, 1989, 2000, 2001, 2002, 2004, 2005, 2006 Free
4 Software Foundation, Inc.
5
6 This file is part of Bison, the GNU Compiler Compiler.
7
8 Bison is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 Bison is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bison; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23#include <config.h>
24#include "system.h"
25
26#include <hash.h>
27#include <quotearg.h>
28
29#include "complain.h"
30#include "gram.h"
31#include "symtab.h"
32
33/*------------------------.
34| Distinguished symbols. |
35`------------------------*/
36
37symbol *errtoken = NULL;
38symbol *undeftoken = NULL;
39symbol *endtoken = NULL;
40symbol *accept = NULL;
41symbol *startsymbol = NULL;
42location startsymbol_location;
43
44/*-----------------------------------.
45| Default %destructor and %printer. |
46`-----------------------------------*/
47
48static const char *default_destructor = NULL;
49static location default_destructor_location;
50static const char *default_printer = NULL;
51static location default_printer_location;
52
53/*---------------------------------.
54| Create a new symbol, named TAG. |
55`---------------------------------*/
56
57static symbol *
58symbol_new (uniqstr tag, location loc)
59{
60 symbol *res = xmalloc (sizeof *res);
61
62 uniqstr_assert (tag);
63 res->tag = tag;
64 res->location = loc;
65
66 res->type_name = NULL;
67 res->destructor = NULL;
68 res->printer = NULL;
69
70 res->number = NUMBER_UNDEFINED;
71 res->prec = 0;
72 res->assoc = undef_assoc;
73 res->user_token_number = USER_NUMBER_UNDEFINED;
74
75 res->alias = NULL;
76 res->class = unknown_sym;
77 res->declared = false;
78
79 if (nsyms == SYMBOL_NUMBER_MAXIMUM)
80 fatal (_("too many symbols in input grammar (limit is %d)"),
81 SYMBOL_NUMBER_MAXIMUM);
82 nsyms++;
83 return res;
84}
85
86/*----------------------------------------.
87| Create a new semantic type, named TAG. |
88`----------------------------------------*/
89
90static semantic_type *
91semantic_type_new (uniqstr tag)
92{
93 semantic_type *res = xmalloc (sizeof *res);
94
95 uniqstr_assert (tag);
96 res->tag = tag;
97 res->destructor = NULL;
98 res->printer = NULL;
99
100 return res;
101}
102
103
104/*-----------------.
105| Print a symbol. |
106`-----------------*/
107
108#define SYMBOL_ATTR_PRINT(Attr) \
109 if (s->Attr) \
110 fprintf (f, " %s { %s }", #Attr, s->Attr)
111
112void
113symbol_print (symbol *s, FILE *f)
114{
115 if (s)
116 {
117 fprintf (f, "\"%s\"", s->tag);
118 SYMBOL_ATTR_PRINT (type_name);
119 SYMBOL_ATTR_PRINT (destructor);
120 SYMBOL_ATTR_PRINT (printer);
121 }
122 else
123 fprintf (f, "<NULL>");
124}
125
126#undef SYMBOL_ATTR_PRINT
127
128/*------------------------------------------------------------------.
129| Complain that S's WHAT is redeclared at SECOND, and was first set |
130| at FIRST. |
131`------------------------------------------------------------------*/
132
133static void
134symbol_redeclaration (symbol *s, const char *what, location first,
135 location second)
136{
137 complain_at (second, _("%s redeclaration for %s"), what, s->tag);
138 complain_at (first, _("previous declaration"));
139}
140
141static void
142semantic_type_redeclaration (semantic_type *s, const char *what, location first,
143 location second)
144{
145 complain_at (second, _("%s redeclaration for <%s>"), what, s->tag);
146 complain_at (first, _("previous declaration"));
147}
148
149
150/*-----------------------------------------------------------------.
151| Set the TYPE_NAME associated with SYM. Does nothing if passed 0 |
152| as TYPE_NAME. |
153`-----------------------------------------------------------------*/
154
155void
156symbol_type_set (symbol *sym, uniqstr type_name, location loc)
157{
158 if (type_name)
159 {
160 if (sym->type_name)
161 symbol_redeclaration (sym, "%type", sym->type_location, loc);
162 uniqstr_assert (type_name);
163 sym->type_name = type_name;
164 sym->type_location = loc;
165 }
166}
167
168
169/*------------------------------------------------------------------.
170| Set the DESTRUCTOR associated with SYM. Do nothing if passed 0. |
171`------------------------------------------------------------------*/
172
173void
174symbol_destructor_set (symbol *sym, const char *destructor, location loc)
175{
176 if (destructor)
177 {
178 if (sym->destructor)
179 symbol_redeclaration (sym, "%destructor", sym->destructor_location,
180 loc);
181 sym->destructor = destructor;
182 sym->destructor_location = loc;
183 }
184}
185
186/*-------------------------------------------------------------------.
187| Set the DESTRUCTOR associated with TYPE. Do nothing if passed 0. |
188`-------------------------------------------------------------------*/
189
190void
191semantic_type_destructor_set (semantic_type *type, const char *destructor,
192 location loc)
193{
194 if (destructor)
195 {
196 if (type->destructor)
197 semantic_type_redeclaration (type, "%destructor",
198 type->destructor_location, loc);
199 type->destructor = destructor;
200 type->destructor_location = loc;
201 }
202}
203
204/*---------------------------------------.
205| Get the computed %destructor for SYM. |
206`---------------------------------------*/
207
208const char *
209symbol_destructor_get (symbol *sym)
210{
211 /* Per-symbol %destructor. */
212 if (sym->destructor != NULL)
213 return sym->destructor;
214
215 /* Per-type %destructor. */
216 if (sym->type_name)
217 {
218 semantic_type *type = semantic_type_get (sym->type_name);
219 if (type->destructor)
220 return type->destructor;
221 }
222
223 /* Apply the default %destructor only to user-defined symbols. */
224 if (sym->tag[0] == '$' || sym == errtoken)
225 return NULL;
226 return default_destructor;
227}
228
229/*---------------------------------------------------------------.
230| Get the grammar location of the %destructor computed for SYM. |
231`---------------------------------------------------------------*/
232
233location
234symbol_destructor_location_get (symbol *sym)
235{
236 if (sym->destructor != NULL)
237 return sym->destructor_location;
238 if (sym->type_name)
239 {
240 semantic_type *type = semantic_type_get (sym->type_name);
241 if (type->destructor)
242 return type->destructor_location;
243 }
244 return default_destructor_location;
245}
246
247/*---------------------------------------------------------------.
248| Set the PRINTER associated with SYM. Do nothing if passed 0. |
249`---------------------------------------------------------------*/
250
251void
252symbol_printer_set (symbol *sym, const char *printer, location loc)
253{
254 if (printer)
255 {
256 if (sym->printer)
257 symbol_redeclaration (sym, "%printer", sym->printer_location, loc);
258 sym->printer = printer;
259 sym->printer_location = loc;
260 }
261}
262
263/*----------------------------------------------------------------.
264| Set the PRINTER associated with TYPE. Do nothing if passed 0. |
265`----------------------------------------------------------------*/
266
267void
268semantic_type_printer_set (semantic_type *type, const char *printer,
269 location loc)
270{
271 if (printer)
272 {
273 if (type->printer)
274 semantic_type_redeclaration (type, "%printer", type->printer_location,
275 loc);
276 type->printer = printer;
277 type->printer_location = loc;
278 }
279}
280
281/*------------------------------------.
282| Get the computed %printer for SYM. |
283`------------------------------------*/
284
285const char *
286symbol_printer_get (symbol *sym)
287{
288 /* Per-symbol %printer. */
289 if (sym->printer != NULL)
290 return sym->printer;
291
292 /* Per-type %printer. */
293 if (sym->type_name)
294 {
295 semantic_type *type = semantic_type_get (sym->type_name);
296 if (type->printer)
297 return type->printer;
298 }
299
300 /* Apply the default %printer only to user-defined symbols. */
301 if (sym->tag[0] == '$' || sym == errtoken)
302 return NULL;
303 return default_printer;
304}
305
306/*------------------------------------------------------------.
307| Get the grammar location of the %printer computed for SYM. |
308`------------------------------------------------------------*/
309
310location
311symbol_printer_location_get (symbol *sym)
312{
313 if (sym->printer != NULL)
314 return sym->printer_location;
315 if (sym->type_name)
316 {
317 semantic_type *type = semantic_type_get (sym->type_name);
318 if (type->printer)
319 return type->printer_location;
320 }
321 return default_printer_location;
322}
323
324
325/*-----------------------------------------------------------------.
326| Set the PRECEDENCE associated with SYM. Does nothing if invoked |
327| with UNDEF_ASSOC as ASSOC. |
328`-----------------------------------------------------------------*/
329
330void
331symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
332{
333 if (a != undef_assoc)
334 {
335 if (sym->prec != 0)
336 symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
337 loc);
338 sym->prec = prec;
339 sym->assoc = a;
340 sym->prec_location = loc;
341 }
342
343 /* Only terminals have a precedence. */
344 symbol_class_set (sym, token_sym, loc, false);
345}
346
347
348/*------------------------------------.
349| Set the CLASS associated with SYM. |
350`------------------------------------*/
351
352void
353symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
354{
355 if (sym->class != unknown_sym && sym->class != class)
356 {
357 complain_at (loc, _("symbol %s redefined"), sym->tag);
358 sym->declared = false;
359 }
360
361 if (class == nterm_sym && sym->class != nterm_sym)
362 sym->number = nvars++;
363 else if (class == token_sym && sym->number == NUMBER_UNDEFINED)
364 sym->number = ntokens++;
365
366 sym->class = class;
367
368 if (declaring)
369 {
370 if (sym->declared)
371 warn_at (loc, _("symbol %s redeclared"), sym->tag);
372 sym->declared = true;
373 }
374}
375
376
377/*------------------------------------------------.
378| Set the USER_TOKEN_NUMBER associated with SYM. |
379`------------------------------------------------*/
380
381void
382symbol_user_token_number_set (symbol *sym, int user_token_number, location loc)
383{
384 int *user_token_numberp;
385
386 aver (sym->class == token_sym);
387
388 if (sym->user_token_number != USER_NUMBER_ALIAS)
389 user_token_numberp = &sym->user_token_number;
390 else
391 user_token_numberp = &sym->alias->user_token_number;
392 if (*user_token_numberp != USER_NUMBER_UNDEFINED
393 && *user_token_numberp != user_token_number)
394 complain_at (loc, _("redefining user token number of %s"), sym->tag);
395
396 *user_token_numberp = user_token_number;
397 /* User defined $end token? */
398 if (user_token_number == 0)
399 {
400 endtoken = sym;
401 endtoken->number = 0;
402 /* It is always mapped to 0, so it was already counted in
403 NTOKENS. */
404 --ntokens;
405 }
406}
407
408
409/*----------------------------------------------------------.
410| If SYM is not defined, report an error, and consider it a |
411| nonterminal. |
412`----------------------------------------------------------*/
413
414static inline bool
415symbol_check_defined (symbol *sym)
416{
417 if (sym->class == unknown_sym)
418 {
419 complain_at
420 (sym->location,
421 _("symbol %s is used, but is not defined as a token and has no rules"),
422 sym->tag);
423 sym->class = nterm_sym;
424 sym->number = nvars++;
425 }
426
427 return true;
428}
429
430static bool
431symbol_check_defined_processor (void *sym, void *null ATTRIBUTE_UNUSED)
432{
433 return symbol_check_defined (sym);
434}
435
436
437/*------------------------------------------------------------------.
438| Declare the new symbol SYM. Make it an alias of SYMVAL, and type |
439| SYMVAL with SYM's type. |
440`------------------------------------------------------------------*/
441
442void
443symbol_make_alias (symbol *sym, symbol *symval, location loc)
444{
445 if (symval->alias)
446 warn_at (loc, _("symbol `%s' used more than once as a literal string"),
447 symval->tag);
448 else if (sym->alias)
449 warn_at (loc, _("symbol `%s' given more than one literal string"),
450 sym->tag);
451 else
452 {
453 symval->class = token_sym;
454 symval->user_token_number = sym->user_token_number;
455 sym->user_token_number = USER_NUMBER_ALIAS;
456 symval->alias = sym;
457 sym->alias = symval;
458 symval->number = sym->number;
459 symbol_type_set (symval, sym->type_name, loc);
460 }
461}
462
463
464/*---------------------------------------------------------.
465| Check that THIS, and its alias, have same precedence and |
466| associativity. |
467`---------------------------------------------------------*/
468
469static inline void
470symbol_check_alias_consistency (symbol *this)
471{
472 symbol *alias = this;
473 symbol *orig = this->alias;
474
475 /* Check only those that _are_ the aliases. */
476 if (!(this->alias && this->user_token_number == USER_NUMBER_ALIAS))
477 return;
478
479 if (orig->type_name != alias->type_name)
480 {
481 if (orig->type_name)
482 symbol_type_set (alias, orig->type_name, orig->type_location);
483 else
484 symbol_type_set (orig, alias->type_name, alias->type_location);
485 }
486
487
488 if (orig->destructor || alias->destructor)
489 {
490 if (orig->destructor)
491 symbol_destructor_set (alias, orig->destructor,
492 orig->destructor_location);
493 else
494 symbol_destructor_set (orig, alias->destructor,
495 alias->destructor_location);
496 }
497
498 if (orig->printer || alias->printer)
499 {
500 if (orig->printer)
501 symbol_printer_set (alias, orig->printer, orig->printer_location);
502 else
503 symbol_printer_set (orig, alias->printer, alias->printer_location);
504 }
505
506 if (alias->prec || orig->prec)
507 {
508 if (orig->prec)
509 symbol_precedence_set (alias, orig->prec, orig->assoc,
510 orig->prec_location);
511 else
512 symbol_precedence_set (orig, alias->prec, alias->assoc,
513 alias->prec_location);
514 }
515}
516
517static bool
518symbol_check_alias_consistency_processor (void *this,
519 void *null ATTRIBUTE_UNUSED)
520{
521 symbol_check_alias_consistency (this);
522 return true;
523}
524
525
526/*-------------------------------------------------------------------.
527| Assign a symbol number, and write the definition of the token name |
528| into FDEFINES. Put in SYMBOLS. |
529`-------------------------------------------------------------------*/
530
531static inline bool
532symbol_pack (symbol *this)
533{
534 if (this->class == nterm_sym)
535 {
536 this->number += ntokens;
537 }
538 else if (this->alias)
539 {
540 /* This symbol and its alias are a single token defn.
541 Allocate a tokno, and assign to both check agreement of
542 prec and assoc fields and make both the same */
543 if (this->number == NUMBER_UNDEFINED)
544 {
545 if (this == endtoken || this->alias == endtoken)
546 this->number = this->alias->number = 0;
547 else
548 {
549 aver (this->alias->number != NUMBER_UNDEFINED);
550 this->number = this->alias->number;
551 }
552 }
553 /* Do not do processing below for USER_NUMBER_ALIASes. */
554 if (this->user_token_number == USER_NUMBER_ALIAS)
555 return true;
556 }
557 else /* this->class == token_sym */
558 aver (this->number != NUMBER_UNDEFINED);
559
560 symbols[this->number] = this;
561 return true;
562}
563
564static bool
565symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED)
566{
567 return symbol_pack (this);
568}
569
570
571
572
573/*--------------------------------------------------.
574| Put THIS in TOKEN_TRANSLATIONS if it is a token. |
575`--------------------------------------------------*/
576
577static inline bool
578symbol_translation (symbol *this)
579{
580 /* Non-terminal? */
581 if (this->class == token_sym
582 && this->user_token_number != USER_NUMBER_ALIAS)
583 {
584 /* A token which translation has already been set? */
585 if (token_translations[this->user_token_number] != undeftoken->number)
586 complain_at (this->location,
587 _("tokens %s and %s both assigned number %d"),
588 symbols[token_translations[this->user_token_number]]->tag,
589 this->tag, this->user_token_number);
590
591 token_translations[this->user_token_number] = this->number;
592 }
593
594 return true;
595}
596
597static bool
598symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED)
599{
600 return symbol_translation (this);
601}
602
603
604/*---------------------------------------.
605| Symbol and semantic type hash tables. |
606`---------------------------------------*/
607
608/* Initial capacity of symbol and semantic type hash table. */
609#define HT_INITIAL_CAPACITY 257
610
611static struct hash_table *symbol_table = NULL;
612static struct hash_table *semantic_type_table = NULL;
613
614static inline bool
615hash_compare_symbol (const symbol *m1, const symbol *m2)
616{
617 /* Since tags are unique, we can compare the pointers themselves. */
618 return UNIQSTR_EQ (m1->tag, m2->tag);
619}
620
621static inline bool
622hash_compare_semantic_type (const semantic_type *m1, const semantic_type *m2)
623{
624 /* Since names are unique, we can compare the pointers themselves. */
625 return UNIQSTR_EQ (m1->tag, m2->tag);
626}
627
628static bool
629hash_symbol_comparator (void const *m1, void const *m2)
630{
631 return hash_compare_symbol (m1, m2);
632}
633
634static bool
635hash_semantic_type_comparator (void const *m1, void const *m2)
636{
637 return hash_compare_semantic_type (m1, m2);
638}
639
640static inline size_t
641hash_symbol (const symbol *m, size_t tablesize)
642{
643 /* Since tags are unique, we can hash the pointer itself. */
644 return ((uintptr_t) m->tag) % tablesize;
645}
646
647static inline size_t
648hash_semantic_type (const semantic_type *m, size_t tablesize)
649{
650 /* Since names are unique, we can hash the pointer itself. */
651 return ((uintptr_t) m->tag) % tablesize;
652}
653
654static size_t
655hash_symbol_hasher (void const *m, size_t tablesize)
656{
657 return hash_symbol (m, tablesize);
658}
659
660static size_t
661hash_semantic_type_hasher (void const *m, size_t tablesize)
662{
663 return hash_semantic_type (m, tablesize);
664}
665
666/*-------------------------------.
667| Create the symbol hash table. |
668`-------------------------------*/
669
670void
671symbols_new (void)
672{
673 symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
674 NULL,
675 hash_symbol_hasher,
676 hash_symbol_comparator,
677 free);
678 semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY,
679 NULL,
680 hash_semantic_type_hasher,
681 hash_semantic_type_comparator,
682 free);
683}
684
685
686/*----------------------------------------------------------------.
687| Find the symbol named KEY, and return it. If it does not exist |
688| yet, create it. |
689`----------------------------------------------------------------*/
690
691symbol *
692symbol_from_uniqstr (const uniqstr key, location loc)
693{
694 symbol probe;
695 symbol *entry;
696
697 probe.tag = key;
698 entry = hash_lookup (symbol_table, &probe);
699
700 if (!entry)
701 {
702 /* First insertion in the hash. */
703 entry = symbol_new (key, loc);
704 hash_insert (symbol_table, entry);
705 }
706 return entry;
707}
708
709
710/*-----------------------------------------------------------------------.
711| Find the semantic type named KEY, and return it. If it does not exist |
712| yet, create it. |
713`-----------------------------------------------------------------------*/
714
715semantic_type *
716semantic_type_from_uniqstr (const uniqstr key)
717{
718 semantic_type probe;
719 semantic_type *entry;
720
721 probe.tag = key;
722 entry = hash_lookup (semantic_type_table, &probe);
723
724 if (!entry)
725 {
726 /* First insertion in the hash. */
727 entry = semantic_type_new (key);
728 hash_insert (semantic_type_table, entry);
729 }
730 return entry;
731}
732
733
734/*----------------------------------------------------------------.
735| Find the symbol named KEY, and return it. If it does not exist |
736| yet, create it. |
737`----------------------------------------------------------------*/
738
739symbol *
740symbol_get (const char *key, location loc)
741{
742 return symbol_from_uniqstr (uniqstr_new (key), loc);
743}
744
745
746/*-----------------------------------------------------------------------.
747| Find the semantic type named KEY, and return it. If it does not exist |
748| yet, create it. |
749`-----------------------------------------------------------------------*/
750
751semantic_type *
752semantic_type_get (const char *key)
753{
754 return semantic_type_from_uniqstr (uniqstr_new (key));
755}
756
757
758/*------------------------------------------------------------------.
759| Generate a dummy nonterminal, whose name cannot conflict with the |
760| user's names. |
761`------------------------------------------------------------------*/
762
763symbol *
764dummy_symbol_get (location loc)
765{
766 /* Incremented for each generated symbol. */
767 static int dummy_count = 0;
768 static char buf[256];
769
770 symbol *sym;
771
772 sprintf (buf, "@%d", ++dummy_count);
773 sym = symbol_get (buf, loc);
774 sym->class = nterm_sym;
775 sym->number = nvars++;
776 return sym;
777}
778
779bool
780symbol_is_dummy (const symbol *sym)
781{
782 return sym->tag[0] == '@';
783}
784
785/*-------------------.
786| Free the symbols. |
787`-------------------*/
788
789void
790symbols_free (void)
791{
792 hash_free (symbol_table);
793 hash_free (semantic_type_table);
794 free (symbols);
795}
796
797
798/*---------------------------------------------------------------.
799| Look for undefined symbols, report an error, and consider them |
800| terminals. |
801`---------------------------------------------------------------*/
802
803static void
804symbols_do (Hash_processor processor, void *processor_data)
805{
806 hash_do_for_each (symbol_table, processor, processor_data);
807}
808
809
810/*--------------------------------------------------------------.
811| Check that all the symbols are defined. Report any undefined |
812| symbols and consider them nonterminals. |
813`--------------------------------------------------------------*/
814
815void
816symbols_check_defined (void)
817{
818 symbols_do (symbol_check_defined_processor, NULL);
819}
820
821/*------------------------------------------------------------------.
822| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same |
823| number. |
824`------------------------------------------------------------------*/
825
826static void
827symbols_token_translations_init (void)
828{
829 bool num_256_available_p = true;
830 int i;
831
832 /* Find the highest user token number, and whether 256, the POSIX
833 preferred user token number for the error token, is used. */
834 max_user_token_number = 0;
835 for (i = 0; i < ntokens; ++i)
836 {
837 symbol *this = symbols[i];
838 if (this->user_token_number != USER_NUMBER_UNDEFINED)
839 {
840 if (this->user_token_number > max_user_token_number)
841 max_user_token_number = this->user_token_number;
842 if (this->user_token_number == 256)
843 num_256_available_p = false;
844 }
845 }
846
847 /* If 256 is not used, assign it to error, to follow POSIX. */
848 if (num_256_available_p
849 && errtoken->user_token_number == USER_NUMBER_UNDEFINED)
850 errtoken->user_token_number = 256;
851
852 /* Set the missing user numbers. */
853 if (max_user_token_number < 256)
854 max_user_token_number = 256;
855
856 for (i = 0; i < ntokens; ++i)
857 {
858 symbol *this = symbols[i];
859 if (this->user_token_number == USER_NUMBER_UNDEFINED)
860 this->user_token_number = ++max_user_token_number;
861 if (this->user_token_number > max_user_token_number)
862 max_user_token_number = this->user_token_number;
863 }
864
865 token_translations = xnmalloc (max_user_token_number + 1,
866 sizeof *token_translations);
867
868 /* Initialize all entries for literal tokens to 2, the internal
869 token number for $undefined, which represents all invalid inputs.
870 */
871 for (i = 0; i < max_user_token_number + 1; i++)
872 token_translations[i] = undeftoken->number;
873 symbols_do (symbol_translation_processor, NULL);
874}
875
876
877/*----------------------------------------------------------------.
878| Assign symbol numbers, and write definition of token names into |
879| FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. |
880`----------------------------------------------------------------*/
881
882void
883symbols_pack (void)
884{
885 symbols_do (symbol_check_alias_consistency_processor, NULL);
886
887 symbols = xcalloc (nsyms, sizeof *symbols);
888 symbols_do (symbol_pack_processor, NULL);
889
890 /* Aliases leave empty slots in symbols, so remove them. */
891 {
892 int writei;
893 int readi;
894 int nsyms_old = nsyms;
895 for (writei = 0, readi = 0; readi < nsyms_old; readi += 1)
896 {
897 if (symbols[readi] == NULL)
898 {
899 nsyms -= 1;
900 ntokens -= 1;
901 }
902 else
903 {
904 symbols[writei] = symbols[readi];
905 symbols[writei]->number = writei;
906 if (symbols[writei]->alias)
907 symbols[writei]->alias->number = writei;
908 writei += 1;
909 }
910 }
911 }
912 symbols = xnrealloc (symbols, nsyms, sizeof *symbols);
913
914 symbols_token_translations_init ();
915
916 if (startsymbol->class == unknown_sym)
917 fatal_at (startsymbol_location,
918 _("the start symbol %s is undefined"),
919 startsymbol->tag);
920 else if (startsymbol->class == token_sym)
921 fatal_at (startsymbol_location,
922 _("the start symbol %s is a token"),
923 startsymbol->tag);
924}
925
926
927/*-----------------------------------.
928| Set default %destructor/%printer. |
929`-----------------------------------*/
930
931void
932default_destructor_set (const char *destructor, location loc)
933{
934 if (default_destructor != NULL)
935 {
936 complain_at (loc, _("redeclaration for default %%destructor"));
937 complain_at (default_destructor_location, _("previous declaration"));
938 }
939 default_destructor = destructor;
940 default_destructor_location = loc;
941}
942
943void
944default_printer_set (const char *printer, location loc)
945{
946 if (default_printer != NULL)
947 {
948 complain_at (loc, _("redeclaration for default %%printer"));
949 complain_at (default_printer_location, _("previous declaration"));
950 }
951 default_printer = printer;
952 default_printer_location = loc;
953}