]> git.saurik.com Git - bison.git/commitdiff
Check for unrecognized %define variables similar to checking for
authorJoel E. Denny <jdenny@ces.clemson.edu>
Sun, 7 Jan 2007 07:50:27 +0000 (07:50 +0000)
committerJoel E. Denny <jdenny@ces.clemson.edu>
Sun, 7 Jan 2007 07:50:27 +0000 (07:50 +0000)
unrecognized %code qualifiers.  Check for redefined %define variables.
* data/bison.m4 (b4_check_for_unrecognized_names): New macro that
generalizes...
(b4_check_percent_code_qualifiers): ... this, which now wraps it.
(b4_check_percent_define_variables): New, also wraps it.
* data/glr.c: Unless glr.cc is wrapping glr.c, declare no valid %define
variables using b4_check_percent_define_variables.
* data/glr.cc, data/lalr1.cc: Declare the valid %define variables as
all those exercised in the test suite and all those listed in the
`Default values' section of c++.m4.  Are there others?
* data/push.c, data/yacc.c: Declare no valid %define variables.
* src/muscle_tab.c, src/muscle_tab.h (muscle_find_const): New function,
similar to muscle_find, but it works even when the muscle stores a
const value.
(muscle_grow_used_name_list): New function for constructing the used
name list muscles that b4_check_for_unrecognized_names requires.
* src/parse-gram.y (prologue_declaration): Warn if a variable is
%define'd more than once.  Define the b4_used_percent_define_variables
muscle with muscle_grow_used_name_list.
(grammar_declaration): Abbreviate %code code with
muscle_grow_used_name_list.
* tests/input.at (%define errors): New.

13 files changed:
ChangeLog
data/bison.m4
data/glr.c
data/glr.cc
data/lalr1.cc
data/push.c
data/yacc.c
src/muscle_tab.c
src/muscle_tab.h
src/parse-gram.c
src/parse-gram.h
src/parse-gram.y
tests/input.at

index e400137b3e16ed43ae3095e6a10cc125c15b6544..384ed98766b6c313a714b305a2ece2a4a7bf9aa3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2007-01-07  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Check for unrecognized %define variables similar to checking for
+       unrecognized %code qualifiers.  Check for redefined %define variables.
+       * data/bison.m4 (b4_check_for_unrecognized_names): New macro that
+       generalizes...
+       (b4_check_percent_code_qualifiers): ... this, which now wraps it.
+       (b4_check_percent_define_variables): New, also wraps it.
+       * data/glr.c: Unless glr.cc is wrapping glr.c, declare no valid %define
+       variables using b4_check_percent_define_variables.
+       * data/glr.cc, data/lalr1.cc: Declare the valid %define variables as
+       all those exercised in the test suite and all those listed in the
+       `Default values' section of c++.m4.  Are there others?
+       * data/push.c, data/yacc.c: Declare no valid %define variables.
+       * src/muscle_tab.c, src/muscle_tab.h (muscle_find_const): New function,
+       similar to muscle_find, but it works even when the muscle stores a
+       const value.
+       (muscle_grow_used_name_list): New function for constructing the used
+       name list muscles that b4_check_for_unrecognized_names requires.
+       * src/parse-gram.y (prologue_declaration): Warn if a variable is
+       %define'd more than once.  Define the b4_used_percent_define_variables
+       muscle with muscle_grow_used_name_list.
+       (grammar_declaration): Abbreviate %code code with
+       muscle_grow_used_name_list.
+       * tests/input.at (%define errors): New.
+
 2007-01-06  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Provide warn_at, complain_at, and fatal_at function callbacks to the
index 79cfd7b7ad038e271ee524a83ad050a8a6852f47..7f0005f128ebeed8aba8ccad06caa99c36eb8759 100644 (file)
@@ -66,7 +66,7 @@ version 2.2 of Bison.])])
 ## ---------------- ##
 
 # b4_error(KIND, FORMAT, [ARG1], [ARG2], ...)
-# -----------------------------------------------------
+# -------------------------------------------
 # Write @KIND(FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
 m4_define([b4_error],
 [m4_divert_push(0)[@]$1[(]$2[]m4_if([$#], [2], [],
@@ -75,7 +75,7 @@ m4_define([b4_error],
             [[@,]b4_arg])])[@)]m4_divert_pop(0)])
 
 # b4_error_at(KIND, START, END, FORMAT, [ARG1], [ARG2], ...)
-# -----------------------------------------------------------------
+# ----------------------------------------------------------
 # Write @KIND(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
 m4_define([b4_error_at],
 [m4_divert_push(0)[@]$1[_at(]$2[@,]$3[@,]$4[]m4_if([$#], [4], [],
@@ -84,7 +84,7 @@ m4_define([b4_error_at],
             [[@,]b4_arg])])[@)]m4_divert_pop(0)])
 
 # b4_warn(FORMAT, [ARG1], [ARG2], ...)
-# -----------------------------------------------------
+# ------------------------------------
 # Write @warn(FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
 #
 # As a simple test suite, this:
@@ -116,13 +116,13 @@ m4_define([b4_warn],
 [b4_error([[warn]], $@)])
 
 # b4_warn_at(START, END, FORMAT, [ARG1], [ARG2], ...)
-# -----------------------------------------------------------------
+# ---------------------------------------------------
 # Write @warn(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
 m4_define([b4_warn_at],
 [b4_error_at([[warn]], $@)])
 
 # b4_complain(FORMAT, [ARG1], [ARG2], ...)
-# ---------------------------------------------------------
+# ----------------------------------------
 # Write @complain(FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
 #
 # See the test suite for b4_warn above.
@@ -130,13 +130,13 @@ m4_define([b4_complain],
 [b4_error([[complain]], $@)])
 
 # b4_complain_at(START, END, FORMAT, [ARG1], [ARG2], ...)
-# ---------------------------------------------------------------------
+# -------------------------------------------------------
 # Write @complain(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
 m4_define([b4_complain_at],
 [b4_error_at([[complain]], $@)])
 
 # b4_fatal(FORMAT, [ARG1], [ARG2], ...)
-# ------------------------------------------------------
+# -------------------------------------
 # Write @fatal(FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
 #
 # See the test suite for b4_warn above.
@@ -144,7 +144,7 @@ m4_define([b4_fatal],
 [b4_error([[fatal]], $@)])
 
 # b4_fatal_at(START, END, FORMAT, [ARG1], [ARG2], ...)
