/* Symbol table manager for Bison.
- Copyright (C) 1984, 1989, 2000-2002, 2004-2013 Free Software
+ Copyright (C) 1984, 1989, 2000-2002, 2004-2015 Free Software
Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
return res;
}
+/* If needed, swap first and second so that first has the earliest
+ location (according to location_cmp).
+
+ Many symbol features (e.g., user token numbers) are not assigned
+ during the parsing, but in a second step, via a traversal of the
+ symbol table sorted on tag.
+
+ However, error messages make more sense if we keep the first
+ declaration first.
+*/
+
+static
+void symbols_sort (symbol **first, symbol **second)
+{
+ if (0 < location_cmp ((*first)->location, (*second)->location))
+ {
+ symbol* tmp = *first;
+ *first = *second;
+ *second = tmp;
+ }
+}
+
+/* Likewise, for locations. */
+
+static
+void locations_sort (location *first, location *second)
+{
+ if (0 < location_cmp (*first, *second))
+ {
+ location tmp = *first;
+ *first = *second;
+ *second = tmp;
+ }
+}
+
char const *
code_props_type_string (code_props_type kind)
{
case printer:
return "%printer";
}
- assert (0);
+ abort ();
}
/*----------------------------------------.
{
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
location second)
{
unsigned i = 0;
+ locations_sort (&first, &second);
complain_indent (&second, complaint, &i,
_("%s redeclaration for %s"), what, s->tag);
i += SUB_INDENT;
location second)
{
unsigned i = 0;
+ locations_sort (&first, &second);
complain_indent (&second, complaint, &i,
_("%s redeclaration for <%s>"), what, s->tag);
i += SUB_INDENT;
{
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->status == declared && !warned)
complain (&loc, Wother, _("symbol %s redeclared"), sym->tag);
- sym->status = declared;
+ else
+ sym->status = declared;
}
}
/* <*> and <> do not have to be "declared". */
if (sem_type->status == declared
|| !*sem_type->tag
- || STREQ(sem_type->tag, "*"))
+ || STREQ (sem_type->tag, "*"))
{
int i;
for (i = 0; i < 2; ++i)
user_token_number_redeclaration (int num, symbol *first, symbol *second)
{
unsigned i = 0;
- /* User token numbers are not assigned during the parsing, but in a
- second step, via a traversal of the symbol table sorted on tag.
-
- However, error messages make more sense if we keep the first
- declaration first. */
- if (location_cmp (first->location, second->location) > 0)
- {
- symbol* tmp = first;
- first = second;
- second = tmp;
- }
+ symbols_sort (&first, &second);
complain_indent (&second->location, complaint, &i,
_("user token number %d redeclaration for %s"),
num, second->tag);
(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;
}
+/*---------------------------------------.
+| 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. |
`---------------------------------------*/
init_assoc (void)
{
graphid i;
- used_assoc = xcalloc(nsyms, sizeof(*used_assoc));
+ used_assoc = xcalloc (nsyms, sizeof *used_assoc);
for (i = 0; i < nsyms; ++i)
used_assoc[i] = false;
}
&& !prec_nodes[i]->succ)
{
if (is_assoc_useless (s))
- complain (&s->location, Wprecedence,
+ complain (&s->prec_location, Wprecedence,
_("useless precedence and associativity for %s"), s->tag);
else if (s->assoc == precedence_assoc)
- complain (&s->location, Wprecedence,
+ complain (&s->prec_location, Wprecedence,
_("useless precedence for %s"), s->tag);
}
else if (is_assoc_useless (s))
- complain (&s->location, Wprecedence,
+ complain (&s->prec_location, Wprecedence,
_("useless associativity for %s, use %%precedence"), s->tag);
}
+ free (used_assoc);
+ assoc_free ();
}