X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/284bc49c832ffe6280907cb6c7788fa06bc58c7c..fd003416d59cae9645d164b12495eb186efee848:/src/symtab.c diff --git a/src/symtab.c b/src/symtab.c index 3028df9f..b132e07b 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -52,6 +52,12 @@ location startsymbol_location; static symgraph **prec_nodes; +/*-----------------------------------. +| Store which associativity is used. | +`-----------------------------------*/ + +bool *used_assoc = NULL; + /*---------------------------------. | Create a new symbol, named TAG. | `---------------------------------*/ @@ -147,13 +153,13 @@ symbol_print (symbol const *s, FILE *f) { 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, ""); + fputs ("", f); } #undef SYMBOL_ATTR_PRINT @@ -1051,6 +1057,81 @@ register_precedence (graphid first, graphid snd) } +/*---------------------------------------. +| 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. | `--------------------------------------------------*/ @@ -1061,15 +1142,27 @@ 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 - && s->assoc == precedence_assoc) - complain (&s->location, Wother, - _("useless precedence for %s"), s->tag); + && !prec_nodes[i]->succ) + { + if (is_assoc_useless (s)) + complain (&s->location, Wprecedence, + _("useless precedence and associativity for %s"), s->tag); + else if (s->assoc == precedence_assoc) + complain (&s->location, Wprecedence, + _("useless precedence for %s"), s->tag); + } + else if (is_assoc_useless (s)) + complain (&s->location, Wprecedence, + _("useless associativity for %s, use %%precedence"), s->tag); } + free (used_assoc); + assoc_free (); }