style: rename stmtMerge as stmt_merge
[bison.git] / tests / actions.at
blobb7b4c0301fe87d7dc3ad359ef20bdc0c12085081
1 # Executing Actions.                               -*- Autotest -*-
3 # Copyright (C) 2001-2015, 2018-2021 Free Software Foundation, Inc.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
18 AT_BANNER([[User Actions.]])
20 ## ----------------- ##
21 ## Midrule actions.  ##
22 ## ----------------- ##
24 AT_SETUP([Midrule actions])
26 # Bison once forgot the midrule actions.  It was because the action
27 # was attached to the host rule (the one with the midrule action),
28 # instead of being attached to the empty rule dedicated to this
29 # action.
31 AT_BISON_OPTION_PUSHDEFS
32 AT_DATA_GRAMMAR([[input.y]],
33 [[%define parse.error verbose
34 %debug
35 %code {
36 ]AT_YYERROR_DECLARE[
37 ]AT_YYLEX_DECLARE[
40 exp:     { putchar ('0'); }
41      '1' { putchar ('1'); }
42      '2' { putchar ('2'); }
43      '3' { putchar ('3'); }
44      '4' { putchar ('4'); }
45      '5' { putchar ('5'); }
46      '6' { putchar ('6'); }
47      '7' { putchar ('7'); }
48      '8' { putchar ('8'); }
49      '9' { putchar ('9'); }
50          { putchar ('\n'); }
51    ;
53 ]AT_YYERROR_DEFINE[
54 ]AT_YYLEX_DEFINE(["123456789"])[
55 ]AT_MAIN_DEFINE[
56 ]])
57 AT_BISON_OPTION_POPDEFS
59 AT_BISON_CHECK([-d -v -o input.c input.y])
60 AT_COMPILE([input])
61 AT_PARSER_CHECK([input], 0,
62 [[0123456789
63 ]])
65 AT_CLEANUP
68 ## ----------------------- ##
69 ## Typed midrule actions.  ##
70 ## ----------------------- ##
72 AT_SETUP([Typed midrule actions])
74 AT_BISON_OPTION_PUSHDEFS
75 AT_DATA_GRAMMAR([[input.y]],
76 [[%define parse.error verbose
77 %debug
78 %code {
79 ]AT_YYERROR_DECLARE[
80 ]AT_YYLEX_DECLARE[
82 %union {
83   int ival;
85 %type <ival> exp
87 exp:     <ival>{ $$ = 0; }
88      '1' <ival>{ $$ = 1; }
89      '2' <ival>{ $$ = 2; }
90      '3' <ival>{ $$ = 3; }
91      '4' <ival>{ $$ = 4; }
92      '5' <ival>{ $$ = 5; }
93      '6' <ival>{ $$ = 6; }
94      '7' <ival>{ $$ = 7; }
95      '8' <ival>{ $$ = 8; }
96      '9' <ival>{ $$ = 9; }  <ival>{ $$ = 10; }  <ival>{ $$ = 11; }
97   {
98     $$ = $1 + $3 + $5 + $7 + $9 + $11 + $13 + $15 + $17 + $19 + $20 + $21;
99     printf ("%d\n", $$);
100   }
103 ]AT_YYERROR_DEFINE[
104 ]AT_YYLEX_DEFINE(["123456789"])[
105 ]AT_MAIN_DEFINE[
107 AT_BISON_OPTION_POPDEFS
109 AT_BISON_CHECK([-d -v -o input.c input.y])
110 AT_COMPILE([input])
111 AT_PARSER_CHECK([input], 0,
112 [[66
115 AT_CLEANUP
118 ## ----------------------- ##
119 ## Implicitly empty rule.  ##
120 ## ----------------------- ##
122 AT_SETUP([Implicitly empty rule])
124 AT_BISON_OPTION_PUSHDEFS
125 AT_DATA_GRAMMAR([[1.y]],
126 [[%%
127 exp: a b;
128 a: /* empty. */ {};
129 // A midrule action does not count as an empty rule.
130 b: {} {};
133 AT_BISON_CHECK([-fcaret -Wempty-rule 1.y], [0], [],
134 [[1.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
135    11 | a: /* empty. */ {};
136       |                 ^~
137       |                 %empty
138 1.y: warning: fix-its can be applied.  Rerun with option '--update'. [-Wother]
141 AT_DATA_GRAMMAR([[2.y]],
142 [[%%
143 exp: a b c;
144 a: /* empty. */ {};
145 b: %empty       {};
146 c: /* empty. */ {};
149 AT_BISON_CHECK([-fcaret 2.y], [0], [],
150 [[2.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
151    11 | a: /* empty. */ {};
152       |                 ^~
153       |                 %empty
154 2.y:13.17-18: warning: empty rule without %empty [-Wempty-rule]
155    13 | c: /* empty. */ {};
156       |                 ^~
157       |                 %empty
158 2.y: warning: fix-its can be applied.  Rerun with option '--update'. [-Wother]
161 AT_BISON_CHECK([-fcaret -Wno-empty-rule 2.y], [0])
163 AT_BISON_OPTION_POPDEFS
164 AT_CLEANUP
168 ## ------------------------ ##
169 ## Invalid uses of %empty.  ##
170 ## ------------------------ ##
172 AT_SETUP([Invalid uses of %empty])
174 AT_BISON_OPTION_PUSHDEFS
175 AT_DATA_GRAMMAR([[one.y]],
176 [[%%
177 exp:
178   %empty {} %empty
182 AT_BISON_CHECK([-fcaret one.y], [1], [],
183 [[one.y:11.13-18: error: only one %empty allowed per rule
184    11 |   %empty {} %empty
185       |             ^~~~~~
186 one.y:11.3-8: note: previous declaration
187    11 |   %empty {} %empty
188       |   ^~~~~~
189 one.y: warning: fix-its can be applied.  Rerun with option '--update'. [-Wother]
192 AT_BISON_CHECK([-fcaret -u one.y], [1], [],
193 [[one.y:11.13-18: error: only one %empty allowed per rule
194    11 |   %empty {} %empty
195       |             ^~~~~~
196 one.y:11.3-8: note: previous declaration
197    11 |   %empty {} %empty
198       |   ^~~~~~
199 bison: file 'one.y' was updated (backup: 'one.y~')
202 AT_CHECK([sed -e '1,8d' one.y], [],
203 [[%%
204 exp:
205   %empty {} @&t@
210 AT_DATA_GRAMMAR([[two.y]],
211 [[%%
212 exp:
213   'a' %empty    {}
214 | %empty 'a'    {}
215 | %empty {}     {}
219 AT_BISON_CHECK([-fcaret two.y], [1], [],
220 [[two.y:11.7-12: error: %empty on non-empty rule
221    11 |   'a' %empty    {}
222       |       ^~~~~~
223 two.y:12.3-8: error: %empty on non-empty rule
224    12 | | %empty 'a'    {}
225       |   ^~~~~~
226 two.y:13.3-8: error: %empty on non-empty rule
227    13 | | %empty {}     {}
228       |   ^~~~~~
229 two.y: warning: fix-its can be applied.  Rerun with option '--update'. [-Wother]
232 AT_BISON_OPTION_POPDEFS
233 AT_CLEANUP
236 ## ---------------------- ##
237 ## Valid uses of %empty.  ##
238 ## ---------------------- ##
240 AT_SETUP([Valid uses of %empty])
242 AT_BISON_OPTION_PUSHDEFS
243 AT_DATA_GRAMMAR([[input.y]],
245 %debug
246 %code
248 ]AT_YYERROR_DECLARE[
249 ]AT_YYLEX_DECLARE[
252 exp: %empty {}
254 ]AT_YYERROR_DEFINE[
255 ]AT_YYLEX_DEFINE[
256 ]AT_MAIN_DEFINE[
259 AT_FULL_COMPILE([input])
260 AT_PARSER_CHECK([input])
261 AT_BISON_OPTION_POPDEFS
262 AT_CLEANUP
266 ## -------------------- ##
267 ## Add missing %empty.  ##
268 ## -------------------- ##
270 AT_SETUP([Add missing %empty])
272 AT_DATA([input.y],
273 [[%%
274 exp: a b c d e
275 a: {}
285 AT_BISON_CHECK([--update -Wall input.y], [], [], [ignore])
286 AT_CHECK([cat input.y], [],
287 [[%%
288 exp: a b c d e
289 a:  %empty {}
290 b: %empty {
292 c: %empty @&t@
294 : %empty @&t@
295 e: %empty @&t@
299 # No warnings.
300 AT_BISON_CHECK([-Wall input.y])
302 AT_CLEANUP
305 ## ------------------ ##
306 ## Initial location.  ##
307 ## ------------------ ##
309 # AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES], [LOCATION = 1.1])
310 # -----------------------------------------------------------------------
311 # Check that the initial location is correct.
312 m4_pushdef([AT_TEST],
313 [AT_SETUP([Initial location: $1 $2])
315 AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
316 AT_DATA_GRAMMAR([[input.y]],
317 [[%locations
318 %debug
319 %skeleton "$1"
320 ]$2[
321 ]$3[
322 %code
324 # include <stdio.h>
325 # include <stdlib.h> /* getenv */
326 ]AT_YYERROR_DECLARE[
327 ]AT_YYLEX_DECLARE[
330 exp: { ]AT_CXX_IF([[std::cerr << @$ << '\n']],
331                   [[LOCATION_PRINT(stderr, @$); fputc ('\n', stderr)]])[; }
333 ]AT_YYERROR_DEFINE[
335 ]AT_YYLEX_PROTOTYPE[
336 {]AT_PURE_IF([
337   YY_USE (lvalp);
338   YY_USE (llocp);], [AT_CXX_IF([
339   YY_USE (lvalp);
340   YY_USE (llocp);])])[
341   return 'x';
345 main (void)
346 {]AT_CXX_IF([[
347   yy::parser p;
348   p.set_debug_level (!!getenv ("YYDEBUG"));
349   return p.parse ();]], [[
350   yydebug = !!getenv ("YYDEBUG");
351   return !!yyparse (]AT_PARAM_IF([0])[);]])[
355 AT_FULL_COMPILE([input])
356 AT_PARSER_CHECK([input], 1, [],
357 [m4_default([$4], [1.1])
358 m4_default([$4], [1.1])[: syntax error
360 AT_BISON_OPTION_POPDEFS
361 AT_CLEANUP
364 ## FIXME: test Java, and iterate over skeletons.
365 AT_TEST([yacc.c])
366 AT_TEST([yacc.c], [%define api.pure full])
367 AT_TEST([yacc.c], [%define api.pure %parse-param { int x }])
368 AT_TEST([yacc.c], [%define api.push-pull both])
369 AT_TEST([yacc.c], [%define api.push-pull both %define api.pure full])
370 AT_TEST([glr.c])
371 AT_TEST([glr.c], [%define api.pure])
372 AT_TEST([lalr1.cc])
373 AT_TEST([glr.cc])
374 AT_TEST([glr2.cc])
376 ## A very different test, based on PostgreSQL's implementation of the
377 ## locations.  See
378 ## https://lists.gnu.org/r/bug-bison/2012-11/msg00023.html
380 ## Weirdly enough, to trigger the warning with GCC 4.7, we must not
381 ## use fprintf, so run the test twice: once to check the warning
382 ## (absence thereof), and another time to check the value.
383 AT_TEST([yacc.c], [%define api.pure full],
384 [[%{
385 # define YYLTYPE int
386 # define LOCATION_PRINT(Stream, Loc)      \
387    (void) (Loc)
388 # define YYLLOC_DEFAULT(Current, Rhs, N)    \
389   (Current) = ((Rhs)[N ? 1 : 0])
392 [@&t@])
394 AT_TEST([yacc.c], [%define api.pure full],
395 [[%{
396 # define YYLTYPE int
397 # define LOCATION_PRINT(Stream, Loc)      \
398     fprintf ((Stream), "%d", (Loc))
399 # define YYLLOC_DEFAULT(Current, Rhs, N)    \
400   (Current) = ((Rhs)[N ? 1 : 0])
403 [0])
406 m4_popdef([AT_TEST])
410 ## ---------------- ##
411 ## Location Print.  ##
412 ## ---------------- ##
414 # AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES])
415 # -----------------------------------------------------
416 # Check that the initial location is correct.
417 m4_pushdef([AT_TEST],
418 [AT_SETUP([Location print: $1 $2])
420 AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
421 AT_DATA_GRAMMAR([[input.y]],
422 [[%locations
423 %debug
424 %skeleton "$1"
425 ]$2[
426 ]$3[
427 %code
429 #include <stdio.h> /* putchar. */
430 ]AT_YYERROR_DECLARE[
431 ]AT_YYLEX_DECLARE[
434 exp: %empty;
436 ]AT_YYERROR_DEFINE[
437 ]AT_YYLEX_DEFINE[
440 main (void)
442   ]AT_YYLTYPE[ loc;
443 ]AT_GLR_CC_IF([loc.initialize();])[
444 #define TEST(L1, C1, L2, C2)          \
445   loc.]AT_FIRST_LINE[ = L1;           \
446   loc.]AT_FIRST_COLUMN[ = C1;         \
447   loc.]AT_LAST_LINE[ = L2;            \
448   loc.]AT_LAST_COLUMN[ = C2;          \
449   ]AT_CXX_IF([std::cout << loc],
450                  [LOCATION_PRINT(stdout, loc)])[;\
451   putchar ('\n');
453   TEST(1, 1, 1, 1);
454   TEST(2, 1, 2, 10);
455   TEST(3, 1, 4, 1);
456   TEST(5, 1, 6, 10);
458   TEST(7, 2, 0, 2);
459   TEST(8, 0, 8, 0);
460   return 0;
464 AT_FULL_COMPILE([input])
465 AT_PARSER_CHECK([input], 0,
466 [[1.1
467 2.1-9
468 3.1-4.0
469 5.1-6.9
473 AT_BISON_OPTION_POPDEFS
474 AT_CLEANUP
477 ## FIXME: test Java and D.
478 m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc])
480 m4_popdef([AT_TEST])
484 ## ---------------- ##
485 ## Exotic Dollars.  ##
486 ## ---------------- ##
488 AT_SETUP([Exotic Dollars])
490 AT_BISON_OPTION_PUSHDEFS
491 AT_DATA_GRAMMAR([[input.y]],
492 [[%define parse.error verbose
493 %debug
494 %code {
495 ]AT_YYERROR_DECLARE[
496 ]AT_YYLEX_DECLARE[
497 # define USE(Var)
500 %union
502   int val;
505 %type <val> a_1 a_2 a_5
506             sum_of_the_five_previous_values
509 exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
510      sum_of_the_five_previous_values
511     {
512        USE (($1, $2, $<foo>3, $<foo>4, $5));
513        printf ("%d\n", $6);
514     }
516 a_1: { $$ = 1; };
517 a_2: { $$ = 2; };
518 a_5: { $$ = 5; };
520 sum_of_the_five_previous_values:
521     {
522        $$ = $<val>0 + $<val>-1 + $<val>-2 + $<val>-3 + $<val>-4;
523     }
527 ]AT_YYERROR_DEFINE[
528 ]AT_YYLEX_DEFINE[
529 ]AT_MAIN_DEFINE[
532 AT_BISON_CHECK([-d -v -o input.c input.y], 0)
533 AT_COMPILE([input])
534 AT_PARSER_CHECK([input], 0,
535 [[15
538 # Make sure that fields after $n or $-n are parsed correctly.  At one
539 # point while implementing dashes in symbol names, we were dropping
540 # fields after $-n.
541 AT_DATA_GRAMMAR([[input.y]],
544 ]AT_YYERROR_DECLARE[
545 ]AT_YYLEX_DECLARE[
546   typedef struct { int val; } stype;
547 # define YYSTYPE stype
551 start: one two { $$.val = $1.val + $2.val; } sum ;
552 one: { $$.val = 1; } ;
553 two: { $$.val = 2; } ;
554 sum: { printf ("%d\n", $0.val + $-1.val + $-2.val); } ;
557 ]AT_YYERROR_DEFINE[
558 ]AT_YYLEX_DEFINE[
559 ]AT_MAIN_DEFINE[
562 AT_FULL_COMPILE([input])
563 AT_PARSER_CHECK([[input]], [[0]],
567 AT_BISON_OPTION_POPDEFS
568 AT_CLEANUP
572 ## -------------------------- ##
573 ## Printers and Destructors.  ##
574 ## -------------------------- ##
576 # _AT_CHECK_PRINTER_AND_DESTRUCTOR($1, $2, $3, $4,
577 #                                  BISON-DIRECTIVE, UNION-FLAG)
578 # -------------------------------------------------------------
579 m4_define([_AT_CHECK_PRINTER_AND_DESTRUCTOR],
580 [# Make sure complex $n work.
581 m4_if([$1$2$3$4], $[1]$[2]$[3]$[4], [],
582        [m4_fatal([$0: Invalid arguments: $@])])dnl
584 # Be sure to pass all the %directives to this macro to have correct
585 # helping macros.  So don't put any directly in the Bison file.
586 AT_BISON_OPTION_PUSHDEFS([$5])
587 AT_DATA_GRAMMAR([[input.y]],
588 [[%code requires {
589 #include <stdio.h>
590 #include <stdlib.h>
591 #include <string.h>
592 #include <assert.h>
594 #define YYINITDEPTH 10
595 #define YYMAXDEPTH 10
596 #define RANGE(Location) ]AT_CXX_IF([(Location).begin.line, (Location).end.line],
597       [(Location).first_line, (Location).last_line])[
599 #define USE(SYM)
601 /* Display the symbol type Symbol.  */
602 #define V(Symbol, Value, Location, Sep) \
603    fprintf (stderr, #Symbol " (%d@%d-%d)%s", Value, RANGE(Location), Sep)
607 ]m4_ifval([$6], [%union
609   int ival;
611 m4_ifval([$6], [[%code provides {]], [[%code {]])
612 AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])[
613 ]AT_YYLEX_DECLARE[
614 ]AT_LALR1_CC_IF([], [AT_YYERROR_DECLARE])
617 ]m4_ifval([$6],
618 [%type <ival> '(' 'x' 'y' ')' ';' thing line input
619               '!' raise check-spontaneous-errors END])[
621 /* FIXME: This %printer isn't actually tested.  */
622 %printer
623   {
624     ]AT_CXX_IF([yyo << $$;],
625                [fprintf (yyo, "%d", $$)])[;
626   }
627   '(' 'x' 'y' ')' ';' thing line input '!' raise check-spontaneous-errors END
629 %destructor
630   { fprintf (stderr, "Freeing nterm input (%d@%d-%d)\n", $$, RANGE (@$)); }
631   input
633 %destructor
634   { fprintf (stderr, "Freeing nterm line (%d@%d-%d)\n", $$, RANGE (@$)); }
635   line
637 %destructor
638   { fprintf (stderr, "Freeing nterm thing (%d@%d-%d)\n", $$, RANGE (@$)); }
639   thing
641 %destructor
642   { fprintf (stderr, "Freeing nterm raise (%d@%d-%d)\n", $$, RANGE (@$)); }
643   raise
645 %destructor
646   { fprintf (stderr, "Freeing nterm check-spontaneous-errors (%d@%d-%d)\n", $$, RANGE (@$)); }
647   check-spontaneous-errors
649 %destructor
650   { fprintf (stderr, "Freeing token 'x' (%d@%d-%d)\n", $$, RANGE (@$)); }
651   'x'
653 %destructor
654   { fprintf (stderr, "Freeing token 'y' (%d@%d-%d)\n", $$, RANGE (@$)); }
655   'y'
657 %token END 0
658 %destructor
659   { fprintf (stderr, "Freeing token END (%d@%d-%d)\n", $$, RANGE (@$)); }
660   END
664    This grammar is made to exercise error recovery.
665    "Lines" starting with '(' support error recovery, with
666    ')' as synchronizing token.  Lines starting with 'x' can never
667    be recovered from if in error.
670 input:
671   %empty
672     {
673       $$ = 0;
674       V(input, $$, @$, ": /* Nothing */\n");
675     }
676 | line input /* Right recursive to load the stack so that popping at
677                 END can be exercised.  */
678     {
679       $$ = 2;
680       V(input, $$, @$, ": ");
681       V(line,  $1, @1, " ");
682       V(input, $2, @2, "\n");
683     }
684 | '!' check-spontaneous-errors
685   {
686     $$ = $2;
687   }
690 check-spontaneous-errors:
691   raise         { abort(); USE(($$, $1)); }
692 | '(' raise ')' { abort(); USE(($$, $2)); }
693 | error
694   {
695     $$ = 5;
696     V(check-spontaneous-errors, $$, @$, ": ");
697     fprintf (stderr, "error (@%d-%d)\n", RANGE(@1));
698   }
701 raise:
702   %empty
703   {
704     $$ = 4;
705     V(raise, $$, @$, ": %empty\n");
706     YYERROR;
707   }
708 | '!' '!'
709   {
710     $$ = 5;
711     V(raise, $$, @$, ": ");
712     V(!, $1, @2, " ");
713     V(!, $2, @2, "\n");
714     YYERROR;
715   }
718 line:
719   thing thing thing ';'
720     {
721       $$ = $1;
722       V(line,  $$, @$, ": ");
723       V(thing, $1, @1, " ");
724       V(thing, $2, @2, " ");
725       V(thing, $3, @3, " ");
726       V(;,     $4, @4, "\n");
727     }
728 | '(' thing thing ')'
729     {
730       $$ = $1;
731       V(line,  $$, @$, ": ");
732       V('(',   $1, @1, " ");
733       V(thing, $2, @2, " ");
734       V(thing, $3, @3, " ");
735       V(')',   $4, @4, "\n");
736     }
737 | '(' thing ')'
738     {
739       $$ = $1;
740       V(line,  $$, @$, ": ");
741       V('(',   $1, @1, " ");
742       V(thing, $2, @2, " ");
743       V(')',   $3, @3, "\n");
744     }
745 | '(' error ')'
746     {
747       $$ = -1;
748       V(line,  $$, @$, ": ");
749       V('(',   $1, @1, " ");
750       fprintf (stderr, "error (@%d-%d) ", RANGE(@2));
751       V(')',   $3, @3, "\n");
752     }
755 thing:
756   'x'
757     {
758       $$ = $1;
759       V(thing, $$, @$, ": ");
760       V('x',   $1, @1, "\n");
761     }
764 /* Alias to ARGV[1]. */
765 const char *source = YY_NULLPTR;
767 ]AT_YYERROR_DEFINE[
769 static
770 ]AT_YYLEX_PROTOTYPE[
772   static int counter = 0;
774   int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++;
775   assert (c <= YY_CAST (int, strlen (source)));
776   /* As in BASIC, line numbers go from 10 to 10.  */
777   ]AT_LOC_FIRST_LINE[ = ]AT_LOC_FIRST_COLUMN[ = (10 * c);
778   ]AT_LOC_LAST_LINE[ = ]AT_LOC_LAST_COLUMN[ = ]AT_LOC_FIRST_LINE[ + 9;
779   if (source[c])
780     fprintf (stderr, "sending: '%c'", source[c]);
781   else
782     fprintf (stderr, "sending: END");
783   fprintf (stderr, " (%d@%d-%d)\n", c, RANGE (]AT_LOC[));
784   return source[c];
786 ]AT_LALR1_CC_IF([static bool yydebug;])[
787 ]AT_CXX_IF([int
788 yyparse ()
790   yy::parser parser;
791   parser.set_debug_level (yydebug);
792   return parser.parse ();
797 main (int argc, const char *argv[])
799   int status;
800   yydebug = !!getenv ("YYDEBUG");
801   assert (argc == 2); (void) argc;
802   source = argv[1];
803   status = yyparse ();
804   switch (status)
805     {
806       case 0: fprintf (stderr, "Successful parse.\n"); break;
807       case 1: fprintf (stderr, "Parsing FAILED.\n"); break;
808       default: fprintf (stderr, "Parsing FAILED (status %d).\n", status); break;
809     }
810   return status;
814 AT_FULL_COMPILE([input])
817 # Check the location of "empty"
818 # -----------------------------
819 # I.e., epsilon-reductions, as in "(x)" which ends by reducing
820 # an empty "line" nterm.
821 # FIXME: This location is not satisfying.  Depend on the lookahead?
822 AT_PARSER_CHECK([input '(x)'], 0, [],
823 [[sending: '(' (0@0-9)
824 sending: 'x' (1@10-19)
825 thing (1@10-19): 'x' (1@10-19)
826 sending: ')' (2@20-29)
827 line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
828 sending: END (3@30-39)
829 input (0@29-29): /* Nothing */
830 input (2@0-29): line (0@0-29) input (0@29-29)
831 Freeing token END (3@30-39)
832 Freeing nterm input (2@0-29)
833 Successful parse.
836 # Check the location of empty reductions raising an error
837 # -------------------------------------------------------
838 # Here, the error is after token "!@0-9", so the error is raised from
839 # @9-9, and the error recovery detects that it starts from @9-9 and
840 # ends where starts the next token: END@10-19.
842 # So error recovery reports error@9-19.
843 AT_PARSER_CHECK([input '!'], 0, [],
844 [[sending: '!' (0@0-9)
845 sending: END (1@10-19)
846 raise (4@9-9): %empty
847 check-spontaneous-errors (5@9-19): error (@9-19)
848 Freeing token END (1@10-19)
849 Freeing nterm input (5@0-19)
850 Successful parse.
853 # Check the location of not empty reductions raising an error
854 # -----------------------------------------------------------
855 # This time the error is raised from a rule with 2 rhs symbols: @10-29.
856 # It is recovered @10-29.
857 AT_PARSER_CHECK([[input '!!!']], 0, [],
858 [[sending: '!' (0@0-9)
859 sending: '!' (1@10-19)
860 sending: '!' (2@20-29)
861 raise (5@10-29): ! (1@20-29) ! (2@20-29)
862 check-spontaneous-errors (5@10-29): error (@10-29)
863 sending: END (3@30-39)
864 Freeing token END (3@30-39)
865 Freeing nterm input (5@0-29)
866 Successful parse.
869 # Check locations in error recovery
870 # ---------------------------------
871 # '(y)' is an error, but can be recovered from.  But what's the location
872 # of the error itself ('y'), and of the resulting reduction ('(error)').
873 AT_PARSER_CHECK([input '(y)'], 0, [],
874 [[sending: '(' (0@0-9)
875 sending: 'y' (1@10-19)
876 10.10-19.18: syntax error, unexpected 'y', expecting 'x'
877 Freeing token 'y' (1@10-19)
878 sending: ')' (2@20-29)
879 line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
880 sending: END (3@30-39)
881 input (0@29-29): /* Nothing */
882 input (2@0-29): line (-1@0-29) input (0@29-29)
883 Freeing token END (3@30-39)
884 Freeing nterm input (2@0-29)
885 Successful parse.
889 # Syntax errors caught by the parser
890 # ----------------------------------
891 # Exercise the discarding of stack top and input until 'error'
892 # can be reduced.
894 #     '(', 'x', 'x', 'x', 'x', 'x', ')',
896 # Load the stack and provoke an error that cannot be caught by the
897 # grammar, to check that the stack is cleared.  And make sure the
898 # lookahead is freed.
900 #     '(', 'x', ')',
901 #     '(', 'x', ')',
902 #     'y'
903 AT_PARSER_CHECK([input '(xxxxx)(x)(x)y'], 1, [],
904 [[sending: '(' (0@0-9)
905 sending: 'x' (1@10-19)
906 thing (1@10-19): 'x' (1@10-19)
907 sending: 'x' (2@20-29)
908 thing (2@20-29): 'x' (2@20-29)
909 sending: 'x' (3@30-39)
910 30.30-39.38: syntax error, unexpected 'x', expecting ')'
911 Freeing nterm thing (2@20-29)
912 Freeing nterm thing (1@10-19)
913 Freeing token 'x' (3@30-39)
914 sending: 'x' (4@40-49)
915 Freeing token 'x' (4@40-49)
916 sending: 'x' (5@50-59)
917 Freeing token 'x' (5@50-59)
918 sending: ')' (6@60-69)
919 line (-1@0-69): '(' (0@0-9) error (@10-59) ')' (6@60-69)
920 sending: '(' (7@70-79)
921 sending: 'x' (8@80-89)
922 thing (8@80-89): 'x' (8@80-89)
923 sending: ')' (9@90-99)
924 line (7@70-99): '(' (7@70-79) thing (8@80-89) ')' (9@90-99)
925 sending: '(' (10@100-109)
926 sending: 'x' (11@110-119)
927 thing (11@110-119): 'x' (11@110-119)
928 sending: ')' (12@120-129)
929 line (10@100-129): '(' (10@100-109) thing (11@110-119) ')' (12@120-129)
930 sending: 'y' (13@130-139)
931 input (0@129-129): /* Nothing */
932 input (2@100-129): line (10@100-129) input (0@129-129)
933 input (2@70-129): line (7@70-99) input (2@100-129)
934 input (2@0-129): line (-1@0-69) input (2@70-129)
935 130.130-139.138: syntax error, unexpected 'y', expecting END
936 Freeing nterm input (2@0-129)
937 Freeing token 'y' (13@130-139)
938 Parsing FAILED.
942 # Syntax error caught by the parser where lookahead = END
943 # --------------------------------------------------------
944 # Load the stack and provoke an error that cannot be caught by the
945 # grammar, to check that the stack is cleared.  And make sure the
946 # lookahead is freed.
948 #     '(', 'x', ')',
949 #     '(', 'x', ')',
950 #     'x'
951 AT_PARSER_CHECK([input '(x)(x)x'], 1, [],
952 [[sending: '(' (0@0-9)
953 sending: 'x' (1@10-19)
954 thing (1@10-19): 'x' (1@10-19)
955 sending: ')' (2@20-29)
956 line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
957 sending: '(' (3@30-39)
958 sending: 'x' (4@40-49)
959 thing (4@40-49): 'x' (4@40-49)
960 sending: ')' (5@50-59)
961 line (3@30-59): '(' (3@30-39) thing (4@40-49) ')' (5@50-59)
962 sending: 'x' (6@60-69)
963 thing (6@60-69): 'x' (6@60-69)
964 sending: END (7@70-79)
965 70.70-79.78: syntax error, unexpected END, expecting 'x'
966 Freeing nterm thing (6@60-69)
967 Freeing nterm line (3@30-59)
968 Freeing nterm line (0@0-29)
969 Freeing token END (7@70-79)
970 Parsing FAILED.
974 # Check destruction upon stack overflow
975 # -------------------------------------
976 # Upon stack overflow, all symbols on the stack should be destroyed.
977 # Only check for yacc.c.
978 AT_YACC_C_IF([
979 AT_PARSER_CHECK([input '(x)(x)(x)(x)(x)(x)(x)'], 2, [],
980 [[sending: '(' (0@0-9)
981 sending: 'x' (1@10-19)
982 thing (1@10-19): 'x' (1@10-19)
983 sending: ')' (2@20-29)
984 line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
985 sending: '(' (3@30-39)
986 sending: 'x' (4@40-49)
987 thing (4@40-49): 'x' (4@40-49)
988 sending: ')' (5@50-59)
989 line (3@30-59): '(' (3@30-39) thing (4@40-49) ')' (5@50-59)
990 sending: '(' (6@60-69)
991 sending: 'x' (7@70-79)
992 thing (7@70-79): 'x' (7@70-79)
993 sending: ')' (8@80-89)
994 line (6@60-89): '(' (6@60-69) thing (7@70-79) ')' (8@80-89)
995 sending: '(' (9@90-99)
996 sending: 'x' (10@100-109)
997 thing (10@100-109): 'x' (10@100-109)
998 sending: ')' (11@110-119)
999 line (9@90-119): '(' (9@90-99) thing (10@100-109) ')' (11@110-119)
1000 sending: '(' (12@120-129)
1001 sending: 'x' (13@130-139)
1002 thing (13@130-139): 'x' (13@130-139)
1003 sending: ')' (14@140-149)
1004 line (12@120-149): '(' (12@120-129) thing (13@130-139) ')' (14@140-149)
1005 sending: '(' (15@150-159)
1006 sending: 'x' (16@160-169)
1007 thing (16@160-169): 'x' (16@160-169)
1008 sending: ')' (17@170-179)
1009 line (15@150-179): '(' (15@150-159) thing (16@160-169) ')' (17@170-179)
1010 sending: '(' (18@180-189)
1011 sending: 'x' (19@190-199)
1012 thing (19@190-199): 'x' (19@190-199)
1013 sending: ')' (20@200-209)
1014 200.200-209.208: memory exhausted
1015 Freeing nterm thing (19@190-199)
1016 Freeing nterm line (15@150-179)
1017 Freeing nterm line (12@120-149)
1018 Freeing nterm line (9@90-119)
1019 Freeing nterm line (6@60-89)
1020 Freeing nterm line (3@30-59)
1021 Freeing nterm line (0@0-29)
1022 Parsing FAILED (status 2).
1026 AT_BISON_OPTION_POPDEFS
1027 ])# _AT_CHECK_PRINTER_AND_DESTRUCTOR
1030 # AT_CHECK_PRINTER_AND_DESTRUCTOR([BISON-OPTIONS], [UNION-FLAG], [SKIP_FLAG])
1031 # ---------------------------------------------------------------------------
1032 m4_define([AT_CHECK_PRINTER_AND_DESTRUCTOR],
1033 [AT_SETUP([Printers and Destructors$2]m4_ifval([$1], [[: $1]]))
1036 _AT_CHECK_PRINTER_AND_DESTRUCTOR($[1], $[2], $[3], $[4],
1037 [%define parse.error verbose
1038 %debug
1039 %verbose
1040 %locations
1041 $1], [$2])
1043 AT_CLEANUP
1047 AT_CHECK_PRINTER_AND_DESTRUCTOR([])
1048 AT_CHECK_PRINTER_AND_DESTRUCTOR([], [ with union])
1050 AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser])
1051 AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [ with union])
1053 AT_CHECK_PRINTER_AND_DESTRUCTOR([%header %skeleton "lalr1.cc"])
1054 AT_CHECK_PRINTER_AND_DESTRUCTOR([%header %skeleton "lalr1.cc"], [ with union])
1056 AT_CHECK_PRINTER_AND_DESTRUCTOR([%header %skeleton "glr.cc"])
1057 AT_CHECK_PRINTER_AND_DESTRUCTOR([%header %skeleton "glr.cc"], [ with union])
1059 AT_CHECK_PRINTER_AND_DESTRUCTOR([%header %skeleton "glr2.cc"])
1060 AT_CHECK_PRINTER_AND_DESTRUCTOR([%header %skeleton "glr2.cc"], [ with union])
1064 ## ----------------------------------------- ##
1065 ## Default tagless %printer and %destructor. ##
1066 ## ----------------------------------------- ##
1068 # Check that the right %printer and %destructor are called, that they're not
1069 # called for $end, and that $$ and @$ work correctly.
1071 AT_SETUP([Default tagless %printer and %destructor])
1072 AT_BISON_OPTION_PUSHDEFS([%locations %debug])
1073 AT_DATA_GRAMMAR([[input.y]],
1074 [[%define parse.error verbose
1075 %debug
1076 %locations
1078 %code {
1079 ]AT_YYLEX_DECLARE[
1080 ]AT_YYERROR_DECLARE[
1081 # define USE(SYM)
1084 %printer {
1085   #error "<*> printer should not be used."
1086 } <*>
1088 %printer {
1089   fprintf (yyo, "<> printer for '%c' @ %d", $$, @$.first_column);
1090 } <>
1091 %destructor {
1092   printf ("<> destructor for '%c' @ %d.\n", $$, @$.first_column);
1093 } <>
1095 %printer {
1096   fprintf (yyo, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
1097 } 'b' 'c'
1098 %destructor {
1099   printf ("'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column);
1100 } 'b' 'c'
1102 %destructor {
1103   #error "<*> destructor should not be used."
1104 } <*>
1108 start: 'a' 'b' 'c' 'd' 'e' { $$ = 'S'; USE(($1, $2, $3, $4, $5)); } ;
1111 ]AT_YYERROR_DEFINE[
1112 ]AT_YYLEX_DEFINE(["abcd"], [[yylval = res]])[
1113 ]AT_MAIN_DEFINE[
1116 AT_BISON_CHECK([-o input.c input.y], [], [],
1117 [[input.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
1118 input.y:30.3-5: warning: useless %printer for type <*> [-Wother]
1120 AT_COMPILE([input])
1121 AT_PARSER_CHECK([input --debug], 1,
1122 [[<> destructor for 'd' @ 4.
1123 'b'/'c' destructor for 'c' @ 3.
1124 'b'/'c' destructor for 'b' @ 2.
1125 <> destructor for 'a' @ 1.
1127 [[Starting parse
1128 Entering state 0
1129 Stack now 0
1130 Reading a token
1131 Next token is token 'a' (1.1: <> printer for 'a' @ 1)
1132 Shifting token 'a' (1.1: <> printer for 'a' @ 1)
1133 Entering state 1
1134 Stack now 0 1
1135 Reading a token
1136 Next token is token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
1137 Shifting token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
1138 Entering state 3
1139 Stack now 0 1 3
1140 Reading a token
1141 Next token is token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
1142 Shifting token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
1143 Entering state 5
1144 Stack now 0 1 3 5
1145 Reading a token
1146 Next token is token 'd' (1.4: <> printer for 'd' @ 4)
1147 Shifting token 'd' (1.4: <> printer for 'd' @ 4)
1148 Entering state 6
1149 Stack now 0 1 3 5 6
1150 Reading a token
1151 Now at end of input.
1152 1.5: syntax error, unexpected end of file, expecting 'e'
1153 Error: popping token 'd' (1.4: <> printer for 'd' @ 4)
1154 Stack now 0 1 3 5
1155 Error: popping token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
1156 Stack now 0 1 3
1157 Error: popping token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
1158 Stack now 0 1
1159 Error: popping token 'a' (1.1: <> printer for 'a' @ 1)
1160 Stack now 0
1161 Cleanup: discarding lookahead token "end of file" (1.5: )
1162 Stack now 0
1165 AT_BISON_OPTION_POPDEFS
1166 AT_CLEANUP
1170 ## ------------------------------------------------------ ##
1171 ## Default tagged and per-type %printer and %destructor.  ##
1172 ## ------------------------------------------------------ ##
1174 AT_SETUP([Default tagged and per-type %printer and %destructor])
1175 AT_BISON_OPTION_PUSHDEFS([%debug])
1176 AT_DATA_GRAMMAR([[input.y]],
1177 [[%define parse.error verbose
1178 %debug
1181 ]AT_YYERROR_DECLARE[
1182 ]AT_YYLEX_DECLARE[
1183 # define USE(SYM)
1186 %printer {
1187   #error "<> printer should not be used."
1188 } <>
1190 %union { int field0; int field1; int field2; }
1191 %type <field0> start 'a' 'g'
1192 %type <field1> 'e'
1193 %type <field2> 'f'
1194 %printer {
1195   fprintf (yyo, "<*>/<field2>/e printer");
1196 } <*> 'e' <field2>
1197 %destructor {
1198   printf ("<*>/<field2>/e destructor.\n");
1199 } <*> 'e' <field2>
1201 %type <field1> 'b'
1202 %printer { fprintf (yyo, "<field1> printer"); } <field1>
1203 %destructor { printf ("<field1> destructor.\n"); } <field1>
1205 %type <field0> 'c'
1206 %printer { fprintf (yyo, "'c' printer"); } 'c'
1207 %destructor { printf ("'c' destructor.\n"); } 'c'
1209 %type <field1> 'd'
1210 %printer { fprintf (yyo, "'d' printer"); } 'd'
1211 %destructor { printf ("'d' destructor.\n"); } 'd'
1213 %destructor {
1214   #error "<> destructor should not be used."
1215 } <>
1219 start:
1220   'a' 'b' 'c' 'd' 'e' 'f' 'g'
1221     {
1222       USE(($1, $2, $3, $4, $5, $6, $7));
1223       $$ = 'S';
1224     }
1225   ;
1228 ]AT_YYERROR_DEFINE[
1229 ]AT_YYLEX_DEFINE(["abcdef"])[
1230 ]AT_MAIN_DEFINE[
1233 AT_BISON_CHECK([-o input.c input.y], [], [],
1234 [[input.y:22.3-4: warning: useless %destructor for type <> [-Wother]
1235 input.y:22.3-4: warning: useless %printer for type <> [-Wother]
1237 AT_COMPILE([input])
1238 AT_PARSER_CHECK([input --debug], 1,
1239 [[<*>/<field2>/e destructor.
1240 <*>/<field2>/e destructor.
1241 'd' destructor.
1242 'c' destructor.
1243 <field1> destructor.
1244 <*>/<field2>/e destructor.
1246 [[Starting parse
1247 Entering state 0
1248 Stack now 0
1249 Reading a token
1250 Next token is token 'a' (<*>/<field2>/e printer)
1251 Shifting token 'a' (<*>/<field2>/e printer)
1252 Entering state 1
1253 Stack now 0 1
1254 Reading a token
1255 Next token is token 'b' (<field1> printer)
1256 Shifting token 'b' (<field1> printer)
1257 Entering state 3
1258 Stack now 0 1 3
1259 Reading a token
1260 Next token is token 'c' ('c' printer)
1261 Shifting token 'c' ('c' printer)
1262 Entering state 5
1263 Stack now 0 1 3 5
1264 Reading a token
1265 Next token is token 'd' ('d' printer)
1266 Shifting token 'd' ('d' printer)
1267 Entering state 6
1268 Stack now 0 1 3 5 6
1269 Reading a token
1270 Next token is token 'e' (<*>/<field2>/e printer)
1271 Shifting token 'e' (<*>/<field2>/e printer)
1272 Entering state 7
1273 Stack now 0 1 3 5 6 7
1274 Reading a token
1275 Next token is token 'f' (<*>/<field2>/e printer)
1276 Shifting token 'f' (<*>/<field2>/e printer)
1277 Entering state 8
1278 Stack now 0 1 3 5 6 7 8
1279 Reading a token
1280 Now at end of input.
1281 syntax error, unexpected end of file, expecting 'g'
1282 Error: popping token 'f' (<*>/<field2>/e printer)
1283 Stack now 0 1 3 5 6 7
1284 Error: popping token 'e' (<*>/<field2>/e printer)
1285 Stack now 0 1 3 5 6
1286 Error: popping token 'd' ('d' printer)
1287 Stack now 0 1 3 5
1288 Error: popping token 'c' ('c' printer)
1289 Stack now 0 1 3
1290 Error: popping token 'b' (<field1> printer)
1291 Stack now 0 1
1292 Error: popping token 'a' (<*>/<field2>/e printer)
1293 Stack now 0
1294 Cleanup: discarding lookahead token "end of file" ()
1295 Stack now 0
1298 AT_BISON_OPTION_POPDEFS
1299 AT_CLEANUP
1303 ## ------------------------------------------------------------- ##
1304 ## Default %printer and %destructor for user-defined end token.  ##
1305 ## ------------------------------------------------------------- ##
1307 AT_SETUP([Default %printer and %destructor for user-defined end token])
1309 # Enable declaration of default %printer/%destructor.  Make the parser
1310 # use these for all user-declared grammar symbols for which the user
1311 # does not declare a specific %printer/%destructor.  Thus, the parser
1312 # uses it for token 0 if the user declares it but not if Bison
1313 # generates it as $end.  Discussed starting at
1314 # <https://lists.gnu.org/r/bison-patches/2006-02/msg00064.html>,
1315 # <https://lists.gnu.org/r/bison-patches/2006-06/msg00091.html>, and
1316 # <https://lists.gnu.org/r/bison-patches/2006-07/msg00019.html>.
1318 # AT_TEST(TYPED)
1319 # --------------
1320 m4_pushdef([AT_TEST],
1321 [m4_if($1, 0,
1322   [m4_pushdef([kind], []) m4_pushdef([not_kind], [*])],
1323   [m4_pushdef([kind], [*]) m4_pushdef([not_kind], [])])
1325 AT_BISON_OPTION_PUSHDEFS([%locations %debug])
1326 AT_DATA_GRAMMAR([[input]]$1[[.y]],
1327 [[%define parse.error verbose
1328 %debug
1329 %locations
1331 %code {
1332 ]AT_YYERROR_DECLARE[
1333 ]AT_YYLEX_DECLARE[
1334 # define USE(SYM)
1337 %destructor {
1338   #error "<]]not_kind[[> destructor should not be used."
1339 } <]]not_kind[[>
1341 %token END 0
1342 %printer {
1343   fprintf (yyo, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
1344 } <]]kind[[>
1345 %destructor {
1346   printf ("<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column);
1347 } <]]kind[[>
1349 %printer {
1350   #error "<]]not_kind[[> printer should not be used."
1351 } <]]not_kind[[>
1353 ]]m4_if($1, 0, [[[
1354 ]]],
1355 [[[%union { char tag; }
1356 %type <tag> start END]]])[[
1360 start: { $$ = 'S'; } ;
1363 #include <stdlib.h> /* abort */
1364 static int
1365 yylex (void)
1367   static int called;
1368   if (called++)
1369     abort ();
1370   yylval]]m4_if($1, 0,, [[[.tag]]])[[ = 'E';
1371   yylloc.first_line = yylloc.last_line = 1;
1372   yylloc.first_column = yylloc.last_column = 1;
1373   return 0;
1375 ]AT_YYERROR_DEFINE[
1376 ]AT_MAIN_DEFINE[
1378 AT_BISON_OPTION_POPDEFS
1380 AT_BISON_CHECK([-o input$1.c input$1.y], [], [],
1381 [m4_if([$1], [0],
1382 [[input0.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
1383 input0.y:30.3-5: warning: useless %printer for type <*> [-Wother]
1385 [[input1.y:30.3-4: warning: useless %destructor for type <> [-Wother]
1386 input1.y:30.3-4: warning: useless %printer for type <> [-Wother]
1387 ]])])
1389 AT_COMPILE([input$1])
1391 AT_PARSER_CHECK([input$1 --debug], 0,
1392 [[<]]kind[[> for 'E' @ 1.
1393 <]]kind[[> for 'S' @ 1.
1395 [[Starting parse
1396 Entering state 0
1397 Stack now 0
1398 Reducing stack by rule 1 (line 49):
1399 -> $$ = nterm start (1.1: <]]kind[[> for 'S' @ 1)
1400 Entering state 1
1401 Stack now 0 1
1402 Reading a token
1403 Now at end of input.
1404 Shifting token END (1.1: <]]kind[[> for 'E' @ 1)
1405 Entering state 2
1406 Stack now 0 1 2
1407 Stack now 0 1 2
1408 Cleanup: popping token END (1.1: <]]kind[[> for 'E' @ 1)
1409 Cleanup: popping nterm start (1.1: <]]kind[[> for 'S' @ 1)
1412 m4_popdef([kind])
1413 m4_popdef([not_kind])
1416 AT_TEST(0)
1417 AT_TEST(1)
1419 m4_popdef([AT_TEST])
1421 AT_CLEANUP
1425 ## ------------------------------------------------------------------ ##
1426 ## Default %printer and %destructor are not for error or $undefined.  ##
1427 ## ------------------------------------------------------------------ ##
1429 AT_SETUP([Default %printer and %destructor are not for error or $undefined])
1431 # If Bison were to apply the default %printer and %destructor to the error
1432 # token or to $undefined:
1433 #   - For the error token:
1434 #     - It would generate warnings for unused $n.
1435 #     - It would invoke the %printer and %destructor on the error token's
1436 #       semantic value, which would be initialized from the lookahead, which
1437 #       would be destroyed separately.
1438 #   - For $undefined, who knows what the semantic value would be.
1439 AT_BISON_OPTION_PUSHDEFS([%debug])
1440 AT_DATA_GRAMMAR([[input.y]],
1441 [[%debug
1444 # include <stdio.h>
1445 # include <stdlib.h>
1446 ]AT_YYERROR_DECLARE[
1447 ]AT_YYLEX_DECLARE[
1448 # define USE(SYM)
1451 %printer {
1452   fprintf (yyo, "'%c'", $$);
1453 } <> <*>
1454 %destructor {
1455   fprintf (stderr, "DESTROY '%c'\n", $$);
1456 } <> <*>
1460 start:
1461   { $$ = 'S'; }
1462   /* In order to reveal the problems that this bug caused during parsing, add
1463    * $2 to USE.  */
1464   | 'a' error 'b' 'c' { USE(($1, $3, $4)); $$ = 'S'; }
1465   ;
1468 ]AT_YYERROR_DEFINE[
1469 ]AT_YYLEX_DEFINE(["abd"], [yylval = res])[
1470 ]AT_MAIN_DEFINE[
1472 AT_BISON_OPTION_POPDEFS
1474 AT_BISON_CHECK([-o input.c input.y], [], [],
1475 [[input.y:23.6-8: warning: useless %destructor for type <*> [-Wother]
1476 input.y:23.6-8: warning: useless %printer for type <*> [-Wother]
1478 AT_COMPILE([input])
1479 AT_PARSER_CHECK([input --debug], [1], [],
1480 [[Starting parse
1481 Entering state 0
1482 Stack now 0
1483 Reading a token
1484 Next token is token 'a' ('a')
1485 Shifting token 'a' ('a')
1486 Entering state 1
1487 Stack now 0 1
1488 Reading a token
1489 Next token is token 'b' ('b')
1490 syntax error
1491 Shifting token error ()
1492 Entering state 3
1493 Stack now 0 1 3
1494 Next token is token 'b' ('b')
1495 Shifting token 'b' ('b')
1496 Entering state 5
1497 Stack now 0 1 3 5
1498 Reading a token
1499 Next token is token "invalid token" ()
1500 Error: popping token 'b' ('b')
1501 DESTROY 'b'
1502 Stack now 0 1 3
1503 Error: popping token error ()
1504 Stack now 0 1
1505 Shifting token error ()
1506 Entering state 3
1507 Stack now 0 1 3
1508 Next token is token "invalid token" ()
1509 Error: discarding token "invalid token" ()
1510 Error: popping token error ()
1511 Stack now 0 1
1512 Shifting token error ()
1513 Entering state 3
1514 Stack now 0 1 3
1515 Reading a token
1516 Now at end of input.
1517 Cleanup: discarding lookahead token "end of file" ()
1518 Stack now 0 1 3
1519 Cleanup: popping token error ()
1520 Cleanup: popping token 'a' ('a')
1521 DESTROY 'a'
1524 AT_CLEANUP
1528 ## ------------------------------------------------------ ##
1529 ## Default %printer and %destructor are not for $accept.  ##
1530 ## ------------------------------------------------------ ##
1532 AT_SETUP([Default %printer and %destructor are not for $accept])
1534 # If YYSTYPE is a union and Bison were to apply the default %printer and
1535 # %destructor to $accept:
1536 #   - The %printer and %destructor code generated for $accept would always be
1537 #     dead code because $accept is currently never shifted onto the stack.
1538 #   - $$ for $accept would always be of type YYSTYPE because it's not possible
1539 #     to declare '%type <field> $accept'.  (Also true for $undefined.)
1540 #   - Thus, the compiler might complain that the user code assumes the wrong
1541 #     type for $$ since the code might assume the type associated with a
1542 #     specific union field, which is especially reasonable in C++ since that
1543 #     type may be a base type.  This test case checks for this problem.  (Also
1544 #     true for $undefined and the error token, so there are three warnings for
1545 #     %printer and three for %destructor.)
1547 AT_BISON_OPTION_PUSHDEFS([%debug])
1548 AT_DATA_GRAMMAR([[input.y]],
1549 [[%debug /* So that %printer is actually compiled.  */
1552 # include <stdio.h>
1553 # include <stdlib.h>
1554 ]AT_YYERROR_DECLARE[
1555 ]AT_YYLEX_DECLARE[
1556 # define USE(SYM)
1559 %printer {
1560   char chr = $$;
1561   fprintf (yyo, "'%c'", chr);
1562 } <> <*>
1563 %destructor {
1564   char chr = $$;
1565   fprintf (stderr, "DESTROY '%c'\n", chr);
1566 } <> <*>
1568 %union { char chr; }
1569 %type <chr> start
1573 start: { USE($$); } ;
1576 ]AT_YYERROR_DEFINE[
1577 ]AT_YYLEX_DEFINE[
1578 ]AT_MAIN_DEFINE[
1580 AT_BISON_OPTION_POPDEFS
1582 AT_BISON_CHECK([-o input.c input.y], [], [],
1583 [[input.y:24.3-4: warning: useless %destructor for type <> [-Wother]
1584 input.y:24.3-4: warning: useless %printer for type <> [-Wother]
1586 AT_COMPILE([input])
1588 AT_CLEANUP
1592 ## ----------------------------------------------------- ##
1593 ## Default %printer and %destructor for midrule values.  ##
1594 ## ----------------------------------------------------- ##
1596 AT_SETUP([Default %printer and %destructor for midrule values])
1598 AT_BISON_OPTION_PUSHDEFS([%debug])
1599 AT_DATA_GRAMMAR([[input.y]],
1600 [[%debug /* So that %printer is actually compiled.  */
1603 ]AT_YYERROR_DECLARE[
1604 ]AT_YYLEX_DECLARE[
1605 # define USE(SYM)
1606 # define YYLTYPE int
1607 # define YYLLOC_DEFAULT(Current, Rhs, N) (void)(Rhs)
1608 # define LOCATION_PRINT(File, Loc)
1611 %printer    { fprintf (yyo, "%d", @$); } <>
1612 %destructor { fprintf (stderr, "DESTROY %d\n", @$); } <>
1613 %printer    { #error "<*> printer should not be used" } <*>
1614 %destructor { #error "<*> destructor should not be used" } <*>
1618 start:
1619   {           @$ = 1; } // Not set or used.
1620   { USE ($$); @$ = 2; } // Both set and used.
1621   { USE ($$); @$ = 3; } // Only set.
1622   {           @$ = 4; } // Only used.
1623   'c'
1624   { USE (($$, $2, $4, $5)); @$ = 0; }
1625   ;
1628 ]AT_YYERROR_DEFINE[
1629 ]AT_YYLEX_DEFINE[
1630 ]AT_MAIN_DEFINE[
1632 AT_BISON_OPTION_POPDEFS
1634 AT_BISON_CHECK([-o input.c input.y], 0,,
1635 [[input.y:24.57-59: warning: useless %destructor for type <*> [-Wother]
1636 input.y:24.57-59: warning: useless %printer for type <*> [-Wother]
1637 input.y:33.3-23: warning: unset value: $$ [-Wother]
1638 input.y:32.3-23: warning: unused value: $3 [-Wother]
1641 AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
1642 [[input.y:24.57-59: warning: useless %destructor for type <*> [-Wother]
1643    24 | %printer    { #error "<*> printer should not be used" } <*>
1644       |                                                         ^~~
1645 input.y:24.57-59: warning: useless %printer for type <*> [-Wother]
1646    24 | %printer    { #error "<*> printer should not be used" } <*>
1647       |                                                         ^~~
1648 input.y:33.3-23: warning: unset value: $$ [-Wother]
1649    33 |   {           @$ = 4; } // Only used.
1650       |   ^~~~~~~~~~~~~~~~~~~~~
1651 input.y:32.3-23: warning: unused value: $3 [-Wother]
1652    32 |   { USE ($$); @$ = 3; } // Only set.
1653       |   ^~~~~~~~~~~~~~~~~~~~~
1656 AT_COMPILE([input])
1657 AT_PARSER_CHECK([input --debug], 1,,
1658 [[Starting parse
1659 Entering state 0
1660 Stack now 0
1661 Reducing stack by rule 1 (line 30):
1662 -> $$ = nterm $@1 (: )
1663 Entering state 2
1664 Stack now 0 2
1665 Reducing stack by rule 2 (line 31):
1666 -> $$ = nterm @2 (: 2)
1667 Entering state 4
1668 Stack now 0 2 4
1669 Reducing stack by rule 3 (line 32):
1670 -> $$ = nterm @3 (: 3)
1671 Entering state 5
1672 Stack now 0 2 4 5
1673 Reducing stack by rule 4 (line 33):
1674 -> $$ = nterm @4 (: 4)
1675 Entering state 6
1676 Stack now 0 2 4 5 6
1677 Reading a token
1678 Now at end of input.
1679 syntax error
1680 Error: popping nterm @4 (: 4)
1681 DESTROY 4
1682 Stack now 0 2 4 5
1683 Error: popping nterm @3 (: 3)
1684 DESTROY 3
1685 Stack now 0 2 4
1686 Error: popping nterm @2 (: 2)
1687 DESTROY 2
1688 Stack now 0 2
1689 Error: popping nterm $@1 (: )
1690 Stack now 0
1691 Cleanup: discarding lookahead token "end of file" (: )
1692 Stack now 0
1695 AT_CLEANUP
1698 ## ----------------------- ##
1699 ## @$ implies %locations.  ##
1700 ## ----------------------- ##
1702 # Bison once forgot to check for @$ in actions other than semantic actions.
1704 # AT_CHECK_ACTION_LOCATIONS(ACTION-DIRECTIVE)
1705 # -------------------------------------------
1706 m4_define([AT_CHECK_ACTION_LOCATIONS],
1707 [AT_SETUP([[@$ in ]$1[ implies %locations]])
1708 AT_BISON_OPTION_PUSHDEFS([%debug])
1709 AT_DATA_GRAMMAR([[input.y]],
1710 [[%code {
1711   #include <stdio.h>
1712 ]AT_YYERROR_DECLARE[
1713 ]AT_YYLEX_DECLARE[
1716 %debug
1718 ]$1[ {
1719   fprintf (stderr, "%d\n", @$.first_line);
1720 } ]m4_if($1, [%initial-action], [], [[start]])[
1724 start:  ;
1728 static int
1729 yylex (void)
1731   return 0;
1734 ]AT_YYERROR_DEFINE[
1735 ]AT_MAIN_DEFINE[
1738 AT_BISON_CHECK([[-o input.c input.y]])
1739 AT_COMPILE([[input]])
1740 AT_BISON_OPTION_POPDEFS
1741 AT_CLEANUP])
1743 AT_CHECK_ACTION_LOCATIONS([[%initial-action]])
1744 AT_CHECK_ACTION_LOCATIONS([[%destructor]])
1745 AT_CHECK_ACTION_LOCATIONS([[%printer]])
1748 ## ------------------------- ##
1749 ## Qualified $$ in actions.  ##
1750 ## ------------------------- ##
1752 # Check that we can use qualified $$ (v.g., $<type>$) not only in rule
1753 # actions, but also where $$ is valid: %destructor/%printer and
1754 # %initial-action.
1756 # FIXME: Not actually checking %destructor, but it's the same code as
1757 # %printer...
1759 # To do that, use a semantic value that has two fields (sem_type),
1760 # declare symbols to have only one of these types (INT, float), and
1761 # use $<type>$ to get the other one.  Including for symbols that are
1762 # not typed (UNTYPED).
1764 m4_pushdef([AT_TEST],
1765 [AT_SETUP([[Qualified $$ in actions: $1]])
1767 AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %debug])
1769 AT_DATA_GRAMMAR([[input.y]],
1770 [[%skeleton "$1"
1771 %debug
1772 %code requires
1774   typedef struct sem_type
1775   {
1776     int ival;
1777     float fval;
1778   } sem_type;
1780 ]AT_CXX_IF([[
1781 # include <cstdio> // EOF.
1782 # include <iostream>
1783   namespace
1784   {
1785     void
1786     report (std::ostream& yyo, int ival, float fval)
1787     {
1788       yyo << "ival: " << ival << ", fval: " <<  fval;
1789     }
1790   }
1791 ]], [[
1792 # include <stdio.h>
1793   static void
1794   report (FILE* yyo, int ival, float fval)
1795   {
1796     fprintf (yyo, "ival: %d, fval: %1.1f", ival, fval);
1797   }
1798 ]])[
1801 %define api.value.type {sem_type}
1803 %code
1805   ]AT_YYERROR_DECLARE[
1806   ]AT_YYLEX_DECLARE[
1809 %token UNTYPED
1810 %token <ival> INT
1811 %type <fval> float
1812 %printer { report (yyo, $$,       $<fval>$); } <ival>;
1813 %printer { report (yyo, $<ival>$, $$      ); } <fval>;
1814 %printer { report (yyo, $<ival>$, $<fval>$); } <>;
1816 %initial-action
1818   $<ival>$ = 42;
1819   $<fval>$ = 4.2f;
1823 float: UNTYPED INT
1825   $$       = $<fval>1 + $<fval>2;
1826   $<ival>$ = $<ival>1 + $][2;
1829 ]AT_YYERROR_DEFINE[
1830 ]AT_YYLEX_DEFINE([[{]AT_TOKEN([UNTYPED])[, ]AT_TOKEN([INT])[, EOF}]],
1831                  [AT_VAL.ival = toknum * 10;
1832                   AT_VAL.fval = YY_CAST (float, toknum) / 10.0f;])[
1833 ]AT_MAIN_DEFINE[
1836 AT_FULL_COMPILE([[input]])
1837 AT_PARSER_CHECK([input --debug], 0, [], [stderr])
1838 # Don't be too picky on the traces, GLR is not exactly the same.  Keep
1839 # only the lines from the printer.
1840 AT_CHECK([[sed -ne '/ival:/p' stderr]], 0,
1841 [[Next token is token UNTYPED (ival: 10, fval: 0.1)
1842 Shifting token UNTYPED (ival: 10, fval: 0.1)
1843 Next token is token INT (ival: 20, fval: 0.2)
1844 Shifting token INT (ival: 20, fval: 0.2)
1845    $][1 = token UNTYPED (ival: 10, fval: 0.1)
1846    $][2 = token INT (ival: 20, fval: 0.2)
1847 -> $$ = nterm float (ival: 30, fval: 0.3)
1848 Cleanup: popping nterm float (ival: 30, fval: 0.3)
1851 AT_BISON_OPTION_POPDEFS
1853 AT_CLEANUP
1856 m4_map_args([AT_TEST], [yacc.c], [glr.c], [lalr1.cc], [glr.cc], [glr2.cc])
1857 m4_popdef([AT_TEST])
1859 ## -------------------------------------------------- ##
1860 ## Destroying lookahead assigned by semantic action.  ##
1861 ## -------------------------------------------------- ##
1863 AT_SETUP([[Destroying lookahead assigned by semantic action]])
1865 AT_BISON_OPTION_PUSHDEFS
1866 AT_DATA_GRAMMAR([input.y],
1868 %code {
1869   #include <assert.h>
1870   #include <stdio.h>
1871 ]AT_YYERROR_DECLARE[
1872 ]AT_YYLEX_DECLARE[
1873   #define USE(Var)
1876 %destructor { fprintf (stderr, "'a' destructor\n"); } 'a'
1877 %destructor { fprintf (stderr, "'b' destructor\n"); } 'b'
1881 // In a previous version of Bison, yychar assigned by the semantic
1882 // action below was not translated into yytoken before the lookahead was
1883 // discarded and thus before its destructor (selected according to
1884 // yytoken) was called in order to return from yyparse.  This would
1885 // happen even if YYACCEPT was performed in a later semantic action as
1886 // long as only consistent states with default reductions were visited
1887 // in between.  However, we leave YYACCEPT in the same semantic action
1888 // for this test in order to show that skeletons cannot simply translate
1889 // immediately after every semantic action because a semantic action
1890 // that has set yychar might not always return normally.  Instead,
1891 // skeletons must translate before every use of yytoken.
1892 start: 'a' accept { USE($1); } ;
1893 accept: %empty {
1894   assert (yychar == YYEMPTY);
1895   yychar = 'b';
1896   YYACCEPT;
1897 } ;
1900 ]AT_YYERROR_DEFINE[
1901 ]AT_YYLEX_DEFINE(["a"])[
1902 ]AT_MAIN_DEFINE[
1904 AT_BISON_OPTION_POPDEFS
1905 AT_BISON_CHECK([[-o input.c input.y]])
1906 AT_COMPILE([[input]])
1907 AT_PARSER_CHECK([[input]], [[0]], [],
1908 [['b' destructor
1909 'a' destructor
1912 AT_CLEANUP
1914 ## ---------- ##
1915 ## YYBACKUP.  ##
1916 ## ---------- ##
1918 AT_SETUP([[YYBACKUP]])
1920 AT_BISON_OPTION_PUSHDEFS([%pure-parser %debug])
1922 AT_DATA_GRAMMAR([input.y],
1924 %define parse.error verbose
1925 %debug
1926 %define api.pure
1927 %code {
1928 # include <stdio.h>
1929 # include <stdlib.h>
1930 # include <assert.h>
1932   ]AT_YYERROR_DECLARE[
1933   ]AT_YYLEX_DECLARE[
1936 input:
1937   exp exp {}
1940 exp:
1941   'a'     { printf ("a: %d\n", $1); }
1942 | 'b'     { YYBACKUP('a', 123); }
1943 | 'c' 'd' { YYBACKUP('a', 456); }
1947 ]AT_YYERROR_DEFINE[
1948 ]AT_YYLEX_DEFINE(["bcd"], [*lvalp = (toknum + 1) * 10])[
1949 ]AT_MAIN_DEFINE[
1951 AT_BISON_OPTION_POPDEFS
1953 AT_BISON_CHECK([[-o input.c input.y]])
1954 AT_COMPILE([[input]])
1955 AT_PARSER_CHECK([[input]], [[0]],
1956 [[a: 123
1957 a: 456
1960 AT_CLEANUP