📄 symtab.c
字号:
/* Symbol table manager for Bison. Copyright (C) 1984, 1989, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. Bison is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Bison is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bison; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "system.h"#include <hash.h>#include <quotearg.h>#include "complain.h"#include "gram.h"#include "symtab.h"/*------------------------.| Distinguished symbols. |`------------------------*/symbol *errtoken = NULL;symbol *undeftoken = NULL;symbol *endtoken = NULL;symbol *accept = NULL;symbol *startsymbol = NULL;location startsymbol_location;/*---------------------------------.| Create a new symbol, named TAG. |`---------------------------------*/static symbol *symbol_new (uniqstr tag, location loc){ symbol *res = xmalloc (sizeof *res); uniqstr_assert (tag); res->tag = tag; res->location = loc; res->type_name = NULL; res->destructor = NULL; res->printer = NULL; res->number = NUMBER_UNDEFINED; res->prec = 0; res->assoc = undef_assoc; res->user_token_number = USER_NUMBER_UNDEFINED; res->alias = NULL; res->class = unknown_sym; if (nsyms == SYMBOL_NUMBER_MAXIMUM) fatal (_("too many symbols in input grammar (limit is %d)"), SYMBOL_NUMBER_MAXIMUM); nsyms++; return res;}/*------------------------------------------------------------------.| Complain that S's WHAT is redeclared at SECOND, and was first set || at FIRST. |`------------------------------------------------------------------*/static voidredeclaration (symbol* s, const char *what, location first, location second){ complain_at (second, _("%s redeclaration for %s"), what, s->tag); complain_at (first, _("first declaration"));}/*-----------------------------------------------------------------.| Set the TYPE_NAME associated with SYM. Does nothing if passed 0 || as TYPE_NAME. |`-----------------------------------------------------------------*/voidsymbol_type_set (symbol *sym, uniqstr type_name, location loc){ if (type_name) { if (sym->type_name) redeclaration (sym, "%type", sym->type_location, loc); uniqstr_assert (type_name); sym->type_name = type_name; sym->type_location = loc; }}/*------------------------------------------------------------------.| Set the DESTRUCTOR associated with SYM. Do nothing if passed 0. |`------------------------------------------------------------------*/voidsymbol_destructor_set (symbol *sym, char *destructor, location loc){ if (destructor) { if (sym->destructor) redeclaration (sym, "%destructor", sym->destructor_location, loc); sym->destructor = destructor; sym->destructor_location = loc; }}/*---------------------------------------------------------------.| Set the PRINTER associated with SYM. Do nothing if passed 0. |`---------------------------------------------------------------*/voidsymbol_printer_set (symbol *sym, char *printer, location loc){ if (printer) { if (sym->printer) redeclaration (sym, "%printer", sym->destructor_location, loc); sym->printer = printer; sym->printer_location = loc; }}/*-----------------------------------------------------------------.| Set the PRECEDENCE associated with SYM. Does nothing if invoked || with UNDEF_ASSOC as ASSOC. |`-----------------------------------------------------------------*/voidsymbol_precedence_set (symbol *sym, int prec, assoc a, location loc){ if (a != undef_assoc) { if (sym->prec != 0) redeclaration (sym, assoc_to_string (a), sym->prec_location, loc); sym->prec = prec; sym->assoc = a; sym->prec_location = loc; } /* Only terminals have a precedence. */ symbol_class_set (sym, token_sym, loc);}/*------------------------------------.| Set the CLASS associated with SYM. |`------------------------------------*/voidsymbol_class_set (symbol *sym, symbol_class class, location loc){ if (sym->class != unknown_sym && sym->class != class) complain_at (loc, _("symbol %s redefined"), sym->tag); if (class == nterm_sym && sym->class != nterm_sym) sym->number = nvars++; else if (class == token_sym && sym->number == NUMBER_UNDEFINED) sym->number = ntokens++; sym->class = class;}/*------------------------------------------------.| Set the USER_TOKEN_NUMBER associated with SYM. |`------------------------------------------------*/voidsymbol_user_token_number_set (symbol *sym, int user_token_number, location loc){ if (sym->class != token_sym) abort (); if (sym->user_token_number != USER_NUMBER_UNDEFINED && sym->user_token_number != user_token_number) complain_at (loc, _("redefining user token number of %s"), sym->tag); sym->user_token_number = user_token_number; /* User defined $end token? */ if (user_token_number == 0) { endtoken = sym; endtoken->number = 0; /* It is always mapped to 0, so it was already counted in NTOKENS. */ --ntokens; }}/*----------------------------------------------------------.| If SYM is not defined, report an error, and consider it a || nonterminal. |`----------------------------------------------------------*/static inline boolsymbol_check_defined (symbol *sym){ if (sym->class == unknown_sym) { complain_at (sym->location, _("symbol %s is used, but is not defined as a token and has no rules"), sym->tag); sym->class = nterm_sym; sym->number = nvars++; } return true;}static boolsymbol_check_defined_processor (void *sym, void *null ATTRIBUTE_UNUSED){ return symbol_check_defined (sym);}/*------------------------------------------------------------------.| Declare the new symbol SYM. Make it an alias of SYMVAL, and type || SYMVAL with SYM's type. |`------------------------------------------------------------------*/voidsymbol_make_alias (symbol *sym, symbol *symval, location loc){ if (symval->alias) warn_at (loc, _("symbol `%s' used more than once as a literal string"), symval->tag); else if (sym->alias) warn_at (loc, _("symbol `%s' given more than one literal string"), sym->tag); else { symval->class = token_sym; symval->user_token_number = sym->user_token_number; sym->user_token_number = USER_NUMBER_ALIAS; symval->alias = sym; sym->alias = symval; /* sym and symval combined are only one symbol. */ nsyms--; ntokens--; if (ntokens != sym->number && ntokens != symval->number) abort (); sym->number = symval->number = (symval->number < sym->number) ? symval->number : sym->number; }}/*---------------------------------------------------------.| Check that THIS, and its alias, have same precedence and || associativity. |`---------------------------------------------------------*/static inline voidsymbol_check_alias_consistency (symbol *this){ symbol *alias = this; symbol *orig = this->alias; /* Check only those that _are_ the aliases. */ if (!(this->alias && this->user_token_number == USER_NUMBER_ALIAS)) return; if (orig->type_name || alias->type_name) { if (orig->type_name) symbol_type_set (alias, orig->type_name, orig->type_location); else symbol_type_set (orig, alias->type_name, alias->type_location); } if (orig->destructor || alias->destructor) { if (orig->destructor) symbol_destructor_set (alias, orig->destructor, orig->destructor_location); else symbol_destructor_set (orig, alias->destructor, alias->destructor_location); } 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -