diagnostics: yacc reserves %type to nonterminals

On

    %token TOKEN1
    %type  <ival> TOKEN1 TOKEN2 't'
    %token TOKEN2
    %%
    expr:

bison -Wyacc gives

    input.y:2.15-20: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
        2 | %type  <ival> TOKEN1 TOKEN2 't'
          |               ^~~~~~
    input.y:2.29-31: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
        2 | %type  <ival> TOKEN1 TOKEN2 't'
          |                             ^~~
    input.y:2.22-27: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
        2 | %type  <ival> TOKEN1 TOKEN2 't'
          |                      ^~~~~~

The messages appear to be out of order, but they are emitted when the
error is found.

* src/symtab.h (symbol_class): Add pct_type_sym, used to denote
symbols appearing in %type.
* src/symtab.c (complain_pct_type_on_token): New.
(symbol_class_set): Check that %type is not applied to tokens.
(symbol_check_defined): pct_type_sym also means undefined.
* src/parse-gram.y (symbol_decl.1): Set the class to pct_type_sym.
* src/reader.c (grammar_current_rule_begin): pct_type_sym also means
undefined.
* tests/input.at (Yacc's %type): New.
This commit is contained in:
Akim Demaille
2019-11-16 17:26:51 +01:00
parent 1817b475a6
commit 28d1ca8f48
7 changed files with 141 additions and 28 deletions

24
NEWS
View File

@@ -2,6 +2,30 @@ GNU Bison NEWS
* Noteworthy changes in release ?.? (????-??-??) [?] * Noteworthy changes in release ?.? (????-??-??) [?]
** New Features
*** Better POSIX Yacc compatibility diagnostics
POSIX Yacc restricts %type to nonterminals. This is now diagnosed by
-Wyacc.
%token TOKEN1
%type <ival> TOKEN1 TOKEN2 't'
%token TOKEN2
%%
expr:
gives, with -Wyacc
input.y:2.15-20: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
2 | %type <ival> TOKEN1 TOKEN2 't'
| ^~~~~~
input.y:2.29-31: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
2 | %type <ival> TOKEN1 TOKEN2 't'
| ^~~
input.y:2.22-27: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
2 | %type <ival> TOKEN1 TOKEN2 't'
| ^~~~~~
* Noteworthy changes in release 3.4.90 (2019-10-29) [beta] * Noteworthy changes in release 3.4.90 (2019-10-29) [beta]

View File

@@ -510,11 +510,11 @@ static const yytype_int16 yyrline[] =
453, 457, 467, 468, 469, 470, 474, 475, 480, 481, 453, 457, 467, 468, 469, 470, 474, 475, 480, 481,
485, 486, 490, 491, 492, 505, 514, 518, 522, 530, 485, 486, 490, 491, 492, 505, 514, 518, 522, 530,
531, 535, 548, 549, 561, 565, 569, 577, 579, 584, 531, 535, 548, 549, 561, 565, 569, 577, 579, 584,
591, 601, 605, 609, 617, 618, 626, 627, 633, 634, 591, 601, 605, 609, 617, 622, 634, 635, 641, 642,
635, 642, 642, 650, 651, 652, 657, 660, 662, 664, 643, 650, 650, 658, 659, 660, 665, 668, 670, 672,
666, 668, 670, 672, 674, 676, 681, 682, 691, 715, 674, 676, 678, 680, 682, 684, 689, 690, 699, 723,
716, 717, 718, 730, 732, 759, 764, 765, 770, 779, 724, 725, 726, 738, 740, 767, 772, 773, 778, 787,
780, 784, 785 788, 792, 793
}; };
#endif #endif
@@ -2410,11 +2410,17 @@ yyreduce:
break; break;
case 84: case 84:
{ (yyval.yytype_86) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } {
symbol_class_set ((yyvsp[0].symbol), pct_type_sym, (yylsp[0]), false);
(yyval.yytype_86) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]));
}
break; break;
case 85: case 85:
{ (yyval.yytype_86) = symbol_list_append ((yyvsp[-1].yytype_86), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); } {
symbol_class_set ((yyvsp[0].symbol), pct_type_sym, (yylsp[0]), false);
(yyval.yytype_86) = symbol_list_append ((yyvsp[-1].yytype_86), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])));
}
break; break;
case 90: case 90:

View File

