/* Symbol table manager for Bison.
- Copyright (C) 1984, 1989, 2000-2002, 2004-2012 Free Software
+ Copyright (C) 1984, 1989, 2000-2002, 2004-2013 Free Software
Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
symbol *startsymbol = NULL;
location startsymbol_location;
+/*---------------------------.
+| Precedence relation graph. |
+`---------------------------*/
+
+static symgraph **prec_nodes;
+
+/*-----------------------------------.
+| Store which associativity is used. |
+`-----------------------------------*/
+
+bool *used_assoc = NULL;
/*---------------------------------.
| Create a new symbol, named TAG. |
symbol_new (uniqstr tag, location loc)
{
symbol *res = xmalloc (sizeof *res);
-
uniqstr_assert (tag);
/* If the tag is not a string (starts with a double quote), check
res->location = loc;
res->type_name = NULL;
- for (int i = 0; i < CODE_PROPS_SIZE; ++i)
- code_props_none_init (&res->props[i]);
+ {
+ int i;
+ for (i = 0; i < CODE_PROPS_SIZE; ++i)
+ code_props_none_init (&res->props[i]);
+ }
res->number = NUMBER_UNDEFINED;
res->prec = 0;
res->tag = tag;
res->location = loc ? *loc : empty_location;
res->status = undeclared;
- for (int i = 0; i < CODE_PROPS_SIZE; ++i)
- code_props_none_init (&res->props[i]);
+ {
+ int i;
+ for (i = 0; i < CODE_PROPS_SIZE; ++i)
+ code_props_none_init (&res->props[i]);
+ }
return res;
}
{
if (s)
{
- fprintf (f, "\"%s\"", s->tag);
+ fputs (s->tag, f);
SYMBOL_ATTR_PRINT (type_name);
SYMBOL_CODE_PRINT (destructor);
SYMBOL_CODE_PRINT (printer);
}
else
- fprintf (f, "<NULL>");
+ fputs ("<NULL>", f);
}
#undef SYMBOL_ATTR_PRINT
{
if (sym->type_name)
symbol_redeclaration (sym, "%type", sym->type_location, loc);
- uniqstr_assert (type_name);
- sym->type_name = type_name;
- sym->type_location = loc;
+ else
+ {
+ uniqstr_assert (type_name);
+ sym->type_name = type_name;
+ sym->type_location = loc;
+ }
}
}
symbol_redeclaration (sym, code_props_type_string (kind),
sym->props[kind].location,
code->location);
- sym->props[kind] = *code;
+ else
+ sym->props[kind] = *code;
}
/*-----------------------------------------------------.
semantic_type_redeclaration (type, code_props_type_string (kind),
type->props[kind].location,
code->location);
- type->props[kind] = *code;
+ else
+ type->props[kind] = *code;
}
/*---------------------------------------------------.
{
if (a != undef_assoc)
{
- if (sym->prec != 0)
+ if (sym->prec)
symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location,
loc);
- sym->prec = prec;
- sym->assoc = a;
- sym->prec_location = loc;
+ else
+ {
+ sym->prec = prec;
+ sym->assoc = a;
+ sym->prec_location = loc;
+ }
}
/* Only terminals have a precedence. */
if (sym->class != unknown_sym && sym->class != class)
{
complain (&loc, complaint, _("symbol %s redefined"), sym->tag);
- // Don't report both "redefined" and "redeclared".
+ /* Don't report both "redefined" and "redeclared". */
warned = true;
}
{
if (sym->status == declared && !warned)
complain (&loc, Wother, _("symbol %s redeclared"), sym->tag);
- sym->status = declared;
+ else
+ sym->status = declared;
}
}
sym->number = nvars++;
}
- for (int i = 0; i < 2; ++i)
- symbol_code_props_get (sym, i)->is_used = true;
+ {
+ int i;
+ for (i = 0; i < 2; ++i)
+ symbol_code_props_get (sym, i)->is_used = true;
+ }
/* Set the semantic type status associated to the current symbol to
'declared' so that we could check semantic types unnecessary uses. */
static inline bool
semantic_type_check_defined (semantic_type *sem_type)
{
- // <*> and <> do not have to be "declared".
+ /* <*> and <> do not have to be "declared". */
if (sem_type->status == declared
|| !*sem_type->tag
- || STREQ(sem_type->tag, "*"))
+ || STREQ (sem_type->tag, "*"))
{
- for (int i = 0; i < 2; ++i)
+ int i;
+ for (i = 0; i < 2; ++i)
if (sem_type->props[i].kind != CODE_PROPS_NONE
&& ! sem_type->props[i].is_used)
complain (&sem_type->location, Wother,
}
- for (int i = 0; i < CODE_PROPS_SIZE; ++i)
- if (str->props[i].code)
- symbol_code_props_set (sym, i, &str->props[i]);
- else if (sym->props[i].code)
- symbol_code_props_set (str, i, &sym->props[i]);
+ {
+ int i;
+ for (i = 0; i < CODE_PROPS_SIZE; ++i)
+ if (str->props[i].code)
+ symbol_code_props_set (sym, i, &str->props[i]);
+ else if (sym->props[i].code)
+ symbol_code_props_set (str, i, &sym->props[i]);
+ }
if (sym->prec || str->prec)
{
(this->user_token_number,
symbols[token_translations[this->user_token_number]],
this);
-
- token_translations[this->user_token_number] = this->number;
+ else
+ token_translations[this->user_token_number] = this->number;
}
return true;
_("the start symbol %s is a token"),
startsymbol->tag);
}
+
+/*---------------------------------.
+| Initialize relation graph nodes. |
+`---------------------------------*/
+
+static void
+init_prec_nodes (void)
+{
+ int i;
+ prec_nodes = xcalloc (nsyms, sizeof *prec_nodes);
+ for (i = 0; i < nsyms; ++i)
+ {
+ prec_nodes[i] = xmalloc (sizeof *prec_nodes[i]);
+ symgraph *s = prec_nodes[i];
+ s->id = i;
+ s->succ = 0;
+ s->pred = 0;
+ }
+}
+
+/*----------------.
+| Create a link. |
+`----------------*/
+
+static symgraphlink *
+symgraphlink_new (graphid id, symgraphlink *next)
+{
+ symgraphlink *l = xmalloc (sizeof *l);
+ l->id = id;
+ l->next = next;
+ return l;
+}
+
+
+/*------------------------------------------------------------------.
+| Register the second symbol of the precedence relation, and return |
+| whether this relation is new. Use only in register_precedence. |
+`------------------------------------------------------------------*/
+
+static bool
+register_precedence_second_symbol (symgraphlink **first, graphid sym)
+{
+ if (!*first || sym < (*first)->id)
+ *first = symgraphlink_new (sym, *first);
+ else
+ {
+ symgraphlink *slist = *first;
+
+ while (slist->next && slist->next->id <= sym)
+ slist = slist->next;
+
+ if (slist->id == sym)
+ /* Relation already present. */
+ return false;
+
+ slist->next = symgraphlink_new (sym, slist->next);
+ }
+ return true;
+}
+
+/*------------------------------------------------------------------.
+| Register a new relation between symbols as used. The first symbol |
+| has a greater precedence than the second one. |
+`------------------------------------------------------------------*/
+
+void
+register_precedence (graphid first, graphid snd)
+{
+ if (!prec_nodes)
+ init_prec_nodes ();
+ register_precedence_second_symbol (&(prec_nodes[first]->succ), snd);
+ register_precedence_second_symbol (&(prec_nodes[snd]->pred), first);
+}
+
+
+/*---------------------------------------.
+| Deep clear a linked / adjacency list). |
+`---------------------------------------*/
+
+static void
+linkedlist_free (symgraphlink *node)
+{
+ if (node)
+ {
+ while (node->next)
+ {
+ symgraphlink *tmp = node->next;
+ free (node);
+ node = tmp;
+ }
+ free (node);
+ }
+}
+
+/*----------------------------------------------.
+| Clear and destroy association tracking table. |
+`----------------------------------------------*/
+
+static void
+assoc_free (void)
+{
+ int i;
+ for (i = 0; i < nsyms; ++i)
+ {
+ linkedlist_free (prec_nodes[i]->pred);
+ linkedlist_free (prec_nodes[i]->succ);
+ free (prec_nodes[i]);
+ }
+ free (prec_nodes);
+}
+
+/*---------------------------------------.
+| Initialize association tracking table. |
+`---------------------------------------*/
+
+static void
+init_assoc (void)
+{
+ graphid i;
+ used_assoc = xcalloc (nsyms, sizeof *used_assoc);
+ for (i = 0; i < nsyms; ++i)
+ used_assoc[i] = false;
+}
+
+/*------------------------------------------------------------------.
+| Test if the associativity for the symbols is defined and useless. |
+`------------------------------------------------------------------*/
+
+static inline bool
+is_assoc_useless (symbol *s)
+{
+ return s
+ && s->assoc != undef_assoc
+ && s->assoc != precedence_assoc
+ && !used_assoc[s->number];
+}
+
+/*-------------------------------.
+| Register a used associativity. |
+`-------------------------------*/
+
+void
+register_assoc (graphid i, graphid j)
+{
+ if (!used_assoc)
+ init_assoc ();
+ used_assoc[i] = true;
+ used_assoc[j] = true;
+}
+
+/*--------------------------------------------------.
+| Print a warning for unused precedence relations. |
+`--------------------------------------------------*/
+
+void
+print_precedence_warnings (void)
+{
+ int i;
+ if (!prec_nodes)
+ init_prec_nodes ();
+ if (!used_assoc)
+ init_assoc ();
+ for (i = 0; i < nsyms; ++i)
+ {
+ symbol *s = symbols[i];
+ if (s
+ && s->prec != 0
+ && !prec_nodes[i]->pred
+ && !prec_nodes[i]->succ)
+ {
+ if (is_assoc_useless (s))
+ complain (&s->prec_location, Wprecedence,
+ _("useless precedence and associativity for %s"), s->tag);
+ else if (s->assoc == precedence_assoc)
+ complain (&s->prec_location, Wprecedence,
+ _("useless precedence for %s"), s->tag);
+ }
+ else if (is_assoc_useless (s))
+ complain (&s->prec_location, Wprecedence,
+ _("useless associativity for %s, use %%precedence"), s->tag);
+ }
+ free (used_assoc);
+ assoc_free ();
+}