📄 symtab.c
字号:
if (orig->printer || alias->printer) { if (orig->printer) symbol_printer_set (alias, orig->printer, orig->printer_location); else symbol_printer_set (orig, alias->printer, alias->printer_location); } if (alias->prec || orig->prec) { if (orig->prec) symbol_precedence_set (alias, orig->prec, orig->assoc, orig->prec_location); else symbol_precedence_set (orig, alias->prec, alias->assoc, alias->prec_location); }}static boolsymbol_check_alias_consistency_processor (void *this, void *null ATTRIBUTE_UNUSED){ symbol_check_alias_consistency (this); return true;}/*-------------------------------------------------------------------.| Assign a symbol number, and write the definition of the token name || into FDEFINES. Put in SYMBOLS. |`-------------------------------------------------------------------*/static inline boolsymbol_pack (symbol *this){ if (this->class == nterm_sym) { this->number += ntokens; } else if (this->alias) { /* This symbol and its alias are a single token defn. Allocate a tokno, and assign to both check agreement of prec and assoc fields and make both the same */ if (this->number == NUMBER_UNDEFINED) { if (this == endtoken || this->alias == endtoken) this->number = this->alias->number = 0; else { if (this->alias->number == NUMBER_UNDEFINED) abort (); this->number = this->alias->number; } } /* Do not do processing below for USER_NUMBER_ALIASes. */ if (this->user_token_number == USER_NUMBER_ALIAS) return true; } else /* this->class == token_sym */ { if (this->number == NUMBER_UNDEFINED) abort (); } symbols[this->number] = this; return true;}static boolsymbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED){ return symbol_pack (this);}/*--------------------------------------------------.| Put THIS in TOKEN_TRANSLATIONS if it is a token. |`--------------------------------------------------*/static inline boolsymbol_translation (symbol *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;}static boolsymbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED){ return symbol_translation (this);}/*----------------------.| A symbol hash table. |`----------------------*//* Initial capacity of symbols hash table. */#define HT_INITIAL_CAPACITY 257static struct hash_table *symbol_table = NULL;static inline boolhash_compare_symbol (const symbol *m1, const symbol *m2){ /* Since tags are unique, we can compare the pointers themselves. */ return UNIQSTR_EQ (m1->tag, m2->tag);}static boolhash_symbol_comparator (void const *m1, void const *m2){ return hash_compare_symbol (m1, m2);}static inline size_thash_symbol (const symbol *m, size_t tablesize){ /* Since tags are unique, we can hash the pointer itself. */ return ((uintptr_t) m->tag) % tablesize;}static size_thash_symbol_hasher (void const *m, size_t tablesize){ return hash_symbol (m, tablesize);}/*-------------------------------.| Create the symbol hash table. |`-------------------------------*/voidsymbols_new (void){ symbol_table = hash_initialize (HT_INITIAL_CAPACITY, NULL, hash_symbol_hasher, hash_symbol_comparator, free);}/*----------------------------------------------------------------.| Find the symbol named KEY, and return it. If it does not exist || yet, create it. |`----------------------------------------------------------------*/symbol *symbol_get (const char *key, location loc){ symbol probe; symbol *entry; key = uniqstr_new (key); probe.tag = key; entry = hash_lookup (symbol_table, &probe); if (!entry) { /* First insertion in the hash. */ entry = symbol_new (key, loc); hash_insert (symbol_table, entry); } return entry;}/*------------------------------------------------------------------.| Generate a dummy nonterminal, whose name cannot conflict with the || user's names. |`------------------------------------------------------------------*/symbol *dummy_symbol_get (location loc){ /* Incremented for each generated symbol. */ static int dummy_count = 0; static char buf[256]; symbol *sym; sprintf (buf, "@%d", ++dummy_count); sym = symbol_get (buf, loc); sym->class = nterm_sym; sym->number = nvars++; return sym;}/*-------------------.| Free the symbols. |`-------------------*/voidsymbols_free (void){ hash_free (symbol_table); free (symbols);}/*---------------------------------------------------------------.| Look for undefined symbols, report an error, and consider them || terminals. |`---------------------------------------------------------------*/static voidsymbols_do (Hash_processor processor, void *processor_data){ hash_do_for_each (symbol_table, processor, processor_data);}/*--------------------------------------------------------------.| Check that all the symbols are defined. Report any undefined || symbols and consider them nonterminals. |`--------------------------------------------------------------*/voidsymbols_check_defined (void){ symbols_do (symbol_check_defined_processor, NULL);}/*------------------------------------------------------------------.| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same || number. |`------------------------------------------------------------------*/static voidsymbols_token_translations_init (void){ bool num_256_available_p = true; int i; /* Find the highest user token number, and whether 256, the POSIX preferred user token number for the error token, is used. */ max_user_token_number = 0; for (i = 0; i < ntokens; ++i) { symbol *this = symbols[i]; if (this->user_token_number != USER_NUMBER_UNDEFINED) { if (this->user_token_number > max_user_token_number) max_user_token_number = this->user_token_number; if (this->user_token_number == 256) num_256_available_p = false; } } /* If 256 is not used, assign it to error, to follow POSIX. */ if (num_256_available_p && errtoken->user_token_number == USER_NUMBER_UNDEFINED) errtoken->user_token_number = 256; /* Set the missing user numbers. */ if (max_user_token_number < 256) max_user_token_number = 256; for (i = 0; i < ntokens; ++i) { symbol *this = symbols[i]; if (this->user_token_number == USER_NUMBER_UNDEFINED) this->user_token_number = ++max_user_token_number; if (this->user_token_number > max_user_token_number) max_user_token_number = this->user_token_number; } token_translations = xnmalloc (max_user_token_number + 1, sizeof *token_translations); /* Initialize all entries for literal tokens to 2, the internal token number for $undefined, which represents all invalid inputs. */ for (i = 0; i < max_user_token_number + 1; i++) token_translations[i] = undeftoken->number; symbols_do (symbol_translation_processor, NULL);}/*----------------------------------------------------------------.| Assign symbol numbers, and write definition of token names into || FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. |`----------------------------------------------------------------*/voidsymbols_pack (void){ symbols = xcalloc (nsyms, sizeof *symbols); symbols_do (symbol_check_alias_consistency_processor, NULL); symbols_do (symbol_pack_processor, NULL); symbols_token_translations_init (); if (startsymbol->class == unknown_sym) fatal_at (startsymbol_location, _("the start symbol %s is undefined"), startsymbol->tag); else if (startsymbol->class == token_sym) fatal_at (startsymbol_location, _("the start symbol %s is a token"), startsymbol->tag);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -