]> git.saurik.com Git - bison.git/blob - tests/actions.at
style: no longer use backquotes
[bison.git] / tests / actions.at
1 e# Executing Actions. -*- Autotest -*-
2
3 # Copyright (C) 2001-2013 Free Software Foundation, Inc.
4
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.
9 #
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.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 AT_BANNER([[User Actions.]])
19
20 ## ------------------ ##
21 ## Mid-rule actions. ##
22 ## ------------------ ##
23
24 AT_SETUP([Mid-rule actions])
25
26 # Bison once forgot the mid-rule actions. It was because the action
27 # was attached to the host rule (the one with the mid-rule action),
28 # instead of being attached to the empty rule dedicated to this
29 # action.
30
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[
38 }
39 %%
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 ;
52 %%
53 ]AT_YYERROR_DEFINE[
54 ]AT_YYLEX_DEFINE(["123456789"])[
55 ]AT_MAIN_DEFINE[
56 ]])
57 AT_BISON_OPTION_POPDEFS
58
59 AT_BISON_CHECK([-d -v -o input.c input.y])
60 AT_COMPILE([input])
61 AT_PARSER_CHECK([./input], 0,
62 [[0123456789
63 ]])
64
65 AT_CLEANUP
66
67 ## ----------------------- ##
68 ## Implicitly empty rule. ##
69 ## ----------------------- ##
70
71 AT_SETUP([Implicitly empty rule])
72
73 AT_DATA_GRAMMAR([[1.y]],
74 [[%%
75 exp: a b;
76 a: /* empty. */ {};
77 // A mid-rule action does not count as an empty rule.
78 b: {} {};
79 ]])
80
81 AT_BISON_CHECK([-fcaret -Wempty-rule 1.y], [0], [],
82 [[1.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
83 a: /* empty. */ {};
84 ^^
85 ]])
86
87 AT_DATA_GRAMMAR([[2.y]],
88 [[%%
89 exp: a b c;
90 a: /* empty. */ {};
91 b: %empty {};
92 c: /* empty. */ {};
93 ]])
94
95 AT_BISON_CHECK([-fcaret 2.y], [0], [],
96 [[2.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
97 a: /* empty. */ {};
98 ^^
99 2.y:13.17-18: warning: empty rule without %empty [-Wempty-rule]
100 c: /* empty. */ {};
101 ^^
102 ]])
103
104 AT_BISON_CHECK([-fcaret -Wno-empty-rule 2.y], [0])
105
106 AT_CLEANUP
107
108 ## ------------------------ ##
109 ## Invalid uses of %empty. ##
110 ## ------------------------ ##
111
112 AT_SETUP([Invalid uses of %empty])
113
114 AT_DATA_GRAMMAR([[one.y]],
115 [[%%
116 exp:
117 %empty %empty {}
118 ;
119 ]])
120
121 AT_BISON_CHECK([-fcaret one.y], [1], [],
122 [[one.y:11.10-15: error: only one %empty allowed per rule
123 %empty %empty {}
124 ^^^^^^
125 ]])
126
127 AT_DATA_GRAMMAR([[two.y]],
128 [[%%
129 exp:
130 'a' %empty {}
131 | %empty 'a' {}
132 | %empty {} {}
133 ;
134 ]])
135
136 AT_BISON_CHECK([-fcaret two.y], [1], [],
137 [[two.y:11.7-12: error: %empty on non-empty rule
138 'a' %empty {}
139 ^^^^^^
140 two.y:12.3-8: error: %empty on non-empty rule
141 | %empty 'a' {}
142 ^^^^^^
143 two.y:13.3-8: error: %empty on non-empty rule
144 | %empty {} {}
145 ^^^^^^
146 ]])
147
148 AT_CLEANUP
149
150 ## ---------------------- ##
151 ## Valid uses of %empty. ##
152 ## ---------------------- ##
153
154 AT_SETUP([Valid uses of %empty])
155
156 AT_BISON_OPTION_PUSHDEFS
157 AT_DATA_GRAMMAR([[input.y]],
158 [[
159 %debug
160 %code
161 {
162 ]AT_YYERROR_DECLARE[
163 ]AT_YYLEX_DECLARE[
164 }
165 %%
166 exp: %empty {}
167 %%
168 ]AT_YYERROR_DEFINE[
169 ]AT_YYLEX_DEFINE[
170 ]AT_MAIN_DEFINE[
171 ]])
172
173 AT_FULL_COMPILE([input])
174 AT_PARSER_CHECK([./input])
175 AT_BISON_OPTION_POPDEFS
176 AT_CLEANUP
177
178 ## ------------------ ##
179 ## Initial location. ##
180 ## ------------------ ##
181
182 # AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES], [LOCATION = 1.1])
183 # -----------------------------------------------------------------------
184 # Check that the initial location is correct.
185 m4_pushdef([AT_TEST],
186 [AT_SETUP([Initial location: $1 $2])
187
188 AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
189 AT_DATA_GRAMMAR([[input.y]],
190 [[%locations
191 %debug
192 %skeleton "$1"
193 ]$2[
194 ]$3[
195 %code
196 {
197 # include <stdio.h>
198 # include <stdlib.h> /* getenv */
199 ]AT_YYERROR_DECLARE[
200 ]AT_YYLEX_DECLARE[
201 }
202 %%
203 exp: { ]AT_SKEL_CC_IF([[std::cerr << @$ << std::endl]],
204 [[LOCATION_PRINT(stderr, @$); fputc ('\n', stderr)]])[; }
205 %%
206 ]AT_YYERROR_DEFINE[
207
208 ]AT_YYLEX_PROTOTYPE[
209 {]AT_PURE_IF([
210 YYUSE(lvalp);
211 YYUSE(llocp);], [AT_SKEL_CC_IF([
212 YYUSE(lvalp);
213 YYUSE(llocp);])])[
214 return 'x';
215 }
216
217 int
218 main (void)
219 {]AT_SKEL_CC_IF([[
220 yy::parser p;
221 p.set_debug_level (!!getenv("YYDEBUG"));
222 return p.parse ();]], [[
223 yydebug = !!getenv("YYDEBUG");
224 return !!yyparse (]AT_PARAM_IF([0])[);]])[
225 }
226 ]])
227
228 AT_FULL_COMPILE([input])
229 AT_PARSER_CHECK([./input], 1, [],
230 [m4_default([$4], [1.1])
231 m4_default([$4], [1.1])[: syntax error
232 ]])
233 AT_BISON_OPTION_POPDEFS
234 AT_CLEANUP
235 ])
236
237 ## FIXME: test Java, and iterate over skeletons.
238 AT_TEST([yacc.c])
239 AT_TEST([yacc.c], [%define api.pure full])
240 AT_TEST([yacc.c], [%define api.pure %parse-param { int x }])
241 AT_TEST([yacc.c], [%define api.push-pull both])
242 AT_TEST([yacc.c], [%define api.push-pull both %define api.pure full])
243 AT_TEST([glr.c])
244 AT_TEST([glr.c], [%define api.pure])
245 AT_TEST([lalr1.cc])
246 AT_TEST([glr.cc])
247
248 ## A very different test, based on PostgreSQL's implementation of the
249 ## locations. See
250 ## http://lists.gnu.org/archive/html/bug-bison/2012-11/msg00023.html
251 ##
252 ## Weirdly enough, to trigger the warning with GCC 4.7, we must not
253 ## use fprintf, so run the test twice: once to check the warning
254 ## (absence thereof), and another time to check the value.
255 AT_TEST([yacc.c], [%define api.pure full],
256 [[%{
257 # define YYLTYPE int
258 # define LOCATION_PRINT(Stream, Loc) \
259 (void) (Loc)
260 # define YYLLOC_DEFAULT(Current, Rhs, N) \
261 (Current) = ((Rhs)[N ? 1 : 0])
262 %}
263 ]],
264 [@&t@])
265
266 AT_TEST([yacc.c], [%define api.pure full],
267 [[%{
268 # define YYLTYPE int
269 # define LOCATION_PRINT(Stream, Loc) \
270 fprintf ((Stream), "%d", (Loc))
271 # define YYLLOC_DEFAULT(Current, Rhs, N) \
272 (Current) = ((Rhs)[N ? 1 : 0])
273 %}
274 ]],
275 [0])
276
277
278 m4_popdef([AT_TEST])
279
280
281
282 ## ---------------- ##
283 ## Location Print. ##
284 ## ---------------- ##
285
286 # AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES], [LOCATION = 1.1])
287 # -----------------------------------------------------------------------
288 # Check that the initial location is correct.
289 m4_pushdef([AT_TEST],
290 [AT_SETUP([Location print: $1 $2])
291
292 AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
293 AT_DATA_GRAMMAR([[input.y]],
294 [[%locations
295 %debug
296 %skeleton "$1"
297 ]$2[
298 ]$3[
299 %code
300 {
301 ]AT_YYERROR_DECLARE[
302 ]AT_YYLEX_DECLARE[
303 }
304 %%
305 exp: %empty;
306 %%
307 ]AT_YYERROR_DEFINE[
308 ]AT_YYLEX_DEFINE[
309
310 int
311 main (void)
312 {
313 ]AT_YYLTYPE[ loc;
314 ]AT_GLR_CC_IF([loc.initialize();])[
315 #define TEST(L1, C1, L2, C2) \
316 loc.]AT_FIRST_LINE[ = L1; \
317 loc.]AT_FIRST_COLUMN[ = C1; \
318 loc.]AT_LAST_LINE[ = L2; \
319 loc.]AT_LAST_COLUMN[ = C2; \
320 ]AT_SKEL_CC_IF([std::cout << loc],
321 [LOCATION_PRINT(stdout, loc)])[;\
322 putchar ('\n');
323
324 TEST(1, 1, 1, 1);
325 TEST(2, 1, 2, 10);
326 TEST(3, 1, 4, 1);
327 TEST(5, 1, 6, 10);
328
329 TEST(7, 2, 0, 2);
330 TEST(8, 0, 8, 0);
331 return 0;
332 }
333 ]])
334
335 AT_FULL_COMPILE([input])
336 AT_PARSER_CHECK([./input], 0,
337 [[1.1
338 2.1-9
339 3.1-4.0
340 5.1-6.9
341 7.2
342 8.0
343 ]])
344 AT_BISON_OPTION_POPDEFS
345 AT_CLEANUP
346 ])
347
348 ## FIXME: test Java, and iterate over skeletons.
349 AT_TEST([yacc.c])
350 AT_TEST([glr.c])
351 AT_TEST([lalr1.cc])
352 AT_TEST([glr.cc])
353
354 m4_popdef([AT_TEST])
355
356
357
358 ## ---------------- ##
359 ## Exotic Dollars. ##
360 ## ---------------- ##
361
362 AT_SETUP([Exotic Dollars])
363
364 AT_BISON_OPTION_PUSHDEFS
365 AT_DATA_GRAMMAR([[input.y]],
366 [[%define parse.error verbose
367 %debug
368 %code {
369 ]AT_YYERROR_DECLARE[
370 ]AT_YYLEX_DECLARE[
371 # define USE(Var)
372 }
373
374 %union
375 {
376 int val;
377 };
378
379 %type <val> a_1 a_2 a_5
380 sum_of_the_five_previous_values
381
382 %%
383 exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
384 sum_of_the_five_previous_values
385 {
386 USE (($1, $2, $<foo>3, $<foo>4, $5));
387 printf ("%d\n", $6);
388 }
389 ;
390 a_1: { $$ = 1; };
391 a_2: { $$ = 2; };
392 a_5: { $$ = 5; };
393
394 sum_of_the_five_previous_values:
395 {
396 $$ = $<val>0 + $<val>-1 + $<val>-2 + $<val>-3 + $<val>-4;
397 }
398 ;
399
400 %%
401 ]AT_YYERROR_DEFINE[
402 ]AT_YYLEX_DEFINE[
403 ]AT_MAIN_DEFINE[
404 ]])
405
406 AT_BISON_CHECK([-d -v -o input.c input.y], 0)
407 AT_COMPILE([input])
408 AT_PARSER_CHECK([./input], 0,
409 [[15
410 ]])
411
412 # Make sure that fields after $n or $-n are parsed correctly. At one
413 # point while implementing dashes in symbol names, we were dropping
414 # fields after $-n.
415 AT_DATA_GRAMMAR([[input.y]],
416 [[
417 %{
418 ]AT_YYERROR_DECLARE[
419 ]AT_YYLEX_DECLARE[
420 typedef struct { int val; } stype;
421 # define YYSTYPE stype
422 %}
423
424 %%
425 start: one two { $$.val = $1.val + $2.val; } sum ;
426 one: { $$.val = 1; } ;
427 two: { $$.val = 2; } ;
428 sum: { printf ("%d\n", $0.val + $-1.val + $-2.val); } ;
429
430 %%
431 ]AT_YYERROR_DEFINE[
432 ]AT_YYLEX_DEFINE[
433 ]AT_MAIN_DEFINE[
434 ]])
435
436 AT_FULL_COMPILE([input])
437 AT_PARSER_CHECK([[./input]], [[0]],
438 [[6
439 ]])
440
441 AT_BISON_OPTION_POPDEFS
442 AT_CLEANUP
443
444
445
446 ## -------------------------- ##
447 ## Printers and Destructors. ##
448 ## -------------------------- ##
449
450 # _AT_CHECK_PRINTER_AND_DESTRUCTOR($1, $2, $3, $4,
451 # BISON-DIRECTIVE, UNION-FLAG)
452 # -------------------------------------------------------------
453 m4_define([_AT_CHECK_PRINTER_AND_DESTRUCTOR],
454 [# Make sure complex $n work.
455 m4_if([$1$2$3$4], $[1]$[2]$[3]$[4], [],
456 [m4_fatal([$0: Invalid arguments: $@])])dnl
457
458 # Be sure to pass all the %directives to this macro to have correct
459 # helping macros. So don't put any directly in the Bison file.
460 AT_BISON_OPTION_PUSHDEFS([$5])
461 AT_DATA_GRAMMAR([[input.y]],
462 [[%code requires {
463 #include <stdio.h>
464 #include <stdlib.h>
465 #include <string.h>
466 #include <assert.h>
467
468 #define YYINITDEPTH 10
469 #define YYMAXDEPTH 10
470 #define RANGE(Location) ]AT_LALR1_CC_IF([(Location).begin.line, (Location).end.line],
471 [(Location).first_line, (Location).last_line])[
472
473 /* Display the symbol type Symbol. */
474 #define V(Symbol, Value, Location, Sep) \
475 fprintf (stderr, #Symbol " (%d@%d-%d)" Sep, Value, RANGE(Location))
476 }
477
478 $5
479 ]m4_ifval([$6], [%union
480 {
481 int ival;
482 }])
483 AT_LALR1_CC_IF([%define global_tokens_and_yystype])
484 m4_ifval([$6], [[%code provides {]], [[%code {]])
485 AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])[
486 ]AT_YYLEX_DECLARE[
487 ]AT_LALR1_CC_IF([], [AT_YYERROR_DECLARE])
488 [}
489
490 ]m4_ifval([$6], [%type <ival> '(' 'x' 'y' ')' ';' thing line input END])[
491
492 /* FIXME: This %printer isn't actually tested. */
493 %printer
494 {
495 ]AT_LALR1_CC_IF([debug_stream () << $$;],
496 [fprintf (yyoutput, "%d", $$)])[;
497 }
498 input line thing 'x' 'y'
499
500 %destructor
501 { fprintf (stderr, "Freeing nterm input (%d@%d-%d)\n", $$, RANGE (@$)); }
502 input
503
504 %destructor
505 { fprintf (stderr, "Freeing nterm line (%d@%d-%d)\n", $$, RANGE (@$)); }
506 line
507
508 %destructor
509 { fprintf (stderr, "Freeing nterm thing (%d@%d-%d)\n", $$, RANGE (@$)); }
510 thing
511
512 %destructor
513 { fprintf (stderr, "Freeing token 'x' (%d@%d-%d)\n", $$, RANGE (@$)); }
514 'x'
515
516 %destructor
517 { fprintf (stderr, "Freeing token 'y' (%d@%d-%d)\n", $$, RANGE (@$)); }
518 'y'
519
520 %token END 0
521 %destructor
522 { fprintf (stderr, "Freeing token END (%d@%d-%d)\n", $$, RANGE (@$)); }
523 END
524
525 %%
526 /*
527 This grammar is made to exercise error recovery.
528 "Lines" starting with '(' support error recovery, with
529 ')' as synchronizing token. Lines starting with 'x' can never
530 be recovered from if in error.
531 */
532
533 input:
534 /* Nothing. */
535 {
536 $$ = 0;
537 V(input, $$, @$, ": /* Nothing */\n");
538 }
539 | line input /* Right recursive to load the stack so that popping at
540 END can be exercised. */
541 {
542 $$ = 2;
543 V(input, $$, @$, ": ");
544 V(line, $1, @1, " ");
545 V(input, $2, @2, "\n");
546 }
547 ;
548
549 line:
550 thing thing thing ';'
551 {
552 $$ = $1;
553 V(line, $$, @$, ": ");
554 V(thing, $1, @1, " ");
555 V(thing, $2, @2, " ");
556 V(thing, $3, @3, " ");
557 V(;, $4, @4, "\n");
558 }
559 | '(' thing thing ')'
560 {
561 $$ = $1;
562 V(line, $$, @$, ": ");
563 V('(', $1, @1, " ");
564 V(thing, $2, @2, " ");
565 V(thing, $3, @3, " ");
566 V(')', $4, @4, "\n");
567 }
568 | '(' thing ')'
569 {
570 $$ = $1;
571 V(line, $$, @$, ": ");
572 V('(', $1, @1, " ");
573 V(thing, $2, @2, " ");
574 V(')', $3, @3, "\n");
575 }
576 | '(' error ')'
577 {
578 $$ = -1;
579 V(line, $$, @$, ": ");
580 V('(', $1, @1, " ");
581 fprintf (stderr, "error (@%d-%d) ", RANGE(@2));
582 V(')', $3, @3, "\n");
583 }
584 ;
585
586 thing:
587 'x'
588 {
589 $$ = $1;
590 V(thing, $$, @$, ": ");
591 V('x', $1, @1, "\n");
592 }
593 ;
594 %%
595 /* Alias to ARGV[1]. */
596 const char *source = YY_NULL;
597
598 ]AT_YYERROR_DEFINE[
599
600 static
601 ]AT_YYLEX_PROTOTYPE[
602 {
603 static unsigned int counter = 0;
604
605 int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++;
606 /* As in BASIC, line numbers go from 10 to 10. */
607 ]AT_LOC_FIRST_LINE[ = ]AT_LOC_FIRST_COLUMN[ = 10 * c;
608 ]AT_LOC_LAST_LINE[ = ]AT_LOC_LAST_COLUMN[ = ]AT_LOC_FIRST_LINE[ + 9;
609 assert (0 <= c && c <= strlen (source));
610 if (source[c])
611 fprintf (stderr, "sending: '%c'", source[c]);
612 else
613 fprintf (stderr, "sending: END");
614 fprintf (stderr, " (%d@%d-%d)\n", c, RANGE (]AT_LOC[));
615 return source[c];
616 }
617 ]AT_LALR1_CC_IF(
618 [static bool yydebug;
619 int
620 yyparse ()
621 {
622 yy::parser parser;
623 parser.set_debug_level (yydebug);
624 return parser.parse ();
625 }
626 ])[
627
628 int
629 main (int argc, const char *argv[])
630 {
631 int status;
632 yydebug = !!getenv ("YYDEBUG");
633 assert (argc == 2);
634 source = argv[1];
635 status = yyparse ();
636 switch (status)
637 {
638 case 0: fprintf (stderr, "Successful parse.\n"); break;
639 case 1: fprintf (stderr, "Parsing FAILED.\n"); break;
640 default: fprintf (stderr, "Parsing FAILED (status %d).\n", status); break;
641 }
642 return status;
643 }
644 ]])
645
646 AT_FULL_COMPILE([input])
647
648
649 # Check the location of "empty"
650 # -----------------------------
651 # I.e., epsilon-reductions, as in "(x)" which ends by reducing
652 # an empty "line" nterm.
653 # FIXME: This location is not satisfying. Depend on the lookahead?
654 AT_PARSER_CHECK([./input '(x)'], 0, [],
655 [[sending: '(' (0@0-9)
656 sending: 'x' (1@10-19)
657 thing (1@10-19): 'x' (1@10-19)
658 sending: ')' (2@20-29)
659 line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
660 sending: END (3@30-39)
661 input (0@29-29): /* Nothing */
662 input (2@0-29): line (0@0-29) input (0@29-29)
663 Freeing token END (3@30-39)
664 Freeing nterm input (2@0-29)
665 Successful parse.
666 ]])
667
668
669 # Check locations in error recovery
670 # ---------------------------------
671 # '(y)' is an error, but can be recovered from. But what's the location
672 # of the error itself ('y'), and of the resulting reduction ('(error)').
673 AT_PARSER_CHECK([./input '(y)'], 0, [],
674 [[sending: '(' (0@0-9)
675 sending: 'y' (1@10-19)
676 10.10-19.18: syntax error, unexpected 'y', expecting 'x'
677 Freeing token 'y' (1@10-19)
678 sending: ')' (2@20-29)
679 line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
680 sending: END (3@30-39)
681 input (0@29-29): /* Nothing */
682 input (2@0-29): line (-1@0-29) input (0@29-29)
683 Freeing token END (3@30-39)
684 Freeing nterm input (2@0-29)
685 Successful parse.
686 ]])
687
688
689 # Syntax errors caught by the parser
690 # ----------------------------------
691 # Exercise the discarding of stack top and input until 'error'
692 # can be reduced.
693 #
694 # '(', 'x', 'x', 'x', 'x', 'x', ')',
695 #
696 # Load the stack and provoke an error that cannot be caught by the
697 # grammar, to check that the stack is cleared. And make sure the
698 # lookahead is freed.
699 #
700 # '(', 'x', ')',
701 # '(', 'x', ')',
702 # 'y'
703 AT_PARSER_CHECK([./input '(xxxxx)(x)(x)y'], 1, [],
704 [[sending: '(' (0@0-9)
705 sending: 'x' (1@10-19)
706 thing (1@10-19): 'x' (1@10-19)
707 sending: 'x' (2@20-29)
708 thing (2@20-29): 'x' (2@20-29)
709 sending: 'x' (3@30-39)
710 30.30-39.38: syntax error, unexpected 'x', expecting ')'
711 Freeing nterm thing (2@20-29)
712 Freeing nterm thing (1@10-19)
713 Freeing token 'x' (3@30-39)
714 sending: 'x' (4@40-49)
715 Freeing token 'x' (4@40-49)
716 sending: 'x' (5@50-59)
717 Freeing token 'x' (5@50-59)
718 sending: ')' (6@60-69)
719 line (-1@0-69): '(' (0@0-9) error (@10-59) ')' (6@60-69)
720 sending: '(' (7@70-79)
721 sending: 'x' (8@80-89)
722 thing (8@80-89): 'x' (8@80-89)
723 sending: ')' (9@90-99)
724 line (7@70-99): '(' (7@70-79) thing (8@80-89) ')' (9@90-99)
725 sending: '(' (10@100-109)
726 sending: 'x' (11@110-119)
727 thing (11@110-119): 'x' (11@110-119)
728 sending: ')' (12@120-129)
729 line (10@100-129): '(' (10@100-109) thing (11@110-119) ')' (12@120-129)
730 sending: 'y' (13@130-139)
731 input (0@129-129): /* Nothing */
732 input (2@100-129): line (10@100-129) input (0@129-129)
733 input (2@70-129): line (7@70-99) input (2@100-129)
734 input (2@0-129): line (-1@0-69) input (2@70-129)
735 130.130-139.138: syntax error, unexpected 'y', expecting END
736 Freeing nterm input (2@0-129)
737 Freeing token 'y' (13@130-139)
738 Parsing FAILED.
739 ]])
740
741
742 # Syntax error caught by the parser where lookahead = END
743 # --------------------------------------------------------
744 # Load the stack and provoke an error that cannot be caught by the
745 # grammar, to check that the stack is cleared. And make sure the
746 # lookahead is freed.
747 #
748 # '(', 'x', ')',
749 # '(', 'x', ')',
750 # 'x'
751 AT_PARSER_CHECK([./input '(x)(x)x'], 1, [],
752 [[sending: '(' (0@0-9)
753 sending: 'x' (1@10-19)
754 thing (1@10-19): 'x' (1@10-19)
755 sending: ')' (2@20-29)
756 line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
757 sending: '(' (3@30-39)
758 sending: 'x' (4@40-49)
759 thing (4@40-49): 'x' (4@40-49)
760 sending: ')' (5@50-59)
761 line (3@30-59): '(' (3@30-39) thing (4@40-49) ')' (5@50-59)
762 sending: 'x' (6@60-69)
763 thing (6@60-69): 'x' (6@60-69)
764 sending: END (7@70-79)
765 70.70-79.78: syntax error, unexpected END, expecting 'x'
766 Freeing nterm thing (6@60-69)
767 Freeing nterm line (3@30-59)
768 Freeing nterm line (0@0-29)
769 Freeing token END (7@70-79)
770 Parsing FAILED.
771 ]])
772
773
774 # Check destruction upon stack overflow
775 # -------------------------------------
776 # Upon stack overflow, all symbols on the stack should be destroyed.
777 # Only check for yacc.c.
778 AT_YACC_IF([
779 AT_PARSER_CHECK([./input '(x)(x)(x)(x)(x)(x)(x)'], 2, [],
780 [[sending: '(' (0@0-9)
781 sending: 'x' (1@10-19)
782 thing (1@10-19): 'x' (1@10-19)
783 sending: ')' (2@20-29)
784 line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
785 sending: '(' (3@30-39)
786 sending: 'x' (4@40-49)
787 thing (4@40-49): 'x' (4@40-49)
788 sending: ')' (5@50-59)
789 line (3@30-59): '(' (3@30-39) thing (4@40-49) ')' (5@50-59)
790 sending: '(' (6@60-69)
791 sending: 'x' (7@70-79)
792 thing (7@70-79): 'x' (7@70-79)
793 sending: ')' (8@80-89)
794 line (6@60-89): '(' (6@60-69) thing (7@70-79) ')' (8@80-89)
795 sending: '(' (9@90-99)
796 sending: 'x' (10@100-109)
797 thing (10@100-109): 'x' (10@100-109)
798 sending: ')' (11@110-119)
799 line (9@90-119): '(' (9@90-99) thing (10@100-109) ')' (11@110-119)
800 sending: '(' (12@120-129)
801 sending: 'x' (13@130-139)
802 thing (13@130-139): 'x' (13@130-139)
803 sending: ')' (14@140-149)
804 line (12@120-149): '(' (12@120-129) thing (13@130-139) ')' (14@140-149)
805 sending: '(' (15@150-159)
806 sending: 'x' (16@160-169)
807 thing (16@160-169): 'x' (16@160-169)
808 sending: ')' (17@170-179)
809 line (15@150-179): '(' (15@150-159) thing (16@160-169) ')' (17@170-179)
810 sending: '(' (18@180-189)
811 sending: 'x' (19@190-199)
812 thing (19@190-199): 'x' (19@190-199)
813 sending: ')' (20@200-209)
814 200.200-209.208: memory exhausted
815 Freeing nterm thing (19@190-199)
816 Freeing nterm line (15@150-179)
817 Freeing nterm line (12@120-149)
818 Freeing nterm line (9@90-119)
819 Freeing nterm line (6@60-89)
820 Freeing nterm line (3@30-59)
821 Freeing nterm line (0@0-29)
822 Parsing FAILED (status 2).
823 ]])
824 ])
825
826 AT_BISON_OPTION_POPDEFS
827 ])# _AT_CHECK_PRINTER_AND_DESTRUCTOR
828
829
830 # AT_CHECK_PRINTER_AND_DESTRUCTOR([BISON-OPTIONS], [UNION-FLAG], [SKIP_FLAG])
831 # ---------------------------------------------------------------------------
832 m4_define([AT_CHECK_PRINTER_AND_DESTRUCTOR],
833 [AT_SETUP([Printers and Destructors$2]m4_ifval([$1], [[: $1]]))
834
835 $3
836 _AT_CHECK_PRINTER_AND_DESTRUCTOR($[1], $[2], $[3], $[4],
837 [%define parse.error verbose
838 %debug
839 %verbose
840 %locations
841 $1], [$2])
842
843 AT_CLEANUP
844 ])
845
846
847 AT_CHECK_PRINTER_AND_DESTRUCTOR([])
848 AT_CHECK_PRINTER_AND_DESTRUCTOR([], [with union])
849
850 AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"])
851 AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"], [with union])
852
853 AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser])
854 AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [with union])
855
856
857
858 ## ----------------------------------------- ##
859 ## Default tagless %printer and %destructor. ##
860 ## ----------------------------------------- ##
861
862 # Check that the right %printer and %destructor are called, that they're not
863 # called for $end, and that $$ and @$ work correctly.
864
865 AT_SETUP([Default tagless %printer and %destructor])
866 AT_BISON_OPTION_PUSHDEFS([%locations %debug])
867 AT_DATA_GRAMMAR([[input.y]],
868 [[%define parse.error verbose
869 %debug
870 %locations
871
872 %code {
873 ]AT_YYLEX_DECLARE[
874 ]AT_YYERROR_DECLARE[
875 # define USE(SYM)
876 }
877
878 %printer {
879 fprintf (yyoutput, "<*> printer should not be called.\n");
880 } <*>
881
882 %printer {
883 fprintf (yyoutput, "<> printer for '%c' @ %d", $$, @$.first_column);
884 } <>
885 %destructor {
886 fprintf (stdout, "<> destructor for '%c' @ %d.\n", $$, @$.first_column);
887 } <>
888
889 %printer {
890 fprintf (yyoutput, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
891 } 'b' 'c'
892 %destructor {
893 fprintf (stdout, "'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column);
894 } 'b' 'c'
895
896 %destructor {
897 fprintf (yyoutput, "<*> destructor should not be called.\n");
898 } <*>
899
900 %%
901
902 start: 'a' 'b' 'c' 'd' 'e' { $$ = 'S'; USE(($1, $2, $3, $4, $5)); } ;
903
904 %%
905 ]AT_YYERROR_DEFINE[
906 ]AT_YYLEX_DEFINE(["abcd"], [[yylval = res]])[
907 ]AT_MAIN_DEFINE[
908 ]])
909
910 AT_BISON_CHECK([-o input.c input.y], [], [],
911 [[input.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
912 input.y:30.3-5: warning: useless %printer for type <*> [-Wother]
913 ]])
914 AT_COMPILE([input])
915 AT_PARSER_CHECK([./input --debug], 1,
916 [[<> destructor for 'd' @ 4.
917 'b'/'c' destructor for 'c' @ 3.
918 'b'/'c' destructor for 'b' @ 2.
919 <> destructor for 'a' @ 1.
920 ]],
921 [[Starting parse
922 Entering state 0
923 Reading a token: Next token is token 'a' (1.1: <> printer for 'a' @ 1)
924 Shifting token 'a' (1.1: <> printer for 'a' @ 1)
925 Entering state 1
926 Reading a token: Next token is token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
927 Shifting token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
928 Entering state 3
929 Reading a token: Next token is token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
930 Shifting token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
931 Entering state 5
932 Reading a token: Next token is token 'd' (1.4: <> printer for 'd' @ 4)
933 Shifting token 'd' (1.4: <> printer for 'd' @ 4)
934 Entering state 6
935 Reading a token: Now at end of input.
936 1.5: syntax error, unexpected $end, expecting 'e'
937 Error: popping token 'd' (1.4: <> printer for 'd' @ 4)
938 Stack now 0 1 3 5
939 Error: popping token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
940 Stack now 0 1 3
941 Error: popping token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
942 Stack now 0 1
943 Error: popping token 'a' (1.1: <> printer for 'a' @ 1)
944 Stack now 0
945 Cleanup: discarding lookahead token $end (1.5: )
946 Stack now 0
947 ]])
948
949 AT_BISON_OPTION_POPDEFS
950 AT_CLEANUP
951
952
953
954 ## ------------------------------------------------------ ##
955 ## Default tagged and per-type %printer and %destructor. ##
956 ## ------------------------------------------------------ ##
957
958 AT_SETUP([Default tagged and per-type %printer and %destructor])
959 AT_BISON_OPTION_PUSHDEFS([%debug])
960 AT_DATA_GRAMMAR([[input.y]],
961 [[%define parse.error verbose
962 %debug
963
964 %{
965 ]AT_YYERROR_DECLARE[
966 ]AT_YYLEX_DECLARE[
967 # define USE(SYM)
968 %}
969
970 %printer {
971 fprintf (yyoutput, "<> printer should not be called.\n");
972 } <>
973
974 %union { int field0; int field1; int field2; }
975 %type <field0> start 'a' 'g'
976 %type <field1> 'e'
977 %type <field2> 'f'
978 %printer {
979 fprintf (yyoutput, "<*>/<field2>/e printer");
980 } <*> 'e' <field2>
981 %destructor {
982 fprintf (stdout, "<*>/<field2>/e destructor.\n");
983 } <*> 'e' <field2>
984
985 %type <field1> 'b'
986 %printer { fprintf (yyoutput, "<field1> printer"); } <field1>
987 %destructor { fprintf (stdout, "<field1> destructor.\n"); } <field1>
988
989 %type <field0> 'c'
990 %printer { fprintf (yyoutput, "'c' printer"); } 'c'
991 %destructor { fprintf (stdout, "'c' destructor.\n"); } 'c'
992
993 %type <field1> 'd'
994 %printer { fprintf (yyoutput, "'d' printer"); } 'd'
995 %destructor { fprintf (stdout, "'d' destructor.\n"); } 'd'
996
997 %destructor {
998 fprintf (yyoutput, "<> destructor should not be called.\n");
999 } <>
1000
1001 %%
1002
1003 start:
1004 'a' 'b' 'c' 'd' 'e' 'f' 'g'
1005 {
1006 USE(($1, $2, $3, $4, $5, $6, $7));
1007 $$ = 'S';
1008 }
1009 ;
1010
1011 %%
1012 ]AT_YYERROR_DEFINE[
1013 ]AT_YYLEX_DEFINE(["abcdef"])[
1014 ]AT_MAIN_DEFINE[
1015 ]])
1016
1017 AT_BISON_CHECK([-o input.c input.y], [], [],
1018 [[input.y:22.3-4: warning: useless %destructor for type <> [-Wother]
1019 input.y:22.3-4: warning: useless %printer for type <> [-Wother]
1020 ]])
1021 AT_COMPILE([input])
1022 AT_PARSER_CHECK([./input --debug], 1,
1023 [[<*>/<field2>/e destructor.
1024 <*>/<field2>/e destructor.
1025 'd' destructor.
1026 'c' destructor.
1027 <field1> destructor.
1028 <*>/<field2>/e destructor.
1029 ]],
1030 [[Starting parse
1031 Entering state 0
1032 Reading a token: Next token is token 'a' (<*>/<field2>/e printer)
1033 Shifting token 'a' (<*>/<field2>/e printer)
1034 Entering state 1
1035 Reading a token: Next token is token 'b' (<field1> printer)
1036 Shifting token 'b' (<field1> printer)
1037 Entering state 3
1038 Reading a token: Next token is token 'c' ('c' printer)
1039 Shifting token 'c' ('c' printer)
1040 Entering state 5
1041 Reading a token: Next token is token 'd' ('d' printer)
1042 Shifting token 'd' ('d' printer)
1043 Entering state 6
1044 Reading a token: Next token is token 'e' (<*>/<field2>/e printer)
1045 Shifting token 'e' (<*>/<field2>/e printer)
1046 Entering state 7
1047 Reading a token: Next token is token 'f' (<*>/<field2>/e printer)
1048 Shifting token 'f' (<*>/<field2>/e printer)
1049 Entering state 8
1050 Reading a token: Now at end of input.
1051 syntax error, unexpected $end, expecting 'g'
1052 Error: popping token 'f' (<*>/<field2>/e printer)
1053 Stack now 0 1 3 5 6 7
1054 Error: popping token 'e' (<*>/<field2>/e printer)
1055 Stack now 0 1 3 5 6
1056 Error: popping token 'd' ('d' printer)
1057 Stack now 0 1 3 5
1058 Error: popping token 'c' ('c' printer)
1059 Stack now 0 1 3
1060 Error: popping token 'b' (<field1> printer)
1061 Stack now 0 1
1062 Error: popping token 'a' (<*>/<field2>/e printer)
1063 Stack now 0
1064 Cleanup: discarding lookahead token $end ()
1065 Stack now 0
1066 ]])
1067
1068 AT_BISON_OPTION_POPDEFS
1069 AT_CLEANUP
1070
1071
1072
1073 ## ------------------------------------------------------------- ##
1074 ## Default %printer and %destructor for user-defined end token. ##
1075 ## ------------------------------------------------------------- ##
1076
1077 AT_SETUP([Default %printer and %destructor for user-defined end token])
1078
1079 # AT_TEST(TYPED)
1080 # --------------
1081 m4_pushdef([AT_TEST],
1082 [m4_if($1, 0,
1083 [m4_pushdef([kind], []) m4_pushdef([not_kind], [*])],
1084 [m4_pushdef([kind], [*]) m4_pushdef([not_kind], [])])
1085
1086 AT_BISON_OPTION_PUSHDEFS([%locations %debug])
1087 AT_DATA_GRAMMAR([[input]]$1[[.y]],
1088 [[%define parse.error verbose
1089 %debug
1090 %locations
1091
1092 %code {
1093 ]AT_YYERROR_DECLARE[
1094 ]AT_YYLEX_DECLARE[
1095 # define USE(SYM)
1096 }
1097
1098 %destructor {
1099 fprintf (yyoutput, "<]]not_kind[[> destructor should not be called.\n");
1100 } <]]not_kind[[>
1101
1102 %token END 0
1103 %printer {
1104 fprintf (yyoutput, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
1105 } <]]kind[[>
1106 %destructor {
1107 fprintf (stdout, "<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column);
1108 } <]]kind[[>
1109
1110 %printer {
1111 fprintf (yyoutput, "<]]not_kind[[> printer should not be called.\n");
1112 } <]]not_kind[[>
1113
1114 ]]m4_if($1, 0, [[[
1115 ]]],
1116 [[[%union { char tag; }
1117 %type <tag> start END]]])[[
1118
1119 %%
1120
1121 start: { $$ = 'S'; } ;
1122
1123 %%
1124 #include <stdlib.h> /* abort */
1125 static int
1126 yylex (void)
1127 {
1128 static int called;
1129 if (called++)
1130 abort ();
1131 yylval]]m4_if($1, 0,, [[[.tag]]])[[ = 'E';
1132 yylloc.first_line = yylloc.last_line = 1;
1133 yylloc.first_column = yylloc.last_column = 1;
1134 return 0;
1135 }
1136 ]AT_YYERROR_DEFINE[
1137 ]AT_MAIN_DEFINE[
1138 ]])
1139 AT_BISON_OPTION_POPDEFS
1140
1141 AT_BISON_CHECK([-o input$1.c input$1.y], [], [],
1142 [m4_if([$1], [0],
1143 [[input0.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
1144 input0.y:30.3-5: warning: useless %printer for type <*> [-Wother]
1145 ]],
1146 [[input1.y:30.3-4: warning: useless %destructor for type <> [-Wother]
1147 input1.y:30.3-4: warning: useless %printer for type <> [-Wother]
1148 ]])])
1149
1150 AT_COMPILE([input$1])
1151
1152 AT_PARSER_CHECK([./input$1 --debug], 0,
1153 [[<]]kind[[> for 'E' @ 1.
1154 <]]kind[[> for 'S' @ 1.
1155 ]],
1156 [[Starting parse
1157 Entering state 0
1158 Reducing stack by rule 1 (line 49):
1159 -> $$ = nterm start (1.1: <]]kind[[> for 'S' @ 1)
1160 Stack now 0
1161 Entering state 1
1162 Reading a token: Now at end of input.
1163 Shifting token END (1.1: <]]kind[[> for 'E' @ 1)
1164 Entering state 2
1165 Stack now 0 1 2
1166 Cleanup: popping token END (1.1: <]]kind[[> for 'E' @ 1)
1167 Cleanup: popping nterm start (1.1: <]]kind[[> for 'S' @ 1)
1168 ]])
1169
1170 m4_popdef([kind])
1171 m4_popdef([not_kind])
1172 ])
1173
1174 AT_TEST(0)
1175 AT_TEST(1)
1176
1177 m4_popdef([AT_TEST])
1178
1179 AT_CLEANUP
1180
1181
1182
1183 ## ------------------------------------------------------------------ ##
1184 ## Default %printer and %destructor are not for error or $undefined. ##
1185 ## ------------------------------------------------------------------ ##
1186
1187 AT_SETUP([Default %printer and %destructor are not for error or $undefined])
1188
1189 # If Bison were to apply the default %printer and %destructor to the error
1190 # token or to $undefined:
1191 # - For the error token:
1192 # - It would generate warnings for unused $n.
1193 # - It would invoke the %printer and %destructor on the error token's
1194 # semantic value, which would be initialized from the lookahead, which
1195 # would be destroyed separately.
1196 # - For $undefined, who knows what the semantic value would be.
1197 AT_BISON_OPTION_PUSHDEFS([%debug])
1198 AT_DATA_GRAMMAR([[input.y]],
1199 [[%debug
1200
1201 %{
1202 # include <stdio.h>
1203 # include <stdlib.h>
1204 ]AT_YYERROR_DECLARE[
1205 ]AT_YYLEX_DECLARE[
1206 # define USE(SYM)
1207 %}
1208
1209 %printer {
1210 fprintf (yyoutput, "'%c'", $$);
1211 } <> <*>
1212 %destructor {
1213 fprintf (stderr, "DESTROY '%c'\n", $$);
1214 } <> <*>
1215
1216 %%
1217
1218 start:
1219 { $$ = 'S'; }
1220 /* In order to reveal the problems that this bug caused during parsing, add
1221 * $2 to USE. */
1222 | 'a' error 'b' 'c' { USE(($1, $3, $4)); $$ = 'S'; }
1223 ;
1224
1225 %%
1226 ]AT_YYERROR_DEFINE[
1227 ]AT_YYLEX_DEFINE(["abd"], [yylval = res])[
1228 ]AT_MAIN_DEFINE[
1229 ]])
1230 AT_BISON_OPTION_POPDEFS
1231
1232 AT_BISON_CHECK([-o input.c input.y], [], [],
1233 [[input.y:23.6-8: warning: useless %destructor for type <*> [-Wother]
1234 input.y:23.6-8: warning: useless %printer for type <*> [-Wother]
1235 ]])
1236 AT_COMPILE([input])
1237 AT_PARSER_CHECK([./input --debug], [1], [],
1238 [[Starting parse
1239 Entering state 0
1240 Reading a token: Next token is token 'a' ('a')
1241 Shifting token 'a' ('a')
1242 Entering state 1
1243 Reading a token: Next token is token 'b' ('b')
1244 syntax error
1245 Shifting token error ()
1246 Entering state 3
1247 Next token is token 'b' ('b')
1248 Shifting token 'b' ('b')
1249 Entering state 5
1250 Reading a token: Next token is token $undefined ()
1251 Error: popping token 'b' ('b')
1252 DESTROY 'b'
1253 Stack now 0 1 3
1254 Error: popping token error ()
1255 Stack now 0 1
1256 Shifting token error ()
1257 Entering state 3
1258 Next token is token $undefined ()
1259 Error: discarding token $undefined ()
1260 Error: popping token error ()
1261 Stack now 0 1
1262 Shifting token error ()
1263 Entering state 3
1264 Reading a token: Now at end of input.
1265 Cleanup: discarding lookahead token $end ()
1266 Stack now 0 1 3
1267 Cleanup: popping token error ()
1268 Cleanup: popping token 'a' ('a')
1269 DESTROY 'a'
1270 ]])
1271
1272 AT_CLEANUP
1273
1274
1275
1276 ## ------------------------------------------------------ ##
1277 ## Default %printer and %destructor are not for $accept. ##
1278 ## ------------------------------------------------------ ##
1279
1280 AT_SETUP([Default %printer and %destructor are not for $accept])
1281
1282 # If YYSTYPE is a union and Bison were to apply the default %printer and
1283 # %destructor to $accept:
1284 # - The %printer and %destructor code generated for $accept would always be
1285 # dead code because $accept is currently never shifted onto the stack.
1286 # - $$ for $accept would always be of type YYSTYPE because it's not possible
1287 # to declare '%type <field> $accept'. (Also true for $undefined.)
1288 # - Thus, the compiler might complain that the user code assumes the wrong
1289 # type for $$ since the code might assume the type associated with a
1290 # specific union field, which is especially reasonable in C++ since that
1291 # type may be a base type. This test case checks for this problem. (Also
1292 # true for $undefined and the error token, so there are three warnings for
1293 # %printer and three for %destructor.)
1294
1295 AT_BISON_OPTION_PUSHDEFS([%debug])
1296 AT_DATA_GRAMMAR([[input.y]],
1297 [[%debug /* So that %printer is actually compiled. */
1298
1299 %{
1300 # include <stdio.h>
1301 # include <stdlib.h>
1302 ]AT_YYERROR_DECLARE[
1303 ]AT_YYLEX_DECLARE[
1304 # define USE(SYM)
1305 %}
1306
1307 %printer {
1308 char chr = $$;
1309 fprintf (yyoutput, "'%c'", chr);
1310 } <> <*>
1311 %destructor {
1312 char chr = $$;
1313 fprintf (stderr, "DESTROY '%c'\n", chr);
1314 } <> <*>
1315
1316 %union { char chr; }
1317 %type <chr> start
1318
1319 %%
1320
1321 start: { USE($$); } ;
1322
1323 %%
1324 ]AT_YYERROR_DEFINE[
1325 ]AT_YYLEX_DEFINE[
1326 ]AT_MAIN_DEFINE[
1327 ]])
1328 AT_BISON_OPTION_POPDEFS
1329
1330 AT_BISON_CHECK([-o input.c input.y], [], [],
1331 [[input.y:24.3-4: warning: useless %destructor for type <> [-Wother]
1332 input.y:24.3-4: warning: useless %printer for type <> [-Wother]
1333 ]])
1334 AT_COMPILE([input])
1335
1336 AT_CLEANUP
1337
1338
1339
1340 ## ------------------------------------------------------ ##
1341 ## Default %printer and %destructor for mid-rule values. ##
1342 ## ------------------------------------------------------ ##
1343
1344 AT_SETUP([Default %printer and %destructor for mid-rule values])
1345
1346 AT_BISON_OPTION_PUSHDEFS([%debug])
1347 AT_DATA_GRAMMAR([[input.y]],
1348 [[%debug /* So that %printer is actually compiled. */
1349
1350 %{
1351 ]AT_YYERROR_DECLARE[
1352 ]AT_YYLEX_DECLARE[
1353 # define USE(SYM)
1354 # define YYLTYPE int
1355 # define YYLLOC_DEFAULT(Current, Rhs, N) (void)(Rhs)
1356 # define LOCATION_PRINT(File, Loc)
1357 %}
1358
1359 %printer { fprintf (yyoutput, "%d", @$); } <>
1360 %destructor { fprintf (stderr, "DESTROY %d\n", @$); } <>
1361 %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1362 %destructor { fprintf (yyoutput, "<*> destructor should not be called"); } <*>
1363
1364 %%
1365
1366 start:
1367 { @$ = 1; } // Not set or used.
1368 { USE ($$); @$ = 2; } // Both set and used.
1369 { USE ($$); @$ = 3; } // Only set.
1370 { @$ = 4; } // Only used.
1371 'c'
1372 { USE (($$, $2, $4, $5)); @$ = 0; }
1373 ;
1374
1375 %%
1376 ]AT_YYERROR_DEFINE[
1377 ]AT_YYLEX_DEFINE[
1378 ]AT_MAIN_DEFINE[
1379 ]])
1380 AT_BISON_OPTION_POPDEFS
1381
1382 AT_BISON_CHECK([-o input.c input.y], 0,,
1383 [[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
1384 input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
1385 input.y:33.3-23: warning: unset value: $$ [-Wother]
1386 input.y:32.3-23: warning: unused value: $3 [-Wother]
1387 ]])
1388
1389 AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
1390 [[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
1391 %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1392 ^^^
1393 input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
1394 %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1395 ^^^
1396 input.y:33.3-23: warning: unset value: $$ [-Wother]
1397 { @$ = 4; } // Only used.
1398 ^^^^^^^^^^^^^^^^^^^^^
1399 input.y:32.3-23: warning: unused value: $3 [-Wother]
1400 { USE ($$); @$ = 3; } // Only set.
1401 ^^^^^^^^^^^^^^^^^^^^^
1402 ]])
1403
1404 AT_COMPILE([input])
1405 AT_PARSER_CHECK([./input --debug], 1,,
1406 [[Starting parse
1407 Entering state 0
1408 Reducing stack by rule 1 (line 30):
1409 -> $$ = nterm $@1 (: )
1410 Stack now 0
1411 Entering state 2
1412 Reducing stack by rule 2 (line 31):
1413 -> $$ = nterm @2 (: 2)
1414 Stack now 0 2
1415 Entering state 4
1416 Reducing stack by rule 3 (line 32):
1417 -> $$ = nterm @3 (: 3)
1418 Stack now 0 2 4
1419 Entering state 5
1420 Reducing stack by rule 4 (line 33):
1421 -> $$ = nterm @4 (: 4)
1422 Stack now 0 2 4 5
1423 Entering state 6
1424 Reading a token: Now at end of input.
1425 syntax error
1426 Error: popping nterm @4 (: 4)
1427 DESTROY 4
1428 Stack now 0 2 4 5
1429 Error: popping nterm @3 (: 3)
1430 DESTROY 3
1431 Stack now 0 2 4
1432 Error: popping nterm @2 (: 2)
1433 DESTROY 2
1434 Stack now 0 2
1435 Error: popping nterm $@1 (: )
1436 Stack now 0
1437 Cleanup: discarding lookahead token $end (: )
1438 Stack now 0
1439 ]])
1440
1441 AT_CLEANUP
1442
1443
1444 ## ----------------------- ##
1445 ## @$ implies %locations. ##
1446 ## ----------------------- ##
1447
1448 # Bison once forgot to check for @$ in actions other than semantic actions.
1449
1450 # AT_CHECK_ACTION_LOCATIONS(ACTION-DIRECTIVE)
1451 # -------------------------------------------
1452 m4_define([AT_CHECK_ACTION_LOCATIONS],
1453 [AT_SETUP([[@$ in ]$1[ implies %locations]])
1454 AT_BISON_OPTION_PUSHDEFS([%debug])
1455 AT_DATA_GRAMMAR([[input.y]],
1456 [[%code {
1457 #include <stdio.h>
1458 ]AT_YYERROR_DECLARE[
1459 ]AT_YYLEX_DECLARE[
1460 }
1461
1462 %debug
1463
1464 ]$1[ {
1465 fprintf (stderr, "%d\n", @$.first_line);
1466 } ]m4_if($1, [%initial-action], [], [[start]])[
1467
1468 %%
1469
1470 start: ;
1471
1472 %%
1473
1474 static int
1475 yylex (void)
1476 {
1477 return 0;
1478 }
1479
1480 ]AT_YYERROR_DEFINE[
1481 ]AT_MAIN_DEFINE[
1482 ]])
1483
1484 AT_BISON_CHECK([[-o input.c input.y]])
1485 AT_COMPILE([[input]])
1486 AT_BISON_OPTION_POPDEFS
1487 AT_CLEANUP])
1488
1489 AT_CHECK_ACTION_LOCATIONS([[%initial-action]])
1490 AT_CHECK_ACTION_LOCATIONS([[%destructor]])
1491 AT_CHECK_ACTION_LOCATIONS([[%printer]])
1492
1493
1494 ## ------------------------- ##
1495 ## Qualified $$ in actions. ##
1496 ## ------------------------- ##
1497
1498 # Check that we can use qualified $$ (v.g., $<type>$) not only in rule
1499 # actions, but also where $$ is valid: %destructor/%printer and
1500 # %initial-action.
1501 #
1502 # FIXME: Not actually checking %destructor, but it's the same code as
1503 # %printer...
1504 #
1505 # To do that, use a semantic value that has two fields (sem_type),
1506 # declare symbols to have only one of these types (INT, float), and
1507 # use $<type>$ to get the other one. Including for symbols that are
1508 # not typed (UNTYPED).
1509
1510 m4_pushdef([AT_TEST],
1511 [AT_SETUP([[Qualified $$ in actions: $1]])
1512
1513 AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %debug])
1514
1515 AT_DATA_GRAMMAR([[input.y]],
1516 [[%skeleton "$1"
1517 %debug
1518 %code requires
1519 {
1520 typedef struct sem_type
1521 {
1522 int ival;
1523 float fval;
1524 } sem_type;
1525
1526 # define YYSTYPE sem_type
1527
1528 ]AT_SKEL_CC_IF([[
1529 # include <iostream>
1530 static void
1531 report (std::ostream& yyo, int ival, float fval)
1532 {
1533 yyo << "ival: " << ival << ", fval: " << fval;
1534 }
1535 ]], [[
1536 # include <stdio.h>
1537 static void
1538 report (FILE* yyo, int ival, float fval)
1539 {
1540 fprintf (yyo, "ival: %d, fval: %1.1f", ival, fval);
1541 }
1542 ]])[
1543 }
1544
1545 %code
1546 {
1547 ]AT_YYERROR_DECLARE[
1548 ]AT_YYLEX_DECLARE[
1549 }
1550
1551 %token UNTYPED
1552 %token <ival> INT
1553 %type <fval> float
1554 %printer { report (yyo, $$, $<fval>$); } <ival>;
1555 %printer { report (yyo, $<ival>$, $$ ); } <fval>;
1556 %printer { report (yyo, $<ival>$, $<fval>$); } <>;
1557
1558 %initial-action
1559 {
1560 $<ival>$ = 42;
1561 $<fval>$ = 4.2;
1562 }
1563
1564 %%
1565 float: UNTYPED INT
1566 {
1567 $$ = $<fval>1 + $<fval>2;
1568 $<ival>$ = $<ival>1 + $][2;
1569 };
1570 %%
1571 ]AT_YYERROR_DEFINE[
1572 ]AT_YYLEX_DEFINE(AT_SKEL_CC_IF([[{yy::parser::token::UNTYPED,
1573 yy::parser::token::INT,
1574 EOF}]],
1575 [[{UNTYPED, INT, EOF}]]),
1576 [AT_VAL.ival = toknum * 10; AT_VAL.fval = toknum / 10.0;])[
1577 ]AT_MAIN_DEFINE[
1578 ]])
1579
1580 AT_FULL_COMPILE([[input]])
1581 AT_PARSER_CHECK([./input --debug], 0, [], [stderr])
1582 # Don't be too picky on the traces, GLR is not exactly the same. Keep
1583 # only the lines from the printer.
1584 AT_CHECK([[sed -ne '/ival:/p' stderr]], 0,
1585 [[Reading a token: Next token is token UNTYPED (ival: 10, fval: 0.1)
1586 Shifting token UNTYPED (ival: 10, fval: 0.1)
1587 Reading a token: Next token is token INT (ival: 20, fval: 0.2)
1588 Shifting token INT (ival: 20, fval: 0.2)
1589 $][1 = token UNTYPED (ival: 10, fval: 0.1)
1590 $][2 = token INT (ival: 20, fval: 0.2)
1591 -> $$ = nterm float (ival: 30, fval: 0.3)
1592 Cleanup: popping nterm float (ival: 30, fval: 0.3)
1593 ]])
1594
1595 AT_BISON_OPTION_POPDEFS
1596
1597 AT_CLEANUP
1598 ])
1599
1600 AT_TEST([yacc.c])
1601 AT_TEST([glr.c])
1602 AT_TEST([lalr1.cc])
1603 AT_TEST([glr.cc])
1604
1605 m4_popdef([AT_TEST])
1606
1607 ## ----------------------------------------------- ##
1608 ## Fix user actions without a trailing semicolon. ##
1609 ## ----------------------------------------------- ##
1610
1611 AT_SETUP([[Fix user actions without a trailing semicolon]])
1612
1613 # This feature is undocumented, but we accidentally broke it in 2.3a,
1614 # and there was a complaint at:
1615 # <http://lists.gnu.org/archive/html/bug-bison/2008-11/msg00001.html>.
1616 AT_BISON_OPTION_PUSHDEFS
1617 AT_DATA([input.y],
1618 [[%%
1619 start: test2 test1 test0 testc;
1620
1621 test2
1622 : 'a' { semi; /* TEST:N:2 */ }
1623 | 'b' { if (0) {no_semi} /* TEST:N:2 */ }
1624 | 'c' { if (0) {semi;} /* TEST:N:2 */ }
1625 | 'd' { semi; no_semi /* TEST:Y:2 */ }
1626 | 'e' { semi(); no_semi() /* TEST:Y:2 */ }
1627 | 'f' { semi[]; no_semi[] /* TEST:Y:2 */ }
1628 | 'g' { semi++; no_semi++ /* TEST:Y:2 */ }
1629 | 'h' { {no_semi} no_semi /* TEST:Y:2 */ }
1630 | 'i' { {semi;} no_semi /* TEST:Y:2 */ }
1631 ;
1632 test1
1633 : 'a' { semi; // TEST:N:1 ;
1634 } | 'b' { if (0) {no_semi} // TEST:N:1 ;
1635 } | 'c' { if (0) {semi;} // TEST:N:1 ;
1636 } | 'd' { semi; no_semi // TEST:Y:1 ;
1637 } | 'e' { semi(); no_semi() // TEST:Y:1 ;
1638 } | 'f' { semi[]; no_semi[] // TEST:Y:1 ;
1639 } | 'g' { semi++; no_semi++ // TEST:Y:1 ;
1640 } | 'h' { {no_semi} no_semi // TEST:Y:1 ;
1641 } | 'i' { {semi;} no_semi // TEST:Y:1 ;
1642 } ;
1643 test0
1644 : 'a' { semi; // TEST:N:1 {}
1645 } | 'b' { if (0) {no_semi} // TEST:N:1 {}
1646 } | 'c' { if (0) {semi;} // TEST:N:1 {}
1647 } | 'd' { semi; no_semi // TEST:Y:1 {}
1648 } | 'e' { semi(); no_semi() // TEST:Y:1 {}
1649 } | 'f' { semi[]; no_semi[] // TEST:Y:1 {}
1650 } | 'g' { semi++; no_semi++ // TEST:Y:1 {}
1651 } | 'h' { {no_semi} no_semi // TEST:Y:1 {}
1652 } | 'i' { {semi;} no_semi // TEST:Y:1 {}
1653 } ;
1654
1655 testc
1656 : 'a' {
1657 #define TEST_MACRO_N \
1658 []"broken\" $ @ $$ @$ [];\
1659 string;"}
1660 | 'b' {
1661 no_semi
1662 #define TEST_MACRO_N \
1663 []"broken\" $ @ $$ @$ [];\
1664 string;"}
1665 ]])
1666 AT_BISON_OPTION_POPDEFS
1667
1668 AT_BISON_CHECK([[-o input.c input.y]], [0], [],
1669 [[input.y:8.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1670 input.y:8.48: future versions of Bison will not add the ';'
1671 input.y:9.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1672 input.y:9.48: future versions of Bison will not add the ';'
1673 input.y:10.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1674 input.y:10.48: future versions of Bison will not add the ';'
1675 input.y:11.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1676 input.y:11.48: future versions of Bison will not add the ';'
1677 input.y:12.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1678 input.y:12.48: future versions of Bison will not add the ';'
1679 input.y:13.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1680 input.y:13.48: future versions of Bison will not add the ';'
1681 input.y:20.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1682 input.y:20.1: future versions of Bison will not add the ';'
1683 input.y:21.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1684 input.y:21.1: future versions of Bison will not add the ';'
1685 input.y:22.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1686 input.y:22.1: future versions of Bison will not add the ';'
1687 input.y:23.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1688 input.y:23.1: future versions of Bison will not add the ';'
1689 input.y:24.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1690 input.y:24.1: future versions of Bison will not add the ';'
1691 input.y:25.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1692 input.y:25.1: future versions of Bison will not add the ';'
1693 input.y:31.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1694 input.y:31.1: future versions of Bison will not add the ';'
1695 input.y:32.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1696 input.y:32.1: future versions of Bison will not add the ';'
1697 input.y:33.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1698 input.y:33.1: future versions of Bison will not add the ';'
1699 input.y:34.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1700 input.y:34.1: future versions of Bison will not add the ';'
1701 input.y:35.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1702 input.y:35.1: future versions of Bison will not add the ';'
1703 input.y:36.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
1704 input.y:36.1: future versions of Bison will not add the ';'
1705 ]])
1706
1707 AT_MATCHES_CHECK([input.c], [[/\* TEST:N:2 \*/ \}$]], [[3]])
1708 AT_MATCHES_CHECK([input.c], [[/\* TEST:Y:2 \*/ ;\}$]], [[6]])
1709 AT_MATCHES_CHECK([input.c], [[// TEST:N:1 [;{}]*\n\}$]], [[6]])
1710 AT_MATCHES_CHECK([input.c], [[// TEST:Y:1 [;{}]*\n;\}$]], [[12]])
1711 AT_MATCHES_CHECK([input.c], [[#define TEST_MACRO_N \\\n\[\]"broken\\" \$ \@ \$\$ \@\$ \[\];\\\nstring;"\}]], [[2]])
1712
1713 AT_CLEANUP
1714
1715
1716 ## -------------------------------------------------- ##
1717 ## Destroying lookahead assigned by semantic action. ##
1718 ## -------------------------------------------------- ##
1719
1720 AT_SETUP([[Destroying lookahead assigned by semantic action]])
1721
1722 AT_BISON_OPTION_PUSHDEFS
1723 AT_DATA_GRAMMAR([input.y],
1724 [[
1725 %code {
1726 #include <assert.h>
1727 #include <stdio.h>
1728 ]AT_YYERROR_DECLARE[
1729 ]AT_YYLEX_DECLARE[
1730 #define USE(Var)
1731 }
1732
1733 %destructor { fprintf (stderr, "'a' destructor\n"); } 'a'
1734 %destructor { fprintf (stderr, "'b' destructor\n"); } 'b'
1735
1736 %%
1737
1738 // In a previous version of Bison, yychar assigned by the semantic
1739 // action below was not translated into yytoken before the lookahead was
1740 // discarded and thus before its destructor (selected according to
1741 // yytoken) was called in order to return from yyparse. This would
1742 // happen even if YYACCEPT was performed in a later semantic action as
1743 // long as only consistent states with default reductions were visited
1744 // in between. However, we leave YYACCEPT in the same semantic action
1745 // for this test in order to show that skeletons cannot simply translate
1746 // immediately after every semantic action because a semantic action
1747 // that has set yychar might not always return normally. Instead,
1748 // skeletons must translate before every use of yytoken.
1749 start: 'a' accept { USE($1); } ;
1750 accept: %empty {
1751 assert (yychar == YYEMPTY);
1752 yychar = 'b';
1753 YYACCEPT;
1754 } ;
1755
1756 %%
1757 ]AT_YYERROR_DEFINE[
1758 ]AT_YYLEX_DEFINE(["a"])[
1759 ]AT_MAIN_DEFINE[
1760 ]])
1761 AT_BISON_OPTION_POPDEFS
1762 AT_BISON_CHECK([[-o input.c input.y]])
1763 AT_COMPILE([[input]])
1764 AT_PARSER_CHECK([[./input]], [[0]], [],
1765 [['b' destructor
1766 'a' destructor
1767 ]])
1768
1769 AT_CLEANUP
1770
1771 ## ---------- ##
1772 ## YYBACKUP. ##
1773 ## ---------- ##
1774
1775 AT_SETUP([[YYBACKUP]])
1776
1777 AT_BISON_OPTION_PUSHDEFS([%pure-parser %debug])
1778
1779 AT_DATA_GRAMMAR([input.y],
1780 [[
1781 %error-verbose
1782 %debug
1783 %pure-parser
1784 %code {
1785 # include <stdio.h>
1786 # include <stdlib.h>
1787 # include <assert.h>
1788
1789 ]AT_YYERROR_DECLARE[
1790 ]AT_YYLEX_DECLARE[
1791 }
1792 %%
1793 input:
1794 exp exp {}
1795 ;
1796
1797 exp:
1798 'a' { printf ("a: %d\n", $1); }
1799 | 'b' { YYBACKUP('a', 123); }
1800 | 'c' 'd' { YYBACKUP('a', 456); }
1801 ;
1802
1803 %%
1804 ]AT_YYERROR_DEFINE[
1805 ]AT_YYLEX_DEFINE(["bcd"], [*lvalp = (toknum + 1) * 10])[
1806 ]AT_MAIN_DEFINE[
1807 ]])
1808 AT_BISON_OPTION_POPDEFS
1809
1810 AT_BISON_CHECK([[-o input.c input.y]])
1811 AT_COMPILE([[input]])
1812 AT_PARSER_CHECK([[./input]], [[0]],
1813 [[a: 123
1814 a: 456
1815 ]])
1816
1817 AT_CLEANUP