+# Make sure that fields after $n or $-n are parsed correctly. At one
+# point while implementing dashes in symbol names, we were dropping
+# fields after $-n.
+AT_DATA_GRAMMAR([[input.y]],
+[[
+%{
+# include <stdio.h>
+ static int yylex (void);
+ static void yyerror (char const *msg);
+ typedef struct { int val; } stype;
+# define YYSTYPE stype
+%}
+
+%%
+start: one two { $$.val = $1.val + $2.val; } sum ;
+one: { $$.val = 1; } ;
+two: { $$.val = 2; } ;
+sum: { printf ("%d\n", $0.val + $-1.val + $-2.val); } ;
+
+%%
+
+static int
+yylex (void)
+{
+ return 0;
+}
+
+static void
+yyerror (char const *msg)
+{
+ fprintf (stderr, "%s\n", msg);
+}
+
+int
+main (void)
+{
+ return yyparse ();
+}
+]])
+
+AT_BISON_CHECK([[-o input.c input.y]])
+AT_COMPILE([[input]])
+AT_PARSER_CHECK([[./input]], [[0]],
+[[6
+]])
+
m4_define([_AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN],
[m4_if($1, 0,
[m4_pushdef([kind], []) m4_pushdef([not_kind], [*])],
[m4_pushdef([kind], [*]) m4_pushdef([not_kind], [])])
AT_DATA_GRAMMAR([[input]]$1[[.y]],
m4_define([_AT_CHECK_DEFAULT_PRINTER_AND_DESTRUCTOR_FOR_END_TOKEN],
[m4_if($1, 0,
[m4_pushdef([kind], []) m4_pushdef([not_kind], [*])],
[m4_pushdef([kind], [*]) m4_pushdef([not_kind], [])])
AT_DATA_GRAMMAR([[input]]$1[[.y]],
-: 'a' { semi; /* TEST:N:2 */ }
-| 'b' { if (0) {no_semi} /* TEST:N:2 */ }
-| 'c' { if (0) {semi;} /* TEST:N:2 */ }
-| 'd' { semi; no_semi /* TEST:Y:2 */ }
-| 'e' { semi(); no_semi() /* TEST:Y:2 */ }
-| 'f' { semi[]; no_semi[] /* TEST:Y:2 */ }
-| 'g' { semi++; no_semi++ /* TEST:Y:2 */ }
-| 'h' { {no_semi} no_semi /* TEST:Y:2 */ }
-| 'i' { {semi;} no_semi /* TEST:Y:2 */ }
+: 'a' { semi; /* TEST:N:2 */ }
+| 'b' { if (0) {no_semi} /* TEST:N:2 */ }
+| 'c' { if (0) {semi;} /* TEST:N:2 */ }
+| 'd' { semi; no_semi /* TEST:Y:2 */ }
+| 'e' { semi(); no_semi() /* TEST:Y:2 */ }
+| 'f' { semi[]; no_semi[] /* TEST:Y:2 */ }
+| 'g' { semi++; no_semi++ /* TEST:Y:2 */ }
+| 'h' { {no_semi} no_semi /* TEST:Y:2 */ }
+| 'i' { {semi;} no_semi /* TEST:Y:2 */ }
- : 'a' { semi; // TEST:N:1 ;
-} | 'b' { if (0) {no_semi} // TEST:N:1 ;
-} | 'c' { if (0) {semi;} // TEST:N:1 ;
-} | 'd' { semi; no_semi // TEST:Y:1 ;
-} | 'e' { semi(); no_semi() // TEST:Y:1 ;
-} | 'f' { semi[]; no_semi[] // TEST:Y:1 ;
-} | 'g' { semi++; no_semi++ // TEST:Y:1 ;
-} | 'h' { {no_semi} no_semi // TEST:Y:1 ;
-} | 'i' { {semi;} no_semi // TEST:Y:1 ;
+ : 'a' { semi; // TEST:N:1 ;
+} | 'b' { if (0) {no_semi} // TEST:N:1 ;
+} | 'c' { if (0) {semi;} // TEST:N:1 ;
+} | 'd' { semi; no_semi // TEST:Y:1 ;
+} | 'e' { semi(); no_semi() // TEST:Y:1 ;
+} | 'f' { semi[]; no_semi[] // TEST:Y:1 ;
+} | 'g' { semi++; no_semi++ // TEST:Y:1 ;
+} | 'h' { {no_semi} no_semi // TEST:Y:1 ;
+} | 'i' { {semi;} no_semi // TEST:Y:1 ;
- : 'a' { semi; // TEST:N:1 {}
-} | 'b' { if (0) {no_semi} // TEST:N:1 {}
-} | 'c' { if (0) {semi;} // TEST:N:1 {}
-} | 'd' { semi; no_semi // TEST:Y:1 {}
-} | 'e' { semi(); no_semi() // TEST:Y:1 {}
-} | 'f' { semi[]; no_semi[] // TEST:Y:1 {}
-} | 'g' { semi++; no_semi++ // TEST:Y:1 {}
-} | 'h' { {no_semi} no_semi // TEST:Y:1 {}
-} | 'i' { {semi;} no_semi // TEST:Y:1 {}
+ : 'a' { semi; // TEST:N:1 {}
+} | 'b' { if (0) {no_semi} // TEST:N:1 {}
+} | 'c' { if (0) {semi;} // TEST:N:1 {}
+} | 'd' { semi; no_semi // TEST:Y:1 {}
+} | 'e' { semi(); no_semi() // TEST:Y:1 {}
+} | 'f' { semi[]; no_semi[] // TEST:Y:1 {}
+} | 'g' { semi++; no_semi++ // TEST:Y:1 {}
+} | 'h' { {no_semi} no_semi // TEST:Y:1 {}
+} | 'i' { {semi;} no_semi // TEST:Y:1 {}
-[[input.y:8.48: warning: a `;' might be needed at the end of action code
-input.y:8.48: warning: future versions of Bison will not add the `;'
-input.y:9.48: warning: a `;' might be needed at the end of action code
-input.y:9.48: warning: future versions of Bison will not add the `;'
-input.y:10.48: warning: a `;' might be needed at the end of action code
-input.y:10.48: warning: future versions of Bison will not add the `;'
-input.y:11.48: warning: a `;' might be needed at the end of action code
-input.y:11.48: warning: future versions of Bison will not add the `;'
-input.y:12.48: warning: a `;' might be needed at the end of action code
-input.y:12.48: warning: future versions of Bison will not add the `;'
-input.y:13.48: warning: a `;' might be needed at the end of action code
-input.y:13.48: warning: future versions of Bison will not add the `;'
-input.y:20.1: warning: a `;' might be needed at the end of action code
-input.y:20.1: warning: future versions of Bison will not add the `;'
-input.y:21.1: warning: a `;' might be needed at the end of action code
-input.y:21.1: warning: future versions of Bison will not add the `;'
-input.y:22.1: warning: a `;' might be needed at the end of action code
-input.y:22.1: warning: future versions of Bison will not add the `;'
-input.y:23.1: warning: a `;' might be needed at the end of action code
-input.y:23.1: warning: future versions of Bison will not add the `;'
-input.y:24.1: warning: a `;' might be needed at the end of action code
-input.y:24.1: warning: future versions of Bison will not add the `;'
-input.y:25.1: warning: a `;' might be needed at the end of action code
-input.y:25.1: warning: future versions of Bison will not add the `;'
-input.y:31.1: warning: a `;' might be needed at the end of action code
-input.y:31.1: warning: future versions of Bison will not add the `;'
-input.y:32.1: warning: a `;' might be needed at the end of action code
-input.y:32.1: warning: future versions of Bison will not add the `;'
-input.y:33.1: warning: a `;' might be needed at the end of action code
-input.y:33.1: warning: future versions of Bison will not add the `;'
-input.y:34.1: warning: a `;' might be needed at the end of action code
-input.y:34.1: warning: future versions of Bison will not add the `;'
-input.y:35.1: warning: a `;' might be needed at the end of action code
-input.y:35.1: warning: future versions of Bison will not add the `;'
-input.y:36.1: warning: a `;' might be needed at the end of action code
-input.y:36.1: warning: future versions of Bison will not add the `;'
+[[input.y:8.48: warning: a ';' might be needed at the end of action code
+input.y:8.48: warning: future versions of Bison will not add the ';'
+input.y:9.48: warning: a ';' might be needed at the end of action code
+input.y:9.48: warning: future versions of Bison will not add the ';'
+input.y:10.48: warning: a ';' might be needed at the end of action code
+input.y:10.48: warning: future versions of Bison will not add the ';'
+input.y:11.48: warning: a ';' might be needed at the end of action code
+input.y:11.48: warning: future versions of Bison will not add the ';'
+input.y:12.48: warning: a ';' might be needed at the end of action code
+input.y:12.48: warning: future versions of Bison will not add the ';'
+input.y:13.48: warning: a ';' might be needed at the end of action code
+input.y:13.48: warning: future versions of Bison will not add the ';'
+input.y:20.1: warning: a ';' might be needed at the end of action code
+input.y:20.1: warning: future versions of Bison will not add the ';'
+input.y:21.1: warning: a ';' might be needed at the end of action code
+input.y:21.1: warning: future versions of Bison will not add the ';'
+input.y:22.1: warning: a ';' might be needed at the end of action code
+input.y:22.1: warning: future versions of Bison will not add the ';'
+input.y:23.1: warning: a ';' might be needed at the end of action code
+input.y:23.1: warning: future versions of Bison will not add the ';'
+input.y:24.1: warning: a ';' might be needed at the end of action code
+input.y:24.1: warning: future versions of Bison will not add the ';'
+input.y:25.1: warning: a ';' might be needed at the end of action code
+input.y:25.1: warning: future versions of Bison will not add the ';'
+input.y:31.1: warning: a ';' might be needed at the end of action code
+input.y:31.1: warning: future versions of Bison will not add the ';'
+input.y:32.1: warning: a ';' might be needed at the end of action code
+input.y:32.1: warning: future versions of Bison will not add the ';'
+input.y:33.1: warning: a ';' might be needed at the end of action code
+input.y:33.1: warning: future versions of Bison will not add the ';'
+input.y:34.1: warning: a ';' might be needed at the end of action code
+input.y:34.1: warning: future versions of Bison will not add the ';'
+input.y:35.1: warning: a ';' might be needed at the end of action code
+input.y:35.1: warning: future versions of Bison will not add the ';'
+input.y:36.1: warning: a ';' might be needed at the end of action code
+input.y:36.1: warning: future versions of Bison will not add the ';'
+
+## ---------- ##
+## YYBACKUP. ##
+## ---------- ##
+
+AT_SETUP([[YYBACKUP]])
+
+AT_DATA_GRAMMAR([input.y],
+[[
+%error-verbose
+%debug
+%pure-parser
+%code {
+# include <stdio.h>
+# include <stdlib.h>
+# include <assert.h>
+
+ static void yyerror (const char *msg);
+ static int yylex (YYSTYPE *yylval);
+}
+%%
+input:
+ exp exp {}
+;
+
+exp:
+ 'a' { printf ("a: %d\n", $1); }
+| 'b' { YYBACKUP('a', 123); }
+| 'c' 'd' { YYBACKUP('a', 456); }
+;
+
+%%
+static int
+yylex (YYSTYPE *yylval)
+{
+ static char const input[] = "bcd";
+ static size_t toknum;
+ assert (toknum < sizeof input);
+ *yylval = (toknum + 1) * 10;
+ return input[toknum++];
+}
+
+static void
+yyerror (const char *msg)
+{
+ fprintf (stderr, "%s\n", msg);
+}
+
+int
+main (void)
+{
+ yydebug = !!getenv("YYDEBUG");
+ return yyparse ();
+}
+]])
+
+AT_BISON_CHECK([[-o input.c input.y]])
+AT_COMPILE([[input]])
+AT_PARSER_CHECK([[./input]], [[0]],
+[[a: 123
+a: 456
+]])
+
+AT_CLEANUP