p = grammar_symbol_append (sym, loc);
if (name)
assign_named_ref(p, name);
+ if (sym->status == undeclared || sym->status == used)
+ sym->status = needed;
}
/* Attach an ACTION to the current rule. */
if (!bitset_test (V, i))
{
nontermmap[i - ntokens] = n++;
- warn_at (symbols[i]->location, _("nonterminal useless in grammar: %s"),
- symbols[i]->tag);
+ if (symbols[i]->status != used)
+ warn_at (symbols[i]->location,
+ _("nonterminal useless in grammar: %s"),
+ symbols[i]->tag);
}
{
case SYMLIST_SYMBOL:
symbol_destructor_set (node->content.sym, &destructor);
- if (node->content.sym->status == needed)
+ if (node->content.sym->status == undeclared)
node->content.sym->status = used;
break;
case SYMLIST_TYPE:
{
case SYMLIST_SYMBOL:
symbol_printer_set (node->content.sym, &printer);
- if (node->content.sym->status == needed)
+ if (node->content.sym->status == undeclared)
node->content.sym->status = used;
break;
case SYMLIST_TYPE:
res->alias = NULL;
res->class = unknown_sym;
- res->status = needed;
+ res->status = undeclared;
if (nsyms == SYMBOL_NUMBER_MAXIMUM)
fatal (_("too many symbols in input grammar (limit is %d)"),
void
symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
{
+ bool warned = false;
if (sym->class != unknown_sym && sym->class != class)
{
complain_at (loc, _("symbol %s redefined"), sym->tag);
- sym->status = needed;
+ // Don't report both "redefined" and "redeclared".
+ warned = true;
}
if (class == nterm_sym && sym->class != nterm_sym)
if (declaring)
{
- if (sym->status == declared)
+ if (sym->status == declared && !warned)
warn_at (loc, _("symbol %s redeclared"), sym->tag);
sym->status = declared;
}
{
if (sym->class == unknown_sym)
{
- if (sym->status == needed)
- complain_at
- (sym->location,
- _("symbol %s is used, but is not defined as a token and has no"
- " rules"),
- sym->tag);
- else
- warn_at
- (sym->location,
- _("symbol %s is used, but is not defined as a token and has no"
- " rules"),
- sym->tag);
+ switch (sym->status)
+ {
+ case used:
+ warn_at (sym->location,
+ _("symbol %s is used, but is not defined as a token"
+ " and has no rules"),
+ sym->tag);
+ break;
+ case undeclared:
+ case needed:
+ complain_at (sym->location,
+ _("symbol %s is used, but is not defined as a token"
+ " and has no rules"),
+ sym->tag);
+ break;
+ case declared:
+ /* If declared, then sym->class != unknown_sym. */
+ assert (0);
+ }
sym->class = nterm_sym;
sym->number = nvars++;
typedef struct symbol symbol;
+/* Declaration status of a symbol.
+
+ First, it is "undeclared". Then, if "undeclared" and used in a
+ %printer/%destructor, it is "used". If not "declared" by used in a
+ rule, it is "needed". Finally, if declared (via a rule for
+ nonterminals, or %oken), it is "declared".
+
+ When status are checked at the end, "declared" symbols are fine,
+ "used" symbols trigger warnings, otherwise it's an error.
+*/
+
typedef enum
{
- needed, /**< found but not "defined". */
- used, /**< used by %printer but not declared. */
- declared, /**< defined with %type or %token. */
+ /** Used in the input file for an unknown reason (error). */
+ undeclared,
+ /** Used by %destructor/%printer but not defined (warning). */
+ used,
+ /** Used in the gramar (rules) but not defined (error). */
+ needed,
+ /** Defined with %type or %token (good). */
+ declared,
} status;
/* When extending this structure, be sure to complete
AT_CLEANUP
-## ---------------------------------------------------- ##
-## Undeclared symbols used for a printer or destructor. ##
-## ---------------------------------------------------- ##
+## ----------------------------------------------------- ##
+## Undeclared symbols used for a printer or destructor. ##
+## ----------------------------------------------------- ##
AT_SETUP([Undeclared symbols used for a printer or destructor])
AT_DATA([[input.y]],
-[[%printer {} token1
-%destructor {} token2
+[[%printer {} foo baz
+%destructor {} bar
%%
-exp: "a";
+exp: bar;
]])
-AT_BISON_CHECK([input.y], [0], [],
-[[input.y:1.13-18: warning: symbol token1 is used, but is not defined as a token and has no rules
-input.y:2.16-21: warning: symbol token2 is used, but is not defined as a token and has no rules
-input.y: warning: 2 nonterminals useless in grammar
-input.y:1.13-18: warning: nonterminal useless in grammar: token1
-input.y:2.16-21: warning: nonterminal useless in grammar: token2
+AT_BISON_CHECK([input.y], [1], [],
+[[input.y:2.16-18: symbol bar is used, but is not defined as a token and has no rules
+input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules
+input.y:1.13-15: warning: symbol foo is used, but is not defined as a token and has no rules
]])
AT_CLEANUP