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