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