-# ------------------------------------------------------------------
+# ----------------------------------------------------
 # Write @fatal(START@,END@,FORMAT@,ARG1@,ARG2@,...@) to diversion 0.
 m4_define([b4_fatal_at],
 [b4_error_at([[fatal]], $@)])
@@ -283,57 +283,81 @@ b4_define_user_code([pre_prologue])
 b4_define_user_code([stype])
 
 
-# b4_check_percent_code_qualifiers([VAILD_QUALIFIER], [VALID_QUALIFIER], ...)
-# ---------------------------------------------------------------------------
-# Complain if any %code qualifier used in the grammar is not a valid qualifier.
+# b4_check_for_unrecognized_names(WHAT, LIST, [VALID_NAME], [VALID_NAME])
+# -----------------------------------------------------------------------
+# Complain if any name of type WHAT is used in the grammar (as recorded in
+# LIST) but is not a VALID_NAME.
+#
+# LIST must expand to a list specifying all grammar occurrences of all names of
+# type WHAT.   Each item in the list is a triplet specifying one occurrence:
+# name, start boundary, and end boundary.  Empty string names are fine.  An
+# empty list is fine.
+#
+# For example, to define b4_foo_list to be used for LIST with three name
+# occurrences and with correct quoting:
 #
-# If no %code qualifiers are used in the grammar,
-# b4_used_percent_code_qualifiers must be undefined or must expand to the empty
-# string.  Otherwise, it must expand to a list specifying all occurrences of
-# all %code qualifiers used in the grammar.   Each item in the list is a
-# triplet specifying one occurrence: qualifier, start boundary, and end
-# boundary.  For example, to define b4_used_percent_code_qualifiers with three
-# qualifier occurrences with correct quoting:
+#   m4_define([b4_foo_list],
+#             [[[[[[bar]], [[parser.y:1.7]], [[parser.y:1.16]]]],
+#               [[[[bar]], [[parser.y:5.7]], [[parser.y:5.16]]]],
+#               [[[[baz]], [[parser.y:8.7]], [[parser.y:8.16]]]]]])
 #
-#   m4_define([b4_used_percent_code_qualifiers],
-#             [[[[[[requires]], [[parser.y:1.7]], [[parser.y:1.16]]]],
-#               [[[[provides]], [[parser.y:5.7]], [[parser.y:5.16]]]],
-#               [[[[provides]], [[parser.y:8.7]], [[parser.y:8.16]]]]]])
+# Each VALID_NAME must expand to a valid name of type WHAT.  Multiple
+# occurrences of the same valid name are fine.  A VALID_NAME that expands to
+# the empty string will correctly define the empty string as a valid name, but
+# it would be ugly for a Bison skeleton to actually use that.
 #
-# Empty string qualifiers are fine.
+# For example, to invoke b4_check_for_unrecognized_names with TYPE foo, with
+# LIST b4_foo_list, with two valid names, and with correct quoting:
 #
-# Each VALID_QUALIFIER must expand to a valid qualifier.  For example,
-# b4_check_percent_code_qualifiers might be invoked with:
+#   b4_check_for_unrecognized_names([[foo]], [b4_foo_list],
+#                                   [[bar]], [[baz]])
 #
