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