bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

diagnostics: yacc reserves %type to nonterminals


From: Akim Demaille
Subject: diagnostics: yacc reserves %type to nonterminals
Date: Sun, 17 Nov 2019 09:48:42 +0100

commit 28d1ca8f48f7dff1550e6607f7aac33714a664b8
Author: Akim Demaille <address@hidden>
Date:   Sat Nov 16 17:26:51 2019 +0100

    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.

diff --git a/NEWS b/NEWS
index 8e6aed95..742ea743 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,30 @@ GNU Bison NEWS
 
 * 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]
 
diff --git a/src/parse-gram.c b/src/parse-gram.c
index 18419525..493ed525 100644
--- a/src/parse-gram.c
+++ b/src/parse-gram.c
@@ -510,11 +510,11 @@ static const yytype_int16 yyrline[] =
      453,   457,   467,   468,   469,   470,   474,   475,   480,   481,
      485,   486,   490,   491,   492,   505,   514,   518,   522,   530,
      531,   535,   548,   549,   561,   565,   569,   577,   579,   584,
-     591,   601,   605,   609,   617,   618,   626,   627,   633,   634,
-     635,   642,   642,   650,   651,   652,   657,   660,   662,   664,
-     666,   668,   670,   672,   674,   676,   681,   682,   691,   715,
-     716,   717,   718,   730,   732,   759,   764,   765,   770,   779,
-     780,   784,   785
+     591,   601,   605,   609,   617,   622,   634,   635,   641,   642,
+     643,   650,   650,   658,   659,   660,   665,   668,   670,   672,
+     674,   676,   678,   680,   682,   684,   689,   690,   699,   723,
+     724,   725,   726,   738,   740,   767,   772,   773,   778,   787,
+     788,   792,   793
 };
 #endif
 
@@ -2410,11 +2410,17 @@ yyreduce:
     break;
 
   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;
 
   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;
 
   case 90:
diff --git a/src/parse-gram.y b/src/parse-gram.y
index ccc3c315..0d1cc3f9 100644
--- a/src/parse-gram.y
+++ b/src/parse-gram.y
@@ -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_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                { $$ = symbol_list_sym_new ($1, @1); }
-| symbol_decl.1 symbol  { $$ = symbol_list_append ($1, symbol_list_sym_new 
($2, @2)); }
+  symbol
+    {
+      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));
+    }
 ;
 
         /*------------------------------------------.
diff --git a/src/reader.c b/src/reader.c
index cf481fd8..fc6a27e6 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -232,12 +232,8 @@ grammar_current_rule_begin (symbol *lhs, location loc,
     assign_named_ref (current_rule, named_ref_copy (lhs_name));
 
   /* Mark the rule's lhs as a nonterminal if not already so.  */
-  if (lhs->content->class == unknown_sym)
-    {
-      lhs->content->class = nterm_sym;
-      lhs->content->number = nvars;
-      ++nvars;
-    }
+  if (lhs->content->class == unknown_sym || lhs->content->class == 
pct_type_sym)
+    symbol_class_set (lhs, nterm_sym, empty_loc, false);
   else if (lhs->content->class == token_sym)
     complain (&loc, complaint, _("rule given for %s, which is a token"),
               lhs->tag);
diff --git a/src/symtab.c b/src/symtab.c
index 1b43ef96..73111b51 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -33,7 +33,6 @@
 #include "intprops.h"
 #include "quote.h"
 
-
 static struct hash_table *symbol_table = NULL;
 static struct hash_table *semantic_type_table = NULL;
 
@@ -233,7 +232,14 @@ symbol_print (symbol const *s, FILE *f)
 {
   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_CODE_PRINT (destructor);
       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.  |
 `------------------------------------*/
 
+static void
+complain_pct_type_on_token (location *loc)
+{
+  complain (loc, Wyacc,
+            _("POSIX yacc reserves %%type to nonterminals"));
+}
+
 void
 symbol_class_set (symbol *sym, symbol_class class, location loc, bool 
declaring)
 {
   aver (class != unknown_sym);
   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);
   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)
         s->number = nvars++;
       else if (class == token_sym && s->number == NUMBER_UNDEFINED)
@@ -579,7 +603,7 @@ static void
 symbol_check_defined (symbol *sym)
 {
   sym_content *s = sym->content;
-  if (s->class == unknown_sym)
+  if (s->class == unknown_sym || s->class == pct_type_sym)
     {
       complain_symbol_undeclared (sym);
       s->class = nterm_sym;
diff --git a/src/symtab.h b/src/symtab.h
index b6e18e61..729f1fb9 100644
--- a/src/symtab.h
+++ b/src/symtab.h
@@ -38,9 +38,15 @@
 /** Symbol classes.  */
 typedef enum
 {
-  unknown_sym,          /**< Undefined.  */
-  token_sym,            /**< Terminal. */
-  nterm_sym             /**< Nonterminal. */
+  /** Undefined.  */
+  unknown_sym,
+  /** 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;
 
 
@@ -219,7 +225,7 @@ void symbol_precedence_set (symbol *sym, int prec, assoc a, 
location loc);
 /** Set the \c class associated with \c sym.
 
     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,
                        bool declaring);
 
diff --git a/tests/input.at b/tests/input.at
index fe03f2e1..00e3a508 100644
--- a/tests/input.at
+++ b/tests/input.at
@@ -195,6 +195,55 @@ input.y:7.4-9: warning: POSIX Yacc does not support %empty 
[-Wyacc]
 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.  ##
 ## ----------------------------- ##




reply via email to

[Prev in Thread] Current Thread [Next in Thread]