]> git.saurik.com Git - bison.git/commitdiff
diagnostics: factor and enhance messages about duplicate rule directives
authorAkim Demaille <akim@lrde.epita.fr>
Sun, 17 Feb 2013 11:47:35 +0000 (12:47 +0100)
committerAkim Demaille <akim@lrde.epita.fr>
Mon, 18 Feb 2013 09:01:29 +0000 (10:01 +0100)
When reporting a duplicate directive on a rule, point to its first
occurrence:

one.y:11.10-15: error: only one %empty allowed per rule
   %empty {} %empty
             ^^^^^^
one.y:11.3-8: previous declaration
   %empty {} %empty
   ^^^^^^

And consistently discard the second one.

* src/complain.h, src/complain.c (duplicate_directive): New.
* src/reader.c: Use it where appropriate.
* src/symlist.h, src/symlist.c (symbol_list): Add a dprec_location member.
* tests/actions.at: Adjust expected output.

src/complain.c
src/complain.h
src/reader.c
src/symlist.c
src/symlist.h
tests/actions.at

index 44e1b1ea94b96a0ec4a6d1e6d28f79303a452da7..2e87097fd225890dcb7aab0b623fd8f8a8170066 100644 (file)
@@ -365,3 +365,13 @@ deprecated_directive (location const *loc, char const *old, char const *upd)
               _("deprecated directive: %s, use %s"),
               quote (old), quote_n (1, upd));
 }
+
+void
+duplicate_directive (char const *directive,
+                     location first, location second)
+{
+  unsigned i = 0;
+  complain (&second, complaint, _("only one %s allowed per rule"), directive);
+  i += SUB_INDENT;
+  complain_indent (&first, complaint, &i, _("previous declaration"));
+}
index a43318482cb137523258755b900c6eb3dbb23efb..4239bf6db1f3732a345b9f0b6f5f39b43c2cb4fd 100644 (file)
@@ -123,6 +123,10 @@ void complain_indent (location const *loc, warnings flags, unsigned *indent,
 void deprecated_directive (location const *loc,
                            char const *obsolete, char const *updated);
 
+/** Report a repeated directive for a rule.  */
+void duplicate_directive (char const *directive,
+                          location first, location second);
+
 /** Warnings treated as errors shouldn't stop the execution as regular errors
     should (because due to their nature, it is safe to go on). Thus, there are
     three possible execution statuses.  */
index 5960e2431eb8640a06f46af3e918c2bfe98c0754..dbf4e95ea5799b800826b1c6d3121a09bae3261d 100644 (file)
@@ -442,8 +442,10 @@ grammar_current_rule_prec_set (symbol *precsym, location loc)
      token.  */
   symbol_class_set (precsym, token_sym, loc, false);
   if (current_rule->ruleprec)
-    complain (&loc, complaint, _("only one %s allowed per rule"), "%prec");
-  current_rule->ruleprec = precsym;
+    duplicate_directive ("%prec",
+                         current_rule->ruleprec->location, loc);
+  else
+    current_rule->ruleprec = precsym;
 }
 
 /* Set %empty for the current rule. */
@@ -456,7 +458,8 @@ grammar_current_rule_empty_set (location loc)
   if (warning_is_unset (Wempty_rule))
     warning_argmatch ("empty-rule", 0, 0);
   if (current_rule->percent_empty_loc.start.file)
-    complain (&loc, complaint, _("only one %s allowed per rule"), "%empty");
+    duplicate_directive ("%empty",
+                         current_rule->percent_empty_loc, loc);
   else
     current_rule->percent_empty_loc = loc;
 }
@@ -473,8 +476,13 @@ grammar_current_rule_dprec_set (int dprec, location loc)
     complain (&loc, complaint, _("%s must be followed by positive number"),
               "%dprec");
   else if (current_rule->dprec != 0)
-    complain (&loc, complaint, _("only one %s allowed per rule"), "%dprec");
-  current_rule->dprec = dprec;
+    duplicate_directive ("%dprec",
+                         current_rule->dprec_location, loc);
+  else
+    {
+      current_rule->dprec = dprec;
+      current_rule->dprec_location = loc;
+    }
 }
 
 /* Attach a merge function NAME with argument type TYPE to current
@@ -487,9 +495,13 @@ grammar_current_rule_merge_set (uniqstr name, location loc)
     complain (&loc, Wother, _("%s affects only GLR parsers"),
               "%merge");
   if (current_rule->merger != 0)
-    complain (&loc, complaint, _("only one %s allowed per rule"), "%merge");
-  current_rule->merger = get_merge_function (name);
-  current_rule->merger_declaration_location = loc;
+    duplicate_directive ("%merge",
+                         current_rule->merger_declaration_location, loc);
+  else
+    {
+      current_rule->merger = get_merge_function (name);
+      current_rule->merger_declaration_location = loc;
+    }
 }
 
 /* Attach SYM to the current rule.  If needed, move the previous
index 005d808b5a40a012791259566000065af0450adb..50915c18bdeebc99590795cd6a2bbe268e63c446 100644 (file)
@@ -47,7 +47,9 @@ symbol_list_sym_new (symbol *sym, location loc)
   res->percent_empty_loc = empty_location;
   code_props_none_init (&res->action_props);
   res->dprec = 0;
+  res->dprec_location = empty_location;
   res->merger = 0;
+  res->merger_declaration_location = empty_location;
 
   res->next = NULL;
 
index 9b0f11720d6ac270b7eafe67735fb1837db270d1..c369f69bb1067a6d6f32a594090093e9eaf1fd49 100644 (file)
@@ -83,6 +83,7 @@ typedef struct symbol_list
   location percent_empty_loc;
 
   int dprec;
+  location dprec_location;
   int merger;
   location merger_declaration_location;
 
index aeff37c3e8775f1e178c98c869d57c4dd0091625..3021c7a9a392f64da8e90dddf1fda6fa79e27843 100644 (file)
@@ -114,14 +114,17 @@ AT_SETUP([Invalid uses of %empty])
 AT_DATA_GRAMMAR([[one.y]],
 [[%%
 exp:
-  %empty %empty {}
+  %empty {} %empty
 ;
 ]])
 
 AT_BISON_CHECK([-fcaret one.y], [1], [],
-[[one.y:11.10-15: error: only one %empty allowed per rule
-   %empty %empty {}
-          ^^^^^^
+[[one.y:11.13-18: error: only one %empty allowed per rule
+   %empty {} %empty
+             ^^^^^^
+one.y:11.3-8: previous declaration
+   %empty {} %empty
+   ^^^^^^
 ]])
 
 AT_DATA_GRAMMAR([[two.y]],