@@ -592,11 +592,11 @@ token_decl_for_prec:
; ;
/*-----------------------. /*-----------------------------------.
| symbol_decls (%type). | | symbol_decls (argument of %type). |
`-----------------------*/ `-----------------------------------*/
// A non empty list of typed symbols. // A non empty list of typed symbols (for %type).
symbol_decls: symbol_decls:
symbol_decl.1[syms] symbol_decl.1[syms]
{ {
@@ -612,10 +612,18 @@ symbol_decls:
} }
; ;
// One or more token declarations. // One or more token declarations (for %type).
symbol_decl.1: symbol_decl.1:
symbol { $$ = symbol_list_sym_new ($1, @1); } symbol
| symbol_decl.1 symbol { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } {
symbol_class_set ($symbol, pct_type_sym, @symbol, false);
$$ = symbol_list_sym_new ($symbol, @symbol);
}
| symbol_decl.1 symbol
{
symbol_class_set ($symbol, pct_type_sym, @symbol, false);
$$ = symbol_list_append ($1, symbol_list_sym_new ($symbol, @symbol));
}
; ;
/*------------------------------------------. /*------------------------------------------.

View File

@@ -232,12 +232,8 @@ grammar_current_rule_begin (symbol *lhs, location loc,
assign_named_ref (current_rule, named_ref_copy (lhs_name)); assign_named_ref (current_rule, named_ref_copy (lhs_name));
/* Mark the rule's lhs as a nonterminal if not already so. */ /* Mark the rule's lhs as a nonterminal if not already so. */
if (lhs->content->class == unknown_sym) if (lhs->content->class == unknown_sym || lhs->content->class == pct_type_sym)
{ symbol_class_set (lhs, nterm_sym, empty_loc, false);
lhs->content->class = nterm_sym;
lhs->content->number = nvars;
++nvars;
}
else if (lhs->content->class == token_sym) else if (lhs->content->class == token_sym)
complain (&loc, complaint, _("rule given for %s, which is a token"), complain (&loc, complaint, _("rule given for %s, which is a token"),
lhs->tag); lhs->tag);

View File

@@ -33,7 +33,6 @@
#include "intprops.h" #include "intprops.h"
#include "quote.h" #include "quote.h"
static struct hash_table *symbol_table = NULL; static struct hash_table *symbol_table = NULL;
static struct hash_table *semantic_type_table = NULL; static struct hash_table *semantic_type_table = NULL;
@@ -233,7 +232,14 @@ symbol_print (symbol const *s, FILE *f)
{ {
if (s) if (s)
{ {
fputs (s->tag, f); symbol_class c = s->content->class;
fprintf (f, "%s: %s",
c == unknown_sym ? "unknown"
: c == pct_type_sym ? "%type"
: c == token_sym ? "token"
: c == nterm_sym ? "nterm"
: NULL, /* abort. */
s->tag);
SYMBOL_ATTR_PRINT (type_name); SYMBOL_ATTR_PRINT (type_name);
SYMBOL_CODE_PRINT (destructor); SYMBOL_CODE_PRINT (destructor);
SYMBOL_CODE_PRINT (printer); SYMBOL_CODE_PRINT (printer);
@@ -502,15 +508,33 @@ symbol_precedence_set (symbol *sym, int prec, assoc a, location loc)
| Set the CLASS associated with SYM. | | Set the CLASS associated with SYM. |
`------------------------------------*/ `------------------------------------*/
static void
complain_pct_type_on_token (location *loc)
{
complain (loc, Wyacc,
_("POSIX yacc reserves %%type to nonterminals"));
}
void void
symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring) symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring)
{ {
aver (class != unknown_sym); aver (class != unknown_sym);
sym_content *s = sym->content; sym_content *s = sym->content;
if (s->class != unknown_sym && s->class != class) if (class == pct_type_sym)
{
if (s->class == token_sym)
complain_pct_type_on_token (&loc);
else if (s->class == unknown_sym)
s->class = class;
}
else if (s->class != unknown_sym && s->class != pct_type_sym
&& s->class != class)
complain_class_redeclared (sym, class, loc); complain_class_redeclared (sym, class, loc);
else else
{ {
if (class == token_sym && s->class == pct_type_sym)
complain_pct_type_on_token (&sym->location);
if (class == nterm_sym && s->class != nterm_sym) if (class == nterm_sym && s->class != nterm_sym)
s->number = nvars++; s->number = nvars++;
else if (class == token_sym && s->number == NUMBER_UNDEFINED) else if (class == token_sym && s->number == NUMBER_UNDEFINED)
@@ -579,7 +603,7 @@ static void
symbol_check_defined (symbol *sym) symbol_check_defined (symbol *sym)
{ {
sym_content *s = sym->content; sym_content *s = sym->content;
if (s->class == unknown_sym) if (s->class == unknown_sym || s->class == pct_type_sym)
{ {
complain_symbol_undeclared (sym); complain_symbol_undeclared (sym);
s->class = nterm_sym; s->class = nterm_sym;

View File

@@ -38,9 +38,15 @@
/** Symbol classes. */ /** Symbol classes. */
typedef enum typedef enum
{ {
unknown_sym, /**< Undefined. */ /** Undefined. */
token_sym, /**< Terminal. */ unknown_sym,
nterm_sym /**< Nonterminal. */ /** Declared with %type: same as Undefined, but triggered a Wyacc if
applied to a terminal. */
pct_type_sym,
/** Terminal. */
token_sym,
/** Nonterminal. */
nterm_sym
} symbol_class; } symbol_class;
@@ -219,7 +225,7 @@ void symbol_precedence_set (symbol *sym, int prec, assoc a, location loc);
/** Set the \c class associated with \c sym. /** Set the \c class associated with \c sym.
Whether \c declaring means whether this class definition comes Whether \c declaring means whether this class definition comes
from %nterm or %token. */ from %nterm or %token (but not %type, prec/assoc, etc.). */
void symbol_class_set (symbol *sym, symbol_class class, location loc, void symbol_class_set (symbol *sym, symbol_class class, location loc,
bool declaring); bool declaring);

View File

@@ -195,6 +195,55 @@ input.y:7.4-9: warning: POSIX Yacc does not support %empty [-Wyacc]
AT_CLEANUP AT_CLEANUP
## -------------- ##
## Yacc's %type. ##
## -------------- ##
AT_SETUP([Yacc's %type])
AT_DATA([input.y],
[[%token TOKEN1
%nterm nterm1
%type <ival> TOKEN1 TOKEN2 "TOKEN3" nterm1 nterm2 nterm3 '+'
%token TOKEN2
%nterm nterm2
%%
expr: nterm1 nterm2 nterm3
nterm1: TOKEN1
nterm2: TOKEN2
nterm3: "TOKEN3"
]])
AT_BISON_CHECK([-fcaret -Wyacc input.y], [0], [],
[[input.y:2.1-6: warning: POSIX Yacc does not support %nterm [-Wyacc]
2 | %nterm nterm1
| ^~~~~~
input.y:3.14-19: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
3 | %type <ival> TOKEN1 TOKEN2 "TOKEN3" nterm1 nterm2 nterm3 '+'
| ^~~~~~
input.y:3.28-35: warning: POSIX Yacc does not support string literals [-Wyacc]
3 | %type <ival> TOKEN1 TOKEN2 "TOKEN3" nterm1 nterm2 nterm3 '+'
| ^~~~~~~~
input.y:3.28-35: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
3 | %type <ival> TOKEN1 TOKEN2 "TOKEN3" nterm1 nterm2 nterm3 '+'
| ^~~~~~~~
input.y:3.58-60: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
3 | %type <ival> TOKEN1 TOKEN2 "TOKEN3" nterm1 nterm2 nterm3 '+'
| ^~~
input.y:5.1-6: warning: POSIX Yacc does not support %nterm [-Wyacc]
5 | %nterm nterm2
| ^~~~~~
input.y:3.21-26: warning: POSIX yacc reserves %type to nonterminals [-Wyacc]
3 | %type <ival> TOKEN1 TOKEN2 "TOKEN3" nterm1 nterm2 nterm3 '+'
| ^~~~~~
input.y:10.9-16: warning: POSIX Yacc does not support string literals [-Wyacc]
10 | nterm3: "TOKEN3"
| ^~~~~~~~
]])
AT_CLEANUP
## ----------------------------- ## ## ----------------------------- ##
## Invalid symbol declarations. ## ## Invalid symbol declarations. ##
## ----------------------------- ## ## ----------------------------- ##