-#   b4_check_percent_code_qualifiers([[requires]], [[provides]])
+# Names and valid names must not contain the character `,'.
+m4_define([b4_check_for_unrecognized_names],
+[m4_foreach([b4_occurrence],
+            $2,
+            [m4_pushdef([b4_occurrence], b4_occurrence)
+             m4_pushdef([b4_name], m4_car(b4_occurrence))
+             m4_pushdef([b4_start], m4_car(m4_shift(b4_occurrence)))
+             m4_pushdef([b4_end], m4_shift(m4_shift(b4_occurrence)))
+             m4_if(m4_index(m4_if($#, 2, [],
+                                  [[,]m4_quote(m4_shift(m4_shift($*)))[,]]),
+                            [,]b4_name[,]),
+                   [-1],
+                   [b4_complain_at([b4_start], [b4_end],
+                                   [[`%s' is not a recognized %s]],
+                                   [b4_name], [$1])
+                   ])
+             m4_popdef([b4_occurrence])
+             m4_popdef([b4_name])
+             m4_popdef([b4_start])
+             m4_popdef([b4_end])
+            ])
+])
+
+# b4_check_percent_define_variables([VAILD_VARIABLE], [VALID_VARIABLE], ...)
+# --------------------------------------------------------------------------
+# Wrapper around b4_check_for_unrecognized_names for %define variables.
 #
-# Multiple occurrences of the same valid qualifier are fine.  A VALID_QUALIFIER
-# that expands to the empty string will correctly define the empty string as a
-# valid qualifier, but it would be ugly for a Bison skeleton to actually use
-# that.  If b4_used_percent_code_qualifiers is invoked with empty parens, then
-# there is one valid qualifier and it is the empty string.  To specify that
-# there are no valid qualifiers, invoke b4_check_percent_code_qualifiers
-# without parens.
+# b4_used_percent_define_variables must contain a list of all %define variables
+# used in the grammar similar to b4_foo_list from the
+# b4_check_for_unrecognized_names documentation's example.  If
+# b4_used_percent_define_variables is undefined, it's treated the same as an
+# empty list.
 #
-# Qualifiers and valid qualifiers must not contain the character `,'.
+# Invoking b4_check_percent_define_variables with empty parens specifies one
+# valid variable that is an empty string.  Invoke it without parens to specify
+# that there are no valid variables.
+m4_define([b4_check_percent_define_variables],
+[m4_ifdef([b4_used_percent_define_variables],
+[b4_check_for_unrecognized_names([[%define variable]],
+[b4_used_percent_define_variables]m4_if([$#], [0], [], [, $@]))])])
+
+# b4_check_percent_code_qualifiers([VAILD_QUALIFIER], [VALID_QUALIFIER], ...)
+# ---------------------------------------------------------------------------
+# Same as b4_check_percent_define_variables but for %code qualifiers using
+# b4_used_percent_code_qualifiers.
 m4_define([b4_check_percent_code_qualifiers],
-[m4_ifdef([b4_used_percent_code_qualifiers], [
-m4_foreach([b4_occurrence],
-           b4_used_percent_code_qualifiers,
-           [m4_pushdef([b4_occurrence], b4_occurrence)
-            m4_pushdef([b4_qualifier], m4_car(b4_occurrence))
-            m4_pushdef([b4_start], m4_car(m4_shift(b4_occurrence)))
-            m4_pushdef([b4_end], m4_shift(m4_shift(b4_occurrence)))
-            m4_if(m4_index(m4_if($#, 0, [], [[,]m4_quote($*)[,]]),
-                           [,]b4_qualifier[,]),
-                  [-1],
-                  [b4_complain_at([b4_start], [b4_end],
-                                  [[`%s' is not a recognized %%code qualifier]],
-                                  [b4_qualifier])
-                  ])
-            m4_popdef([b4_occurrence])
-            m4_popdef([b4_qualifier])
-            m4_popdef([b4_start])
-            m4_popdef([b4_end])
-           ])
-])])
+[m4_ifdef([b4_used_percent_code_qualifiers],
+[b4_check_for_unrecognized_names([[%code qualifier]],
+[b4_used_percent_code_qualifiers]m4_if([$#], [0], [], [, $@]))])])
index 7ed26df4170261c88f0178f727117707df5aea15..5c85bcb44c8097df11d567e157379fc78c2af0a1 100644 (file)
 
 
 m4_include(b4_pkgdatadir/[c.m4])
-b4_check_percent_code_qualifiers([[requires]], [[provides]], [[top]])
+
+# glr.cc checks %define variables also.
+m4_if(b4_skeleton, [["glr.c"]], [b4_check_percent_define_variables])
+
+b4_check_percent_code_qualifiers([[requires]],
+                                 [[provides]],
+                                 [[top]])
 
 b4_push_if([
 b4_complain([[non-deterministic push parsers are not yet supported]])])
index 80702a20efcc0bf9f582fc6d8fcbadae53805394..2f164c74101e3caf5d3682cc515f09aede110c25 100644 (file)
@@ -57,6 +57,12 @@ b4_defines_if([],
 m4_include(b4_pkgdatadir/[c++.m4])
 m4_include(b4_pkgdatadir/[location.cc])
 
+b4_check_percent_define_variables([[global_tokens_and_yystype]],
+                                  [[parser_class_name]],
+                                  [[location_type]],
+                                  [[filename_type]],
+                                  [[b4_namespace]],
+                                  [[b4_define_location_comparison]])
 
 # Save the parse parameters.
 m4_define([b4_parse_param_orig], m4_defn([b4_parse_param]))
index 271cdb3e94ff4e8ab816b8075f89e7c920b8e1b4..1a61c50d0510a76ba0f80d4ead19b68debba5403 100644 (file)
 # 02110-1301  USA
 
 m4_include(b4_pkgdatadir/[c++.m4])
-b4_check_percent_code_qualifiers([[requires]], [[provides]], [[top]])
+
+b4_check_percent_define_variables([[global_tokens_and_yystype]],
+                                  [[parser_class_name]],
+                                  [[location_type]],
+                                  [[filename_type]],
+                                  [[b4_namespace]],
+                                  [[b4_define_location_comparison]])
+
+b4_check_percent_code_qualifiers([[requires]],
+                                 [[provides]],
+                                 [[top]])
 
 # The header is mandatory.
 b4_defines_if([],
index 250105092ba0d35d0e67ba5cfd9c8f5d87263ece..dbbdb1137e7c7f8f1f5618b8ac18ff586b4e74a6 100644 (file)
@@ -33,7 +33,12 @@ b4_use_push_for_pull_if([
   ])])
 
 m4_include(b4_pkgdatadir/[c.m4])
-b4_check_percent_code_qualifiers([[requires]], [[provides]], [[top]])
+
+b4_check_percent_define_variables
+
+b4_check_percent_code_qualifiers([[requires]],
+                                 [[provides]],
+                                 [[top]])
 
 ## ---------------- ##
 ## Default values.  ##
index a8bb367b1cc66c7ed9d5ee511926c8896915c953..8cd7dbf4bb4ab3eed88edb447fd7ef965058946e 100644 (file)
 b4_use_push_for_pull_if([m4_include(b4_pkgdatadir/[push.c])m4_exit])
 
 m4_include(b4_pkgdatadir/[c.m4])
-b4_check_percent_code_qualifiers([[requires]], [[provides]], [[top]])
+
+b4_check_percent_define_variables
+
+b4_check_percent_code_qualifiers([[requires]],
+                                 [[provides]],
+                                 [[top]])
 
 ## ---------------- ##
 ## Default values.  ##
index 2a637d3799db36a0228cc7749a9e2a56e84d70e5..54145cf5a244959d2bfa44575b0d0c0b7f122643 100644 (file)
@@ -209,6 +209,26 @@ void muscle_pair_list_grow (const char *muscle,
   obstack_free (&muscle_obstack, pair);
 }
 
+
+/*----------------------------------------------------------------------------.
+| Find the value of muscle KEY.  Unlike MUSCLE_FIND, this is always reliable  |
+| to determine whether KEY has a value.                                       |
+`----------------------------------------------------------------------------*/
+
+char const *
+muscle_find_const (char const *key)
+{
+  muscle_entry probe;
+  muscle_entry *result = NULL;
+
+  probe.key = key;
+  result = hash_lookup (muscle_table, &probe);
+  if (result)
+    return result->value;
+  return NULL;
+}
+
+
 /*----------------------------------------------------------------------------.
 | Find the value of muscle KEY.  Abort if muscle_insert was invoked more      |
 | recently than muscle_grow for KEY since muscle_find can't return a          |
@@ -216,7 +236,7 @@ void muscle_pair_list_grow (const char *muscle,
 `----------------------------------------------------------------------------*/
 
 char *
-muscle_find (const char *key)
+muscle_find (char const *key)
 {
   muscle_entry probe;
   muscle_entry *result = NULL;
@@ -276,3 +296,16 @@ muscle_boundary_grow (char const *key, boundary bound)
   muscle_grow (key, extension, "");
   obstack_free (&muscle_obstack, extension);
 }
+
+void
+muscle_grow_used_name_list (char const *key, char const *used_name,
+                            location loc)
+{
+  muscle_grow (key, "[[[[", ",");
+  muscle_grow (key, used_name, "");
+  muscle_grow (key, "]], [[", "");
+  muscle_boundary_grow (key, loc.start);
+  muscle_grow (key, "]], [[", "");
+  muscle_boundary_grow (key, loc.end);
+  muscle_grow (key, "]]]]", "");
+}
index 82df190120a17e37afdd650e4ad8508ec294bb3a..619fe78e407fa071d82e17ce3c13d4c3318d79d3 100644 (file)
@@ -26,6 +26,7 @@
 void muscle_init (void);
 void muscle_insert (char const *key, char const *value);
 char *muscle_find (char const *key);
+char const *muscle_find_const (char const *key);
 void muscle_free (void);
 
 
@@ -116,4 +117,12 @@ void muscles_m4_output (FILE *out);
    for special characters in the file name.  */
 void muscle_boundary_grow (char const *key, boundary bound);
 
+/* Grow KEY for the occurrence of the name USED_NAME at LOC appropriately for
+   use with b4_check_for_unrecognized_names in ../data/bison.m4.  USED_NAME
+   is not escaped with digraphs, so it must not contain `[' or `]'.  As a
+   precondition on b4_check_for_unrecognized_names, it can't contain `,'
+   either.  */
+void muscle_grow_used_name_list (char const *key, char const *used_name,
+                                 location loc);
+
 #endif /* not MUSCLE_TAB_H_ */
index f1d16c8dc7c617d2721b38bc0d3b6f325885b8eb..50b4fb8cf5c702d7558b44d247be925cf3751423 100644 (file)
@@ -77,7 +77,7 @@
 
 /* Copy the first part of user declarations.  */
 
-/* Line 171 of yacc.c  */
+/* Line 176 of yacc.c  */
 #line 1 "parse-gram.y"
 /* Bison Grammar Parser                             -*- C -*-
 
@@ -157,7 +157,7 @@ static int current_prec = 0;
 #define YYTYPE_UINT8 uint_fast8_t
 
 
-/* Line 171 of yacc.c  */
+/* Line 176 of yacc.c  */
 #line 162 "parse-gram.c"
 
 /* Enabling traces.  */
@@ -309,8 +309,8 @@ static int current_prec = 0;
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
-/* Line 205 of yacc.c  */
-#line 98 "parse-gram.y"
+/* Line 210 of yacc.c  */
+#line 97 "parse-gram.y"
 
   symbol *symbol;
   symbol_list *list;
@@ -322,7 +322,7 @@ typedef union YYSTYPE
   unsigned char character;
 }
 
-/* Line 205 of yacc.c  */
+/* Line 210 of yacc.c  */
 #line 327 "parse-gram.c"
        YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
@@ -347,7 +347,7 @@ typedef struct YYLTYPE
 /* Copy the second part of user declarations.  */
 
 
-/* Line 228 of yacc.c  */
+/* Line 233 of yacc.c  */
 #line 352 "parse-gram.c"
 
 #ifdef short
@@ -673,17 +673,17 @@ static const yytype_int8 yyrhs[] =
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   211,   211,   219,   221,   225,   226,   235,   236,   237,
-     238,   243,   244,   245,   246,   247,   248,   253,   262,   263,
-     264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
-     274,   275,   276,   277,   278,   279,   280,   284,   285,   286,
-     290,   297,   304,   308,   312,   317,   344,   345,   349,   378,
-     378,   383,   383,   388,   399,   414,   415,   416,   420,   421,
-     426,   428,   433,   434,   438,   439,   440,   441,   446,   451,
-     456,   462,   468,   479,   480,   489,   490,   496,   497,   498,
-     505,   505,   509,   510,   511,   516,   517,   519,   521,   523,
-     525,   535,   536,   542,   546,   551,   571,   573,   582,   587,
-     588,   593,   600,   602
+       0,   210,   210,   218,   220,   224,   225,   234,   235,   244,
+     245,   250,   251,   252,   253,   254,   255,   260,   269,   270,
+     271,   272,   273,   274,   275,   276,   277,   278,   279,   280,
+     281,   282,   283,   284,   285,   286,   287,   291,   292,   293,
+     297,   304,   311,   315,   319,   324,   347,   348,   352,   381,
+     381,   386,   386,   391,   402,   417,   418,   419,   423,   424,
+     429,   431,   436,   437,   441,   442,   443,   444,   449,   454,
+     459,   465,   471,   482,   483,   492,   493,   499,   500,   501,
+     508,   508,   512,   513,   514,   519,   520,   522,   524,   526,
+     528,   538,   539,   545,   549,   554,   574,   576,   585,   590,
+     591,   596,   603,   605
 };
 #endif
 
@@ -1044,146 +1044,146 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
     {
       case 3: /* "\"string\"" */
 
-/* Line 681 of yacc.c  */
-#line 189 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 188 "parse-gram.y"
        { fputs (quotearg_style (c_quoting_style, (yyvaluep->chars)), stderr); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1053 "parse-gram.c"
        break;
       case 4: /* "\"integer\"" */
 
-/* Line 681 of yacc.c  */
-#line 200 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 199 "parse-gram.y"
        { fprintf (stderr, "%d", (yyvaluep->integer)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1062 "parse-gram.c"
        break;
       case 45: /* "\"{...}\"" */
 
-/* Line 681 of yacc.c  */
-#line 191 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 190 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->code)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1071 "parse-gram.c"
        break;
       case 46: /* "\"char\"" */
 
-/* Line 681 of yacc.c  */
-#line 183 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 182 "parse-gram.y"
        { fputs (char_name ((yyvaluep->character)), stderr); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1080 "parse-gram.c"
        break;
       case 47: /* "\"epilogue\"" */
 
-/* Line 681 of yacc.c  */
-#line 191 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 190 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1089 "parse-gram.c"
        break;
       case 49: /* "\"identifier\"" */
 
-/* Line 681 of yacc.c  */
-#line 196 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 195 "parse-gram.y"
        { fputs ((yyvaluep->uniqstr), stderr); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1098 "parse-gram.c"
        break;
       case 50: /* "\"identifier:\"" */
 
-/* Line 681 of yacc.c  */
-#line 197 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 196 "parse-gram.y"
        { fprintf (stderr, "%s:", (yyvaluep->uniqstr)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1107 "parse-gram.c"
        break;
       case 53: /* "\"%{...%}\"" */
 
-/* Line 681 of yacc.c  */
-#line 191 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 190 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1116 "parse-gram.c"
        break;
       case 55: /* "\"type\"" */
 
-/* Line 681 of yacc.c  */
-#line 195 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 194 "parse-gram.y"
        { fprintf (stderr, "<%s>", (yyvaluep->uniqstr)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1125 "parse-gram.c"
        break;
       case 82: /* "content" */
 
-/* Line 681 of yacc.c  */
-#line 191 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 190 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1134 "parse-gram.c"
        break;
       case 83: /* "content.opt" */
 
-/* Line 681 of yacc.c  */
-#line 191 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 190 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1143 "parse-gram.c"
        break;
       case 84: /* "braceless" */
 
-/* Line 681 of yacc.c  */
-#line 191 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 190 "parse-gram.y"
        { fprintf (stderr, "{\n%s\n}", (yyvaluep->chars)); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1152 "parse-gram.c"
        break;
       case 85: /* "id" */
 
-/* Line 681 of yacc.c  */
-#line 203 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 202 "parse-gram.y"
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1161 "parse-gram.c"
        break;
       case 86: /* "id_colon" */
 
-/* Line 681 of yacc.c  */
-#line 204 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 203 "parse-gram.y"
        { fprintf (stderr, "%s:", (yyvaluep->symbol)->tag); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1170 "parse-gram.c"
        break;
       case 87: /* "symbol" */
 
-/* Line 681 of yacc.c  */
-#line 203 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 202 "parse-gram.y"
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1179 "parse-gram.c"
        break;
       case 88: /* "string_as_id" */
 
-/* Line 681 of yacc.c  */
-#line 203 "parse-gram.y"
+/* Line 686 of yacc.c  */
+#line 202 "parse-gram.y"
        { fprintf (stderr, "%s", (yyvaluep->symbol)->tag); };
 
-/* Line 681 of yacc.c  */
+/* Line 686 of yacc.c  */
 #line 1188 "parse-gram.c"
        break;
       default:
@@ -1698,8 +1698,8 @@ YYLTYPE yylloc;
 
   /* User initialization code.  */
   
-/* Line 1093 of yacc.c  */
-#line 90 "parse-gram.y"
+/* Line 1098 of yacc.c  */
+#line 89 "parse-gram.y"
 {
   /* Bison's grammar can initial empty locations, hence a default
      location is needed. */
@@ -1707,7 +1707,7 @@ YYLTYPE yylloc;
   boundary_set (&yylloc.end, current_file, 1, 1);
 }
 
-/* Line 1093 of yacc.c  */
+/* Line 1098 of yacc.c  */
 #line 1712 "parse-gram.c"
   yylsp[0] = yylloc;
   goto yysetstate;
@@ -1893,8 +1893,8 @@ yyreduce:
     {
         case 6:
 
-/* Line 1280 of yacc.c  */
-#line 227 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 226 "parse-gram.y"
     {
       code_props plain_code;
       code_props_plain_init (&plain_code, (yyvsp[(1) - (1)].chars), (yylsp[(1) - (1)]));
@@ -1907,29 +1907,36 @@ yyreduce:
 
   case 7:
 
-/* Line 1280 of yacc.c  */
-#line 235 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 234 "parse-gram.y"
     { debug_flag = true; }
     break;
 
   case 8:
 
-/* Line 1280 of yacc.c  */
+/* Line 1285 of yacc.c  */
 #line 236 "parse-gram.y"
-    { muscle_insert ((yyvsp[(2) - (3)].chars), (yyvsp[(3) - (3)].chars)); }
+    {
+      /* FIXME: Special characters in $2 may break %define.
+         For example: `['.  */
+      if (muscle_find_const ((yyvsp[(2) - (3)].chars)))
+        warn_at ((yylsp[(2) - (3)]), _("%s: `%s' redefined"), "%define", (yyvsp[(2) - (3)].chars));
+      muscle_insert ((yyvsp[(2) - (3)].chars), (yyvsp[(3) - (3)].chars));
+      muscle_grow_used_name_list ("used_percent_define_variables", (yyvsp[(2) - (3)].chars), (yylsp[(2) - (3)]));
+    }
     break;
 
   case 9:
 
-/* Line 1280 of yacc.c  */
-#line 237 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 244 "parse-gram.y"
     { defines_flag = true; }
     break;
 
   case 10:
 
-/* Line 1280 of yacc.c  */
-#line 239 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 246 "parse-gram.y"
     {
       defines_flag = true;
       spec_defines_file = xstrdup ((yyvsp[(2) - (2)].chars));
@@ -1938,43 +1945,43 @@ yyreduce:
 
   case 11:
 
-/* Line 1280 of yacc.c  */
-#line 243 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 250 "parse-gram.y"
     { error_verbose = true; }
     break;
 
   case 12:
 
-/* Line 1280 of yacc.c  */
-#line 244 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 251 "parse-gram.y"
     { expected_sr_conflicts = (yyvsp[(2) - (2)].integer); }
     break;
 
   case 13:
 
-/* Line 1280 of yacc.c  */
-#line 245 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 252 "parse-gram.y"
     { expected_rr_conflicts = (yyvsp[(2) - (2)].integer); }
     break;
 
   case 14:
 
-/* Line 1280 of yacc.c  */
-#line 246 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 253 "parse-gram.y"
     { spec_file_prefix = (yyvsp[(2) - (2)].chars); }
     break;
 
   case 15:
 
-/* Line 1280 of yacc.c  */
-#line 247 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 254 "parse-gram.y"
     { spec_file_prefix = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 16:
 
-/* Line 1280 of yacc.c  */
-#line 249 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 256 "parse-gram.y"
     {
       nondeterministic_parser = true;
       glr_parser = true;
@@ -1983,8 +1990,8 @@ yyreduce:
 
   case 17:
 
-/* Line 1280 of yacc.c  */
-#line 254 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 261 "parse-gram.y"
     {
       code_props action;
       code_props_symbol_action_init (&action, (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)]));
@@ -1997,134 +2004,134 @@ yyreduce:
 
   case 18:
 
-/* Line 1280 of yacc.c  */
-#line 262 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 269 "parse-gram.y"
     { language_argmatch ((yyvsp[(2) - (2)].chars), 1, &(yylsp[(1) - (2)])); }
     break;
 
   case 19:
 
-/* Line 1280 of yacc.c  */
-#line 263 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 270 "parse-gram.y"
     { add_param ("lex_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); }
     break;
 
   case 20:
 
-/* Line 1280 of yacc.c  */
-#line 264 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 271 "parse-gram.y"
     { locations_flag = true; }
     break;
 
   case 21:
 
-/* Line 1280 of yacc.c  */
-#line 265 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 272 "parse-gram.y"
     { spec_name_prefix = (yyvsp[(2) - (2)].chars); }
     break;
 
   case 22:
 
-/* Line 1280 of yacc.c  */
-#line 266 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 273 "parse-gram.y"
     { spec_name_prefix = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 23:
 
-/* Line 1280 of yacc.c  */
-#line 267 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 274 "parse-gram.y"
     { no_lines_flag = true; }
     break;
 
   case 24:
 
-/* Line 1280 of yacc.c  */
-#line 268 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 275 "parse-gram.y"
     { nondeterministic_parser = true; }
     break;
 
   case 25:
 
-/* Line 1280 of yacc.c  */
-#line 269 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 276 "parse-gram.y"
     { spec_outfile = (yyvsp[(2) - (2)].chars); }
     break;
 
   case 26:
 
-/* Line 1280 of yacc.c  */
-#line 270 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 277 "parse-gram.y"
     { spec_outfile = (yyvsp[(3) - (3)].chars); }
     break;
 
   case 27:
 
-/* Line 1280 of yacc.c  */
-#line 271 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 278 "parse-gram.y"
     { add_param ("parse_param", (yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); }
     break;
 
   case 28:
 
-/* Line 1280 of yacc.c  */
-#line 272 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 279 "parse-gram.y"
     { pure_parser = true; }
     break;
 
   case 29:
 
-/* Line 1280 of yacc.c  */
-#line 273 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 280 "parse-gram.y"
     { push_parser = true; pull_parser = false; }
     break;
 
   case 30:
 
-/* Line 1280 of yacc.c  */
-#line 274 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 281 "parse-gram.y"
     { push_parser = true; pull_parser = true; }
     break;
 
   case 31:
 
-/* Line 1280 of yacc.c  */
-#line 275 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 282 "parse-gram.y"
     { version_check (&(yylsp[(2) - (2)]), (yyvsp[(2) - (2)].chars)); }
     break;
 
   case 32:
 
-/* Line 1280 of yacc.c  */
-#line 276 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 283 "parse-gram.y"
     { skeleton_arg ((yyvsp[(2) - (2)].chars), 1, &(yylsp[(1) - (2)])); }
     break;
 
   case 33:
 
-/* Line 1280 of yacc.c  */
-#line 277 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 284 "parse-gram.y"
     { token_table_flag = true; }
     break;
 
   case 34:
 
-/* Line 1280 of yacc.c  */
-#line 278 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 285 "parse-gram.y"
     { report_flag = report_states; }
     break;
 
   case 35:
 
-/* Line 1280 of yacc.c  */
-#line 279 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 286 "parse-gram.y"
     { yacc_flag = true; }
     break;
 
   case 39:
 
-/* Line 1280 of yacc.c  */
-#line 287 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 294 "parse-gram.y"
     {
       grammar_start_symbol_set ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]));
     }
@@ -2132,8 +2139,8 @@ yyreduce:
 
   case 40:
 
-/* Line 1280 of yacc.c  */
-#line 291 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 298 "parse-gram.y"
     {
       symbol_list *list;
       for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
@@ -2144,8 +2151,8 @@ yyreduce:
 
   case 41:
 
-/* Line 1280 of yacc.c  */
-#line 298 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 305 "parse-gram.y"
     {
       symbol_list *list;
       for (list = (yyvsp[(3) - (3)].list); list; list = list->next)
@@ -2156,8 +2163,8 @@ yyreduce:
 
   case 42:
 
-/* Line 1280 of yacc.c  */
-#line 305 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 312 "parse-gram.y"
     {
       default_prec = true;
     }
@@ -2165,8 +2172,8 @@ yyreduce:
 
   case 43:
 
-/* Line 1280 of yacc.c  */
-#line 309 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 316 "parse-gram.y"
     {
       default_prec = false;
     }
@@ -2174,8 +2181,8 @@ yyreduce:
 
   case 44:
 
-/* Line 1280 of yacc.c  */
-#line 313 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 320 "parse-gram.y"
     {
       muscle_code_grow ("percent_code", (yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)]));
       code_scanner_last_string_free ();
@@ -2184,9 +2191,11 @@ yyreduce:
 
   case 45:
 
-/* Line 1280 of yacc.c  */
-#line 318 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 325 "parse-gram.y"
     {
+      /* FIXME: Special characters in $2 may break %code.
+         For example: `['.  */
       char const name_prefix[] = "percent_code_";
       char *name = xmalloc (sizeof name_prefix + strlen ((yyvsp[(2) - (3)].chars)));
       strcpy (name, name_prefix);
@@ -2194,34 +2203,28 @@ yyreduce:
       muscle_code_grow (uniqstr_new (name), (yyvsp[(3) - (3)].chars), (yylsp[(3) - (3)]));
       free (name);
       code_scanner_last_string_free ();
-      muscle_grow ("used_percent_code_qualifiers", "[[[[", ",");
-      muscle_grow ("used_percent_code_qualifiers", (yyvsp[(2) - (3)].chars), "");
-      muscle_grow ("used_percent_code_qualifiers", "]], [[", "");
-      muscle_boundary_grow ("used_percent_code_qualifiers", (yylsp[(2) - (3)]).start);
-      muscle_grow ("used_percent_code_qualifiers", "]], [[", "");
-      muscle_boundary_grow ("used_percent_code_qualifiers", (yylsp[(2) - (3)]).end);
-      muscle_grow ("used_percent_code_qualifiers", "]]]]", "");
+      muscle_grow_used_name_list ("used_percent_code_qualifiers", (yyvsp[(2) - (3)].chars), (yylsp[(2) - (3)]));
     }
     break;
 
   case 46:
 
-/* Line 1280 of yacc.c  */
-#line 344 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 347 "parse-gram.y"
     {}
     break;
 
   case 47:
 
-/* Line 1280 of yacc.c  */
-#line 345 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 348 "parse-gram.y"
     { muscle_code_grow ("union_name", (yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 48:
 
-/* Line 1280 of yacc.c  */
-#line 350 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 353 "parse-gram.y"
     {
       char const *body = (yyvsp[(3) - (3)].code);
 
@@ -2248,15 +2251,15 @@ yyreduce:
 
   case 49:
 
-/* Line 1280 of yacc.c  */
-#line 378 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 381 "parse-gram.y"
     { current_class = nterm_sym; }
     break;
 
   case 50:
 
-/* Line 1280 of yacc.c  */
-#line 379 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 382 "parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
@@ -2265,15 +2268,15 @@ yyreduce:
 
   case 51:
 
-/* Line 1280 of yacc.c  */
-#line 383 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 386 "parse-gram.y"
     { current_class = token_sym; }
     break;
 
   case 52:
 
-/* Line 1280 of yacc.c  */
-#line 384 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 387 "parse-gram.y"
     {
       current_class = unknown_sym;
       current_type = NULL;
@@ -2282,8 +2285,8 @@ yyreduce:
 
   case 53:
 
-/* Line 1280 of yacc.c  */
-#line 389 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 392 "parse-gram.y"
     {
       symbol_list *list;
       tag_seen = true;
@@ -2295,8 +2298,8 @@ yyreduce:
 
   case 54:
 
-/* Line 1280 of yacc.c  */
-#line 400 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 403 "parse-gram.y"
     {
       symbol_list *list;
       ++current_prec;
@@ -2312,99 +2315,99 @@ yyreduce:
 
   case 55:
 
-/* Line 1280 of yacc.c  */
-#line 414 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 417 "parse-gram.y"
     { (yyval.assoc) = left_assoc; }
     break;
 
   case 56:
 
-/* Line 1280 of yacc.c  */
-#line 415 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 418 "parse-gram.y"
     { (yyval.assoc) = right_assoc; }
     break;
 
   case 57:
 
-/* Line 1280 of yacc.c  */
-#line 416 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 419 "parse-gram.y"
     { (yyval.assoc) = non_assoc; }
     break;
 
   case 58:
 
-/* Line 1280 of yacc.c  */
-#line 420 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 423 "parse-gram.y"
     { current_type = NULL; }
     break;
 
   case 59:
 
-/* Line 1280 of yacc.c  */
-#line 421 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 424 "parse-gram.y"
     { current_type = (yyvsp[(1) - (1)].uniqstr); tag_seen = true; }
     break;
 
   case 60:
 
-/* Line 1280 of yacc.c  */
-#line 427 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 430 "parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
     break;
 
   case 61:
 
-/* Line 1280 of yacc.c  */
-#line 429 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 432 "parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), symbol_list_sym_new ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)]))); }
     break;
 
   case 62:
 
-/* Line 1280 of yacc.c  */
-#line 433 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 436 "parse-gram.y"
     { (yyval.list) = (yyvsp[(1) - (1)].list); }
     break;
 
   case 63:
 
-/* Line 1280 of yacc.c  */
-#line 434 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 437 "parse-gram.y"
     { (yyval.list) = symbol_list_prepend ((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list)); }
     break;
 
   case 64:
 
-/* Line 1280 of yacc.c  */
-#line 438 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 441 "parse-gram.y"
     { (yyval.list) = symbol_list_sym_new ((yyvsp[(1) - (1)].symbol), (yylsp[(1) - (1)])); }
     break;
 
   case 65:
 
-/* Line 1280 of yacc.c  */
-#line 439 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 442 "parse-gram.y"
     { (yyval.list) = symbol_list_type_new ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 66:
 
-/* Line 1280 of yacc.c  */
-#line 440 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 443 "parse-gram.y"
     { (yyval.list) = symbol_list_default_tagged_new ((yylsp[(1) - (1)])); }
     break;
 
   case 67:
 
-/* Line 1280 of yacc.c  */
-#line 441 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 444 "parse-gram.y"
     { (yyval.list) = symbol_list_default_tagless_new ((yylsp[(1) - (1)])); }
     break;
 
   case 68:
 
-/* Line 1280 of yacc.c  */
-#line 447 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 450 "parse-gram.y"
     {
        current_type = (yyvsp[(1) - (1)].uniqstr);
        tag_seen = true;
@@ -2413,8 +2416,8 @@ yyreduce:
 
   case 69:
 
-/* Line 1280 of yacc.c  */
-#line 452 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 455 "parse-gram.y"
     {
        symbol_class_set ((yyvsp[(1) - (1)].symbol), current_class, (yylsp[(1) - (1)]), true);
        symbol_type_set ((yyvsp[(1) - (1)].symbol), current_type, (yylsp[(1) - (1)]));
@@ -2423,8 +2426,8 @@ yyreduce:
 
   case 70:
 
-/* Line 1280 of yacc.c  */
-#line 457 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 460 "parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
       symbol_type_set ((yyvsp[(1) - (2)].symbol), current_type, (yylsp[(1) - (2)]));
@@ -2434,8 +2437,8 @@ yyreduce:
 
   case 71:
 
-/* Line 1280 of yacc.c  */
-#line 463 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 466 "parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (2)].symbol), current_class, (yylsp[(1) - (2)]), true);
       symbol_type_set ((yyvsp[(1) - (2)].symbol), current_type, (yylsp[(1) - (2)]));
@@ -2445,8 +2448,8 @@ yyreduce:
 
   case 72:
 
-/* Line 1280 of yacc.c  */
-#line 469 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 472 "parse-gram.y"
     {
       symbol_class_set ((yyvsp[(1) - (3)].symbol), current_class, (yylsp[(1) - (3)]), true);
       symbol_type_set ((yyvsp[(1) - (3)].symbol), current_type, (yylsp[(1) - (3)]));
@@ -2457,8 +2460,8 @@ yyreduce:
 
   case 79:
 
-/* Line 1280 of yacc.c  */
-#line 499 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 502 "parse-gram.y"
     {
       yyerrok;
     }
@@ -2466,71 +2469,71 @@ yyreduce:
 
   case 80:
 
-/* Line 1280 of yacc.c  */
-#line 505 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 508 "parse-gram.y"
     { current_lhs = (yyvsp[(1) - (1)].symbol); current_lhs_location = (yylsp[(1) - (1)]); }
     break;
 
   case 82:
 
-/* Line 1280 of yacc.c  */
-#line 509 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 512 "parse-gram.y"
     { grammar_current_rule_end ((yylsp[(1) - (1)])); }
     break;
 
   case 83:
 
-/* Line 1280 of yacc.c  */
-#line 510 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 513 "parse-gram.y"
     { grammar_current_rule_end ((yylsp[(3) - (3)])); }
     break;
 
   case 85:
 
-/* Line 1280 of yacc.c  */
-#line 516 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 519 "parse-gram.y"
     { grammar_current_rule_begin (current_lhs, current_lhs_location); }
     break;
 
   case 86:
 
-/* Line 1280 of yacc.c  */
-#line 518 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 521 "parse-gram.y"
     { grammar_current_rule_symbol_append ((yyvsp[(2) - (2)].symbol), (yylsp[(2) - (2)])); }
     break;
 
   case 87:
 
-/* Line 1280 of yacc.c  */
-#line 520 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 523 "parse-gram.y"
     { grammar_current_rule_action_append ((yyvsp[(2) - (2)].code), (yylsp[(2) - (2)])); }
     break;
 
   case 88:
 
-/* Line 1280 of yacc.c  */
-#line 522 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 525 "parse-gram.y"
     { grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); }
     break;
 
   case 89:
 
-/* Line 1280 of yacc.c  */
-#line 524 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 527 "parse-gram.y"
     { grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); }
     break;
 
   case 90:
 
-/* Line 1280 of yacc.c  */
-#line 526 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 529 "parse-gram.y"
     { grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); }
     break;
 
   case 93:
 
-/* Line 1280 of yacc.c  */
-#line 542 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 545 "parse-gram.y"
     {
       static char one[] = "1";
       (yyval.chars) = one;
@@ -2539,8 +2542,8 @@ yyreduce:
 
   case 95:
 
-/* Line 1280 of yacc.c  */
-#line 552 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 555 "parse-gram.y"
     {
       code_props plain_code;
       (yyvsp[(1) - (1)].code)[strlen ((yyvsp[(1) - (1)].code)) - 1] = '\n';
@@ -2553,15 +2556,15 @@ yyreduce:
 
   case 96:
 
-/* Line 1280 of yacc.c  */
-#line 572 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 575 "parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 97:
 
-/* Line 1280 of yacc.c  */
-#line 574 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 577 "parse-gram.y"
     {
       (yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)]));
       symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
@@ -2571,15 +2574,15 @@ yyreduce:
 
   case 98:
 
-/* Line 1280 of yacc.c  */
-#line 582 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 585 "parse-gram.y"
     { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
     break;
 
   case 101:
 
-/* Line 1280 of yacc.c  */
-#line 594 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 597 "parse-gram.y"
     {
       (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)]));
       symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
@@ -2588,8 +2591,8 @@ yyreduce:
 
   case 103:
 
-/* Line 1280 of yacc.c  */
-#line 603 "parse-gram.y"
+/* Line 1285 of yacc.c  */
+#line 606 "parse-gram.y"
     {
       code_props plain_code;
       code_props_plain_init (&plain_code, (yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)]));
@@ -2602,8 +2605,8 @@ yyreduce:
 
 
 
-/* Line 1280 of yacc.c  */
-#line 2607 "parse-gram.c"
+/* Line 1285 of yacc.c  */
+#line 2610 "parse-gram.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2821,8 +2824,8 @@ yyreturn:
 
 
 
-/* Line 1497 of yacc.c  */
-#line 613 "parse-gram.y"
+/* Line 1502 of yacc.c  */
+#line 616 "parse-gram.y"
 
 
 
index 1fdbbef250d1d91e4953444e220301ed62213348..16a979fbd35cf0742c32af8705593f4d01f3335d 100644 (file)
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
-/* Line 1546 of yacc.c  */
-#line 98 "parse-gram.y"
+/* Line 1551 of yacc.c  */
+#line 97 "parse-gram.y"
 
   symbol *symbol;
   symbol_list *list;
@@ -178,7 +178,7 @@ typedef union YYSTYPE
   unsigned char character;
 }
 
-/* Line 1546 of yacc.c  */
+/* Line 1551 of yacc.c  */
 #line 183 "parse-gram.h"
        YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
index ff3b9de85f2319427b3b915e9a2ebd5e97b080fd..d0ea0569b4f6b090dd225664a1aed105c7514d0b 100644 (file)
@@ -82,7 +82,6 @@ static int current_prec = 0;
 %locations
 %pure-parser
 %error-verbose
-%defines
 %name-prefix="gram_"
 %expect 0
 
@@ -233,7 +232,15 @@ prologue_declaration:
       code_scanner_last_string_free ();
     }
 | "%debug"                         { debug_flag = true; }
-| "%define" STRING content.opt     { muscle_insert ($2, $3); }
+| "%define" STRING content.opt
+    {
+      /* FIXME: Special characters in $2 may break %define.
+         For example: `['.  */
+      if (muscle_find_const ($2))
+        warn_at (@2, _("%s: `%s' redefined"), "%define", $2);
+      muscle_insert ($2, $3);
+      muscle_grow_used_name_list ("used_percent_define_variables", $2, @2);
+    }
 | "%defines"                       { defines_flag = true; }
 | "%defines" STRING
     {
@@ -316,6 +323,8 @@ grammar_declaration:
     }
 | "%code" STRING braceless
     {
+      /* FIXME: Special characters in $2 may break %code.
+         For example: `['.  */
       char const name_prefix[] = "percent_code_";
       char *name = xmalloc (sizeof name_prefix + strlen ($2));
       strcpy (name, name_prefix);
@@ -323,13 +332,7 @@ grammar_declaration:
       muscle_code_grow (uniqstr_new (name), $3, @3);
       free (name);
       code_scanner_last_string_free ();
-      muscle_grow ("used_percent_code_qualifiers", "[[[[", ",");
-      muscle_grow ("used_percent_code_qualifiers", $2, "");
-      muscle_grow ("used_percent_code_qualifiers", "]], [[", "");
-      muscle_boundary_grow ("used_percent_code_qualifiers", @2.start);
-      muscle_grow ("used_percent_code_qualifiers", "]], [[", "");
-      muscle_boundary_grow ("used_percent_code_qualifiers", @2.end);
-      muscle_grow ("used_percent_code_qualifiers", "]]]]", "");
+      muscle_grow_used_name_list ("used_percent_code_qualifiers", $2, @2);
     }
 ;
 
index 352aaeaa351189684d5c9abcc5c9801a8e303a6f..7bbfb3038f1762b76b8cf4d7522aac4f3eb8c2a4 100644 (file)
@@ -788,3 +788,28 @@ special-char-@:>@.y:3.7-8: `' is not a recognized %code qualifier
 ]])
 
 AT_CLEANUP
+
+
+## ---------------- ##
+## %define errors.  ##
+## ---------------- ##
+
+AT_SETUP([%define errors])
+
+AT_DATA([input.y],
+[[%define "var" "value1"
+%define "var" "value1"
+ %define "var" "value2"
+%%
+start: ;
+]])
+
+AT_CHECK([[bison input.y]], [1], [],
+[[input.y:2.9-13: warning: %define: `var' redefined
+input.y:3.10-14: warning: %define: `var' redefined
+input.y:1.9-13: `var' is not a recognized %define variable
+input.y:2.9-13: `var' is not a recognized %define variable
+input.y:3.10-14: `var' is not a recognized %define variable
+]])
+
+AT_CLEANUP