+
+
+
+/*--------------------------------------------------.
+| Put THIS in TOKEN_TRANSLATIONS if it is a token. |
+`--------------------------------------------------*/
+
+static bool
+symbol_translation (symbol_t *this)
+{
+ /* Non-terminal? */
+ if (this->class == token_sym
+ && this->user_token_number != USER_NUMBER_ALIAS)
+ {
+ /* A token which translation has already been set? */
+ if (token_translations[this->user_token_number] != undeftoken->number)
+ complain_at (this->location,
+ _("tokens %s and %s both assigned number %d"),
+ symbols[token_translations[this->user_token_number]]->tag,
+ this->tag, this->user_token_number);
+
+ token_translations[this->user_token_number] = this->number;
+ }
+
+ return TRUE;
+}
+
+
+/*----------------------.
+| A symbol hash table. |
+`----------------------*/
+
+/* Initial capacity of symbols hash table. */
+#define HT_INITIAL_CAPACITY 257
+
+static struct hash_table *symbol_table = NULL;
+
+static bool
+hash_compare_symbol_t (const symbol_t *m1, const symbol_t *m2)
+{
+ return strcmp (m1->tag, m2->tag) ? FALSE : TRUE;
+}
+
+static unsigned int
+hash_symbol_t (const symbol_t *m, unsigned int tablesize)
+{
+ return hash_string (m->tag, tablesize);
+}
+
+
+/*-------------------------------.
+| Create the symbol hash table. |
+`-------------------------------*/
+
+void
+symbols_new (void)
+{
+ symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
+ NULL,
+ (Hash_hasher) hash_symbol_t,
+ (Hash_comparator) hash_compare_symbol_t,
+ (Hash_data_freer) symbol_free);
+}
+
+
+/*----------------------------------------------------------------.
+| Find the symbol named KEY, and return it. If it does not exist |
+| yet, create it. |
+`----------------------------------------------------------------*/
+
+symbol_t *
+symbol_get (const char *key, location_t location)
+{
+ symbol_t probe;
+ symbol_t *entry;
+
+ /* Keep the symbol in a printable form. */
+ key = quotearg_style (escape_quoting_style, key);
+ *(char const **) &probe.tag = key;
+ entry = hash_lookup (symbol_table, &probe);
+
+ if (!entry)
+ {
+ /* First insertion in the hash. */
+ entry = symbol_new (key, location);
+ hash_insert (symbol_table, entry);