bar.y: error: shift/reduce conflicts: 1 found, 0 expected
bar.y: error: reduce/reduce conflicts: 2 found, 0 expected
+*** Useless precedence
+
+ Bison now warns about symbols with a declared precedence but no declared
+ associativity (i.e. declared with %precedence), and whose precedence is
+ never used. In that case, the symbol can be safely declared with %token
+ instead, without modifying the parsing tables.
+
** Additional yylex/yyparse arguments
The new directive %param declares additional arguments to both yylex and
The precedence of shifting is that of token i. */
if (symbols[i]->prec < redprec)
{
+ register_precedence (redrule->prec->number, i);
log_resolution (redrule, i, reduce_resolution);
flush_shift (s, i);
}
else if (symbols[i]->prec > redprec)
{
+ register_precedence (i, redrule->prec->number);
log_resolution (redrule, i, shift_resolution);
flush_reduce (lookahead_tokens, i);
}
grammar_rules_useless_report (_("rule useless in parser due to conflicts"));
+ print_precedence_warnings ();
+
/* Output file names. */
compute_output_file_names ();
symbol *startsymbol = NULL;
location startsymbol_location;
+/*---------------------------.
+| Precedence relation graph. |
+`---------------------------*/
+
+static symgraph **prec_nodes;
/*---------------------------------.
| Create a new symbol, named TAG. |
_("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);
+}
+
+
+/*--------------------------------------------------.
+| Print a warning for unused precedence relations. |
+`--------------------------------------------------*/
+
+void
+print_precedence_warnings (void)
+{
+ int i;
+ if (!prec_nodes)
+ init_prec_nodes ();
+ 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);
+ }
+}
extern location startsymbol_location;
+
+/*-------------------.
+| Symbol Relations. |
+`-------------------*/
+
+/* The symbol relations are represented by a directed graph. */
+
+/* The id of a node */
+typedef int graphid;
+
+typedef struct symgraphlink symgraphlink;
+
+struct symgraphlink
+{
+ /** The second \c symbol or group of a precedence relation.
+ * See \c symgraph. */
+ graphid id;
+
+ symgraphlink *next;
+};
+
+/* Symbol precedence graph, to store the used precedence relations between
+ * symbols. */
+
+typedef struct symgraph symgraph;
+
+struct symgraph
+{
+ /** Identifier for the node: equal to the number of the symbol. */
+ graphid id;
+
+ /** The list of related symbols that have a smaller precedence. */
+ symgraphlink *succ;
+
+ /** The list of related symbols that have a greater precedence. */
+ symgraphlink *pred;
+};
+
+/** Register a new precedence relation as used. */
+
+void register_precedence (graphid first, graphid snd);
+
+/** Print a warning for each symbol whose precedence is useless. */
+
+void print_precedence_warnings (void);
+
/*-----------------.
| Semantic types. |
`-----------------*/
}
]])
-AT_FULL_COMPILE([input])
+AT_BISON_CHECK([-o input.c input.y], [], [],
+[[input.y:24.13: warning: useless precedence for R [-Wother]
+input.y:24.15: warning: useless precedence for S [-Wother]
+input.y:24.17: warning: useless precedence for T [-Wother]
+input.y:24.19: warning: useless precedence for U [-Wother]
+input.y:25.13: warning: useless precedence for V [-Wother]
+input.y:25.15: warning: useless precedence for W [-Wother]
+]])
+AT_COMPILE([input])
AT_PARSER_CHECK([./input])
AT_CLEANUP
+## ---------------------------- ##
+## Useless precedence warning. ##
+## ---------------------------- ##
+
+AT_SETUP([Useless precedence warning])
+
+AT_DATA([[input.y]],
+[[%token A B
+%precedence Z
+%left X
+%precedence Y
+%left W
+%right V
+%nonassoc U
+%%
+a: b
+ | a U b
+ | f
+;
+b: c
+ | b V c
+;
+c: d
+ | c W d
+;
+d: A
+ | d X d
+ | d Y A
+;
+f: B
+ | f Z B
+;
+]])
+
+AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [],
+[[input.y:2.13: warning: useless precedence for Z [-Wother]
+ %precedence Z
+ ^
+]])
+
+AT_CLEANUP
+
+
## ---------------- ##
## S/R in initial. ##
## ---------------- ##