]> git.saurik.com Git - bison.git/blame_incremental - tests/actions.at
tests: enable -Wsign-compare and fix corresponding warnings
[bison.git] / tests / actions.at
... / ...
CommitLineData
1e# 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
18AT_BANNER([[User Actions.]])
19
20## ------------------ ##
21## Mid-rule actions. ##
22## ------------------ ##
23
24AT_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
31AT_BISON_OPTION_PUSHDEFS
32AT_DATA_GRAMMAR([[input.y]],
33[[%define parse.error verbose
34%debug
35%code {
36]AT_YYERROR_DECLARE[
37]AT_YYLEX_DECLARE[
38}
39%%
40exp: { 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]])
57AT_BISON_OPTION_POPDEFS
58
59AT_BISON_CHECK([-d -v -o input.c input.y])
60AT_COMPILE([input])
61AT_PARSER_CHECK([./input], 0,
62[[0123456789
63]])
64
65AT_CLEANUP
66
67## ----------------------- ##
68## Implicitly empty rule. ##
69## ----------------------- ##
70
71AT_SETUP([Implicitly empty rule])
72
73AT_DATA_GRAMMAR([[1.y]],
74[[%%
75exp: a b;
76a: /* empty. */ {};
77// A mid-rule action does not count as an empty rule.
78b: {} {};
79]])
80
81AT_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
87AT_DATA_GRAMMAR([[2.y]],
88[[%%
89exp: a b c;
90a: /* empty. */ {};
91b: %empty {};
92c: /* empty. */ {};
93]])
94
95AT_BISON_CHECK([-fcaret 2.y], [0], [],
96[[2.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
97 a: /* empty. */ {};
98 ^^
992.y:13.17-18: warning: empty rule without %empty [-Wempty-rule]
100 c: /* empty. */ {};
101 ^^
102]])
103
104AT_BISON_CHECK([-fcaret -Wno-empty-rule 2.y], [0])
105
106AT_CLEANUP
107
108## ------------------------ ##
109## Invalid uses of %empty. ##
110## ------------------------ ##
111
112AT_SETUP([Invalid uses of %empty])
113
114AT_DATA_GRAMMAR([[one.y]],
115[[%%
116exp:
117 %empty {} %empty
118;
119]])
120
121AT_BISON_CHECK([-fcaret one.y], [1], [],
122[[one.y:11.13-18: error: only one %empty allowed per rule
123 %empty {} %empty
124 ^^^^^^
125one.y:11.3-8: previous declaration
126 %empty {} %empty
127 ^^^^^^
128]])
129
130AT_DATA_GRAMMAR([[two.y]],
131[[%%
132exp:
133 'a' %empty {}
134| %empty 'a' {}
135| %empty {} {}
136;
137]])
138
139AT_BISON_CHECK([-fcaret two.y], [1], [],
140[[two.y:11.7-12: error: %empty on non-empty rule
141 'a' %empty {}
142 ^^^^^^
143two.y:12.3-8: error: %empty on non-empty rule
144 | %empty 'a' {}
145 ^^^^^^
146two.y:13.3-8: error: %empty on non-empty rule
147 | %empty {} {}
148 ^^^^^^
149]])
150
151AT_CLEANUP
152
153## ---------------------- ##
154## Valid uses of %empty. ##
155## ---------------------- ##
156
157AT_SETUP([Valid uses of %empty])
158
159AT_BISON_OPTION_PUSHDEFS
160AT_DATA_GRAMMAR([[input.y]],
161[[
162%debug
163%code
164{
165]AT_YYERROR_DECLARE[
166]AT_YYLEX_DECLARE[
167}
168%%
169exp: %empty {}
170%%
171]AT_YYERROR_DEFINE[
172]AT_YYLEX_DEFINE[
173]AT_MAIN_DEFINE[
174]])
175
176AT_FULL_COMPILE([input])
177AT_PARSER_CHECK([./input])
178AT_BISON_OPTION_POPDEFS
179AT_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.
188m4_pushdef([AT_TEST],
189[AT_SETUP([Initial location: $1 $2])
190
191AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
192AT_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%%
206exp: { ]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
220int
221main (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
231AT_FULL_COMPILE([input])
232AT_PARSER_CHECK([./input], 1, [],
233[m4_default([$4], [1.1])
234m4_default([$4], [1.1])[: syntax error
235]])
236AT_BISON_OPTION_POPDEFS
237AT_CLEANUP
238])
239
240## FIXME: test Java, and iterate over skeletons.
241AT_TEST([yacc.c])
242AT_TEST([yacc.c], [%define api.pure full])
243AT_TEST([yacc.c], [%define api.pure %parse-param { int x }])
244AT_TEST([yacc.c], [%define api.push-pull both])
245AT_TEST([yacc.c], [%define api.push-pull both %define api.pure full])
246AT_TEST([glr.c])
247AT_TEST([glr.c], [%define api.pure])
248AT_TEST([lalr1.cc])
249AT_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.
258AT_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
269AT_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
281m4_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.
292m4_pushdef([AT_TEST],
293[AT_SETUP([Location print: $1 $2])
294
295AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
296AT_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%%
308exp: %empty;
309%%
310]AT_YYERROR_DEFINE[
311]AT_YYLEX_DEFINE[
312
313int
314main (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
338AT_FULL_COMPILE([input])
339AT_PARSER_CHECK([./input], 0,
340[[1.1
3412.1-9
3423.1-4.0
3435.1-6.9
3447.2
3458.0
346]])
347AT_BISON_OPTION_POPDEFS
348AT_CLEANUP
349])
350
351## FIXME: test Java, and iterate over skeletons.
352AT_TEST([yacc.c])
353AT_TEST([glr.c])
354AT_TEST([lalr1.cc])
355AT_TEST([glr.cc])
356
357m4_popdef([AT_TEST])
358
359
360
361## ---------------- ##
362## Exotic Dollars. ##
363## ---------------- ##
364
365AT_SETUP([Exotic Dollars])
366
367AT_BISON_OPTION_PUSHDEFS
368AT_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%%
386exp: 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;
393a_1: { $$ = 1; };
394a_2: { $$ = 2; };
395a_5: { $$ = 5; };
396
397sum_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
409AT_BISON_CHECK([-d -v -o input.c input.y], 0)
410AT_COMPILE([input])
411AT_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.
418AT_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%%
428start: one two { $$.val = $1.val + $2.val; } sum ;
429one: { $$.val = 1; } ;
430two: { $$.val = 2; } ;
431sum: { 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
439AT_FULL_COMPILE([input])
440AT_PARSER_CHECK([[./input]], [[0]],
441[[6
442]])
443
444AT_BISON_OPTION_POPDEFS
445AT_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# -------------------------------------------------------------
456m4_define([_AT_CHECK_PRINTER_AND_DESTRUCTOR],
457[# Make sure complex $n work.
458m4_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.
463AT_BISON_OPTION_PUSHDEFS([$5])
464AT_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}])
486AT_LALR1_CC_IF([%define global_tokens_and_yystype])
487m4_ifval([$6], [[%code provides {]], [[%code {]])
488AT_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
536input:
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
552line:
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
589thing:
590 'x'
591 {
592 $$ = $1;
593 V(thing, $$, @$, ": ");
594 V('x', $1, @1, "\n");
595 }
596;
597%%
598/* Alias to ARGV[1]. */
599const char *source = YY_NULL;
600
601]AT_YYERROR_DEFINE[
602
603static
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;
622int
623yyparse ()
624{
625 yy::parser parser;
626 parser.set_debug_level (yydebug);
627 return parser.parse ();
628}
629])[
630
631int
632main (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
649AT_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?
657AT_PARSER_CHECK([./input '(x)'], 0, [],
658[[sending: '(' (0@0-9)
659sending: 'x' (1@10-19)
660thing (1@10-19): 'x' (1@10-19)
661sending: ')' (2@20-29)
662line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
663sending: END (3@30-39)
664input (0@29-29): /* Nothing */
665input (2@0-29): line (0@0-29) input (0@29-29)
666Freeing token END (3@30-39)
667Freeing nterm input (2@0-29)
668Successful 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)').
676AT_PARSER_CHECK([./input '(y)'], 0, [],
677[[sending: '(' (0@0-9)
678sending: 'y' (1@10-19)
67910.10-19.18: syntax error, unexpected 'y', expecting 'x'
680Freeing token 'y' (1@10-19)
681sending: ')' (2@20-29)
682line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
683sending: END (3@30-39)
684input (0@29-29): /* Nothing */
685input (2@0-29): line (-1@0-29) input (0@29-29)
686Freeing token END (3@30-39)
687Freeing nterm input (2@0-29)
688Successful 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'
706AT_PARSER_CHECK([./input '(xxxxx)(x)(x)y'], 1, [],
707[[sending: '(' (0@0-9)
708sending: 'x' (1@10-19)
709thing (1@10-19): 'x' (1@10-19)
710sending: 'x' (2@20-29)
711thing (2@20-29): 'x' (2@20-29)
712sending: 'x' (3@30-39)
71330.30-39.38: syntax error, unexpected 'x', expecting ')'
714Freeing nterm thing (2@20-29)
715Freeing nterm thing (1@10-19)
716Freeing token 'x' (3@30-39)
717sending: 'x' (4@40-49)
718Freeing token 'x' (4@40-49)
719sending: 'x' (5@50-59)
720Freeing token 'x' (5@50-59)
721sending: ')' (6@60-69)
722line (-1@0-69): '(' (0@0-9) error (@10-59) ')' (6@60-69)
723sending: '(' (7@70-79)
724sending: 'x' (8@80-89)
725thing (8@80-89): 'x' (8@80-89)
726sending: ')' (9@90-99)
727line (7@70-99): '(' (7@70-79) thing (8@80-89) ')' (9@90-99)
728sending: '(' (10@100-109)
729sending: 'x' (11@110-119)
730thing (11@110-119): 'x' (11@110-119)
731sending: ')' (12@120-129)
732line (10@100-129): '(' (10@100-109) thing (11@110-119) ')' (12@120-129)
733sending: 'y' (13@130-139)
734input (0@129-129): /* Nothing */
735input (2@100-129): line (10@100-129) input (0@129-129)
736input (2@70-129): line (7@70-99) input (2@100-129)
737input (2@0-129): line (-1@0-69) input (2@70-129)
738130.130-139.138: syntax error, unexpected 'y', expecting END
739Freeing nterm input (2@0-129)
740Freeing token 'y' (13@130-139)
741Parsing 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'
754AT_PARSER_CHECK([./input '(x)(x)x'], 1, [],
755[[sending: '(' (0@0-9)
756sending: 'x' (1@10-19)
757thing (1@10-19): 'x' (1@10-19)
758sending: ')' (2@20-29)
759line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
760sending: '(' (3@30-39)
761sending: 'x' (4@40-49)
762thing (4@40-49): 'x' (4@40-49)
763sending: ')' (5@50-59)
764line (3@30-59): '(' (3@30-39) thing (4@40-49) ')' (5@50-59)
765sending: 'x' (6@60-69)
766thing (6@60-69): 'x' (6@60-69)
767sending: END (7@70-79)
76870.70-79.78: syntax error, unexpected END, expecting 'x'
769Freeing nterm thing (6@60-69)
770Freeing nterm line (3@30-59)
771Freeing nterm line (0@0-29)
772Freeing token END (7@70-79)
773Parsing 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.
781AT_YACC_IF([
782AT_PARSER_CHECK([./input '(x)(x)(x)(x)(x)(x)(x)'], 2, [],
783[[sending: '(' (0@0-9)
784sending: 'x' (1@10-19)
785thing (1@10-19): 'x' (1@10-19)
786sending: ')' (2@20-29)
787line (0@0-29): '(' (0@0-9) thing (1@10-19) ')' (2@20-29)
788sending: '(' (3@30-39)
789sending: 'x' (4@40-49)
790thing (4@40-49): 'x' (4@40-49)
791sending: ')' (5@50-59)
792line (3@30-59): '(' (3@30-39) thing (4@40-49) ')' (5@50-59)
793sending: '(' (6@60-69)
794sending: 'x' (7@70-79)
795thing (7@70-79): 'x' (7@70-79)
796sending: ')' (8@80-89)
797line (6@60-89): '(' (6@60-69) thing (7@70-79) ')' (8@80-89)
798sending: '(' (9@90-99)
799sending: 'x' (10@100-109)
800thing (10@100-109): 'x' (10@100-109)
801sending: ')' (11@110-119)
802line (9@90-119): '(' (9@90-99) thing (10@100-109) ')' (11@110-119)
803sending: '(' (12@120-129)
804sending: 'x' (13@130-139)
805thing (13@130-139): 'x' (13@130-139)
806sending: ')' (14@140-149)
807line (12@120-149): '(' (12@120-129) thing (13@130-139) ')' (14@140-149)
808sending: '(' (15@150-159)
809sending: 'x' (16@160-169)
810thing (16@160-169): 'x' (16@160-169)
811sending: ')' (17@170-179)
812line (15@150-179): '(' (15@150-159) thing (16@160-169) ')' (17@170-179)
813sending: '(' (18@180-189)
814sending: 'x' (19@190-199)
815thing (19@190-199): 'x' (19@190-199)
816sending: ')' (20@200-209)
817200.200-209.208: memory exhausted
818Freeing nterm thing (19@190-199)
819Freeing nterm line (15@150-179)
820Freeing nterm line (12@120-149)
821Freeing nterm line (9@90-119)
822Freeing nterm line (6@60-89)
823Freeing nterm line (3@30-59)
824Freeing nterm line (0@0-29)
825Parsing FAILED (status 2).
826]])
827])
828
829AT_BISON_OPTION_POPDEFS
830])# _AT_CHECK_PRINTER_AND_DESTRUCTOR
831
832
833# AT_CHECK_PRINTER_AND_DESTRUCTOR([BISON-OPTIONS], [UNION-FLAG], [SKIP_FLAG])
834# ---------------------------------------------------------------------------
835m4_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
846AT_CLEANUP
847])
848
849
850AT_CHECK_PRINTER_AND_DESTRUCTOR([])
851AT_CHECK_PRINTER_AND_DESTRUCTOR([], [ with union])
852
853AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"])
854AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"], [ with union])
855
856AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser])
857AT_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
868AT_SETUP([Default tagless %printer and %destructor])
869AT_BISON_OPTION_PUSHDEFS([%locations %debug])
870AT_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
905start: '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
913AT_BISON_CHECK([-o input.c input.y], [], [],
914[[input.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
915input.y:30.3-5: warning: useless %printer for type <*> [-Wother]
916]])
917AT_COMPILE([input])
918AT_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
925Entering state 0
926Reading a token: Next token is token 'a' (1.1: <> printer for 'a' @ 1)
927Shifting token 'a' (1.1: <> printer for 'a' @ 1)
928Entering state 1
929Reading a token: Next token is token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
930Shifting token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
931Entering state 3
932Reading a token: Next token is token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
933Shifting token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
934Entering state 5
935Reading a token: Next token is token 'd' (1.4: <> printer for 'd' @ 4)
936Shifting token 'd' (1.4: <> printer for 'd' @ 4)
937Entering state 6
938Reading a token: Now at end of input.
9391.5: syntax error, unexpected $end, expecting 'e'
940Error: popping token 'd' (1.4: <> printer for 'd' @ 4)
941Stack now 0 1 3 5
942Error: popping token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
943Stack now 0 1 3
944Error: popping token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
945Stack now 0 1
946Error: popping token 'a' (1.1: <> printer for 'a' @ 1)
947Stack now 0
948Cleanup: discarding lookahead token $end (1.5: )
949Stack now 0
950]])
951
952AT_BISON_OPTION_POPDEFS
953AT_CLEANUP
954
955
956
957## ------------------------------------------------------ ##
958## Default tagged and per-type %printer and %destructor. ##
959## ------------------------------------------------------ ##
960
961AT_SETUP([Default tagged and per-type %printer and %destructor])
962AT_BISON_OPTION_PUSHDEFS([%debug])
963AT_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
1006start:
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
1020AT_BISON_CHECK([-o input.c input.y], [], [],
1021[[input.y:22.3-4: warning: useless %destructor for type <> [-Wother]
1022input.y:22.3-4: warning: useless %printer for type <> [-Wother]
1023]])
1024AT_COMPILE([input])
1025AT_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
1034Entering state 0
1035Reading a token: Next token is token 'a' (<*>/<field2>/e printer)
1036Shifting token 'a' (<*>/<field2>/e printer)
1037Entering state 1
1038Reading a token: Next token is token 'b' (<field1> printer)
1039Shifting token 'b' (<field1> printer)
1040Entering state 3
1041Reading a token: Next token is token 'c' ('c' printer)
1042Shifting token 'c' ('c' printer)
1043Entering state 5
1044Reading a token: Next token is token 'd' ('d' printer)
1045Shifting token 'd' ('d' printer)
1046Entering state 6
1047Reading a token: Next token is token 'e' (<*>/<field2>/e printer)
1048Shifting token 'e' (<*>/<field2>/e printer)
1049Entering state 7
1050Reading a token: Next token is token 'f' (<*>/<field2>/e printer)
1051Shifting token 'f' (<*>/<field2>/e printer)
1052Entering state 8
1053Reading a token: Now at end of input.
1054syntax error, unexpected $end, expecting 'g'
1055Error: popping token 'f' (<*>/<field2>/e printer)
1056Stack now 0 1 3 5 6 7
1057Error: popping token 'e' (<*>/<field2>/e printer)
1058Stack now 0 1 3 5 6
1059Error: popping token 'd' ('d' printer)
1060Stack now 0 1 3 5
1061Error: popping token 'c' ('c' printer)
1062Stack now 0 1 3
1063Error: popping token 'b' (<field1> printer)
1064Stack now 0 1
1065Error: popping token 'a' (<*>/<field2>/e printer)
1066Stack now 0
1067Cleanup: discarding lookahead token $end ()
1068Stack now 0
1069]])
1070
1071AT_BISON_OPTION_POPDEFS
1072AT_CLEANUP
1073
1074
1075
1076## ------------------------------------------------------------- ##
1077## Default %printer and %destructor for user-defined end token. ##
1078## ------------------------------------------------------------- ##
1079
1080AT_SETUP([Default %printer and %destructor for user-defined end token])
1081
1082# AT_TEST(TYPED)
1083# --------------
1084m4_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
1089AT_BISON_OPTION_PUSHDEFS([%locations %debug])
1090AT_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
1124start: { $$ = 'S'; } ;
1125
1126%%
1127#include <stdlib.h> /* abort */
1128static int
1129yylex (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]])
1142AT_BISON_OPTION_POPDEFS
1143
1144AT_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]
1147input0.y:30.3-5: warning: useless %printer for type <*> [-Wother]
1148]],
1149[[input1.y:30.3-4: warning: useless %destructor for type <> [-Wother]
1150input1.y:30.3-4: warning: useless %printer for type <> [-Wother]
1151]])])
1152
1153AT_COMPILE([input$1])
1154
1155AT_PARSER_CHECK([./input$1 --debug], 0,
1156[[<]]kind[[> for 'E' @ 1.
1157<]]kind[[> for 'S' @ 1.
1158]],
1159[[Starting parse
1160Entering state 0
1161Reducing stack by rule 1 (line 49):
1162-> $$ = nterm start (1.1: <]]kind[[> for 'S' @ 1)
1163Stack now 0
1164Entering state 1
1165Reading a token: Now at end of input.
1166Shifting token END (1.1: <]]kind[[> for 'E' @ 1)
1167Entering state 2
1168Stack now 0 1 2
1169Cleanup: popping token END (1.1: <]]kind[[> for 'E' @ 1)
1170Cleanup: popping nterm start (1.1: <]]kind[[> for 'S' @ 1)
1171]])
1172
1173m4_popdef([kind])
1174m4_popdef([not_kind])
1175])
1176
1177AT_TEST(0)
1178AT_TEST(1)
1179
1180m4_popdef([AT_TEST])
1181
1182AT_CLEANUP
1183
1184
1185
1186## ------------------------------------------------------------------ ##
1187## Default %printer and %destructor are not for error or $undefined. ##
1188## ------------------------------------------------------------------ ##
1189
1190AT_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.
1200AT_BISON_OPTION_PUSHDEFS([%debug])
1201AT_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
1221start:
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]])
1233AT_BISON_OPTION_POPDEFS
1234
1235AT_BISON_CHECK([-o input.c input.y], [], [],
1236[[input.y:23.6-8: warning: useless %destructor for type <*> [-Wother]
1237input.y:23.6-8: warning: useless %printer for type <*> [-Wother]
1238]])
1239AT_COMPILE([input])
1240AT_PARSER_CHECK([./input --debug], [1], [],
1241[[Starting parse
1242Entering state 0
1243Reading a token: Next token is token 'a' ('a')
1244Shifting token 'a' ('a')
1245Entering state 1
1246Reading a token: Next token is token 'b' ('b')
1247syntax error
1248Shifting token error ()
1249Entering state 3
1250Next token is token 'b' ('b')
1251Shifting token 'b' ('b')
1252Entering state 5
1253Reading a token: Next token is token $undefined ()
1254Error: popping token 'b' ('b')
1255DESTROY 'b'
1256Stack now 0 1 3
1257Error: popping token error ()
1258Stack now 0 1
1259Shifting token error ()
1260Entering state 3
1261Next token is token $undefined ()
1262Error: discarding token $undefined ()
1263Error: popping token error ()
1264Stack now 0 1
1265Shifting token error ()
1266Entering state 3
1267Reading a token: Now at end of input.
1268Cleanup: discarding lookahead token $end ()
1269Stack now 0 1 3
1270Cleanup: popping token error ()
1271Cleanup: popping token 'a' ('a')
1272DESTROY 'a'
1273]])
1274
1275AT_CLEANUP
1276
1277
1278
1279## ------------------------------------------------------ ##
1280## Default %printer and %destructor are not for $accept. ##
1281## ------------------------------------------------------ ##
1282
1283AT_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
1298AT_BISON_OPTION_PUSHDEFS([%debug])
1299AT_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
1324start: { USE($$); } ;
1325
1326%%
1327]AT_YYERROR_DEFINE[
1328]AT_YYLEX_DEFINE[
1329]AT_MAIN_DEFINE[
1330]])
1331AT_BISON_OPTION_POPDEFS
1332
1333AT_BISON_CHECK([-o input.c input.y], [], [],
1334[[input.y:24.3-4: warning: useless %destructor for type <> [-Wother]
1335input.y:24.3-4: warning: useless %printer for type <> [-Wother]
1336]])
1337AT_COMPILE([input])
1338
1339AT_CLEANUP
1340
1341
1342
1343## ------------------------------------------------------ ##
1344## Default %printer and %destructor for mid-rule values. ##
1345## ------------------------------------------------------ ##
1346
1347AT_SETUP([Default %printer and %destructor for mid-rule values])
1348
1349AT_BISON_OPTION_PUSHDEFS([%debug])
1350AT_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
1369start:
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]])
1383AT_BISON_OPTION_POPDEFS
1384
1385AT_BISON_CHECK([-o input.c input.y], 0,,
1386[[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
1387input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
1388input.y:33.3-23: warning: unset value: $$ [-Wother]
1389input.y:32.3-23: warning: unused value: $3 [-Wother]
1390]])
1391
1392AT_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 ^^^
1396input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
1397 %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1398 ^^^
1399input.y:33.3-23: warning: unset value: $$ [-Wother]
1400 { @$ = 4; } // Only used.
1401 ^^^^^^^^^^^^^^^^^^^^^
1402input.y:32.3-23: warning: unused value: $3 [-Wother]
1403 { USE ($$); @$ = 3; } // Only set.
1404 ^^^^^^^^^^^^^^^^^^^^^
1405]])
1406
1407AT_COMPILE([input])
1408AT_PARSER_CHECK([./input --debug], 1,,
1409[[Starting parse
1410Entering state 0
1411Reducing stack by rule 1 (line 30):
1412-> $$ = nterm $@1 (: )
1413Stack now 0
1414Entering state 2
1415Reducing stack by rule 2 (line 31):
1416-> $$ = nterm @2 (: 2)
1417Stack now 0 2
1418Entering state 4
1419Reducing stack by rule 3 (line 32):
1420-> $$ = nterm @3 (: 3)
1421Stack now 0 2 4
1422Entering state 5
1423Reducing stack by rule 4 (line 33):
1424-> $$ = nterm @4 (: 4)
1425Stack now 0 2 4 5
1426Entering state 6
1427Reading a token: Now at end of input.
1428syntax error
1429Error: popping nterm @4 (: 4)
1430DESTROY 4
1431Stack now 0 2 4 5
1432Error: popping nterm @3 (: 3)
1433DESTROY 3
1434Stack now 0 2 4
1435Error: popping nterm @2 (: 2)
1436DESTROY 2
1437Stack now 0 2
1438Error: popping nterm $@1 (: )
1439Stack now 0
1440Cleanup: discarding lookahead token $end (: )
1441Stack now 0
1442]])
1443
1444AT_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# -------------------------------------------
1455m4_define([AT_CHECK_ACTION_LOCATIONS],
1456[AT_SETUP([[@$ in ]$1[ implies %locations]])
1457AT_BISON_OPTION_PUSHDEFS([%debug])
1458AT_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
1473start: ;
1474
1475%%
1476
1477static int
1478yylex (void)
1479{
1480 return 0;
1481}
1482
1483]AT_YYERROR_DEFINE[
1484]AT_MAIN_DEFINE[
1485]])
1486
1487AT_BISON_CHECK([[-o input.c input.y]])
1488AT_COMPILE([[input]])
1489AT_BISON_OPTION_POPDEFS
1490AT_CLEANUP])
1491
1492AT_CHECK_ACTION_LOCATIONS([[%initial-action]])
1493AT_CHECK_ACTION_LOCATIONS([[%destructor]])
1494AT_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
1513m4_pushdef([AT_TEST],
1514[AT_SETUP([[Qualified $$ in actions: $1]])
1515
1516AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %debug])
1517
1518AT_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%%
1568float: 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
1583AT_FULL_COMPILE([[input]])
1584AT_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.
1587AT_CHECK([[sed -ne '/ival:/p' stderr]], 0,
1588[[Reading a token: Next token is token UNTYPED (ival: 10, fval: 0.1)
1589Shifting token UNTYPED (ival: 10, fval: 0.1)
1590Reading a token: Next token is token INT (ival: 20, fval: 0.2)
1591Shifting 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)
1595Cleanup: popping nterm float (ival: 30, fval: 0.3)
1596]])
1597
1598AT_BISON_OPTION_POPDEFS
1599
1600AT_CLEANUP
1601])
1602
1603AT_TEST([yacc.c])
1604AT_TEST([glr.c])
1605AT_TEST([lalr1.cc])
1606AT_TEST([glr.cc])
1607
1608m4_popdef([AT_TEST])
1609
1610## -------------------------------------------------- ##
1611## Destroying lookahead assigned by semantic action. ##
1612## -------------------------------------------------- ##
1613
1614AT_SETUP([[Destroying lookahead assigned by semantic action]])
1615
1616AT_BISON_OPTION_PUSHDEFS
1617AT_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.
1643start: 'a' accept { USE($1); } ;
1644accept: %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]])
1655AT_BISON_OPTION_POPDEFS
1656AT_BISON_CHECK([[-o input.c input.y]])
1657AT_COMPILE([[input]])
1658AT_PARSER_CHECK([[./input]], [[0]], [],
1659[['b' destructor
1660'a' destructor
1661]])
1662
1663AT_CLEANUP
1664
1665## ---------- ##
1666## YYBACKUP. ##
1667## ---------- ##
1668
1669AT_SETUP([[YYBACKUP]])
1670
1671AT_BISON_OPTION_PUSHDEFS([%pure-parser %debug])
1672
1673AT_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%%
1687input:
1688 exp exp {}
1689;
1690
1691exp:
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]])
1702AT_BISON_OPTION_POPDEFS
1703
1704AT_BISON_CHECK([[-o input.c input.y]])
1705AT_COMPILE([[input]])
1706AT_PARSER_CHECK([[./input]], [[0]],
1707[[a: 123
1708a: 456
1709]])
1710
1711AT_CLEANUP