]> git.saurik.com Git - bison.git/blame - tests/actions.at
tests: minor change to make it easier to test other skeletons
[bison.git] / tests / actions.at
CommitLineData
9534d2be 1e# Executing Actions. -*- Autotest -*-
7d424de1 2
7d6bad19 3# Copyright (C) 2001-2013 Free Software Foundation, Inc.
82c035a8 4
f16b0819 5# This program is free software: you can redistribute it and/or modify
82c035a8 6# it under the terms of the GNU General Public License as published by
f16b0819
PE
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
82c035a8
AD
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.
f16b0819 14#
82c035a8 15# You should have received a copy of the GNU General Public License
f16b0819 16# along with this program. If not, see <http://www.gnu.org/licenses/>.
82c035a8
AD
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
55f48c48 31AT_BISON_OPTION_PUSHDEFS
9501dc6e 32AT_DATA_GRAMMAR([[input.y]],
cf499cff 33[[%define parse.error verbose
8f3596a6 34%debug
f0f95a50 35%code {
55f48c48
AD
36]AT_YYERROR_DECLARE[
37]AT_YYLEX_DECLARE[
f0f95a50 38}
82c035a8 39%%
931394cb
AD
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'); }
82c035a8
AD
51 ;
52%%
55f48c48 53]AT_YYERROR_DEFINE[
95361618 54]AT_YYLEX_DEFINE(["123456789"])[
3ef9fa8f 55]AT_MAIN_DEFINE[
82c035a8 56]])
55f48c48 57AT_BISON_OPTION_POPDEFS
82c035a8 58
da730230 59AT_BISON_CHECK([-d -v -o input.c input.y])
1154cced
AD
60AT_COMPILE([input])
61AT_PARSER_CHECK([./input], 0,
931394cb 62[[0123456789
82c035a8
AD
63]])
64
65AT_CLEANUP
75d1fe16 66
f68a49ed
AD
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
42d101da
AD
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
f68a49ed
AD
106AT_CLEANUP
107
ae2b48f5
AD
108## ------------------------ ##
109## Invalid uses of %empty. ##
110## ------------------------ ##
111
112AT_SETUP([Invalid uses of %empty])
113
114AT_DATA_GRAMMAR([[one.y]],
115[[%%
116exp:
0fe5a72a 117 %empty {} %empty
ae2b48f5
AD
118;
119]])
120
121AT_BISON_CHECK([-fcaret one.y], [1], [],
0fe5a72a
AD
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 ^^^^^^
ae2b48f5
AD
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
75d1fe16 180
a1d1ab50
AD
181## ------------------ ##
182## Initial location. ##
183## ------------------ ##
184
fb4c8a7c
TR
185# AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES], [LOCATION = 1.1])
186# -----------------------------------------------------------------------
63951be2 187# Check that the initial location is correct.
a1d1ab50
AD
188m4_pushdef([AT_TEST],
189[AT_SETUP([Initial location: $1 $2])
190
6428a8a4 191AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
a1d1ab50 192AT_DATA_GRAMMAR([[input.y]],
66fb016e 193[[%locations
a1d1ab50
AD
194%debug
195%skeleton "$1"
fb4c8a7c
TR
196]$2[
197]$3[
a1d1ab50
AD
198%code
199{
200# include <stdio.h>
1127a75a 201# include <stdlib.h> /* getenv */
a1d1ab50
AD
202]AT_YYERROR_DECLARE[
203]AT_YYLEX_DECLARE[
204}
205%%
206exp: { ]AT_SKEL_CC_IF([[std::cerr << @$ << std::endl]],
f0f95a50 207 [[LOCATION_PRINT(stderr, @$); fputc ('\n', stderr)]])[; }
a1d1ab50
AD
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([[
6428a8a4 223 yy::parser p;
a1d1ab50
AD
224 p.set_debug_level (!!getenv("YYDEBUG"));
225 return p.parse ();]], [[
226 yydebug = !!getenv("YYDEBUG");
6428a8a4 227 return !!yyparse (]AT_PARAM_IF([0])[);]])[
a1d1ab50
AD
228}
229]])
230
231AT_FULL_COMPILE([input])
232AT_PARSER_CHECK([./input], 1, [],
fb4c8a7c
TR
233[m4_default([$4], [1.1])
234m4_default([$4], [1.1])[: syntax error
a1d1ab50
AD
235]])
236AT_BISON_OPTION_POPDEFS
237AT_CLEANUP
238])
239
240## FIXME: test Java, and iterate over skeletons.
241AT_TEST([yacc.c])
6428a8a4
TR
242AT_TEST([yacc.c], [%define api.pure full])
243AT_TEST([yacc.c], [%define api.pure %parse-param { int x }])
a1d1ab50 244AT_TEST([yacc.c], [%define api.push-pull both])
6428a8a4 245AT_TEST([yacc.c], [%define api.push-pull both %define api.pure full])
a1d1ab50 246AT_TEST([glr.c])
6428a8a4 247AT_TEST([glr.c], [%define api.pure])
a1d1ab50
AD
248AT_TEST([lalr1.cc])
249AT_TEST([glr.cc])
250
fb4c8a7c
TR
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.
6428a8a4 258AT_TEST([yacc.c], [%define api.pure full],
fb4c8a7c
TR
259[[%{
260# define YYLTYPE int
f0f95a50 261# define LOCATION_PRINT(Stream, Loc) \
fb4c8a7c
TR
262 (void) (Loc)
263# define YYLLOC_DEFAULT(Current, Rhs, N) \
264 (Current) = ((Rhs)[N ? 1 : 0])
265%}
266]],
267[@&t@])
268
6428a8a4 269AT_TEST([yacc.c], [%define api.pure full],
fb4c8a7c
TR
270[[%{
271# define YYLTYPE int
f0f95a50 272# define LOCATION_PRINT(Stream, Loc) \
fb4c8a7c
TR
273 fprintf ((Stream), "%d", (Loc))
274# define YYLLOC_DEFAULT(Current, Rhs, N) \
275 (Current) = ((Rhs)[N ? 1 : 0])
276%}
277]],
278[0])
279
280
a1d1ab50 281m4_popdef([AT_TEST])
75d1fe16 282
5dac0025
PE
283
284
3804aa26
AD
285## ---------------- ##
286## Location Print. ##
287## ---------------- ##
288
edaa22ec
AD
289# AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES])
290# -----------------------------------------------------
3804aa26
AD
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]],
66fb016e 297[[%locations
3804aa26
AD
298%debug
299%skeleton "$1"
300]$2[
301]$3[
302%code
303{
3804aa26
AD
304]AT_YYERROR_DECLARE[
305]AT_YYLEX_DECLARE[
306}
307%%
684083f0 308exp: %empty;
3804aa26
AD
309%%
310]AT_YYERROR_DEFINE[
311]AT_YYLEX_DEFINE[
312
313int
314main (void)
315{
aedcb6c0
AD
316 ]AT_YYLTYPE[ loc;
317]AT_GLR_CC_IF([loc.initialize();])[
3804aa26 318#define TEST(L1, C1, L2, C2) \
aedcb6c0
AD
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],
f0f95a50 324 [LOCATION_PRINT(stdout, loc)])[;\
3804aa26
AD
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);
1127a75a 334 return 0;
3804aa26
AD
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])
aedcb6c0
AD
354AT_TEST([lalr1.cc])
355AT_TEST([glr.cc])
3804aa26
AD
356
357m4_popdef([AT_TEST])
358
359
360
75d1fe16
AD
361## ---------------- ##
362## Exotic Dollars. ##
363## ---------------- ##
364
365AT_SETUP([Exotic Dollars])
366
55f48c48 367AT_BISON_OPTION_PUSHDEFS
9501dc6e 368AT_DATA_GRAMMAR([[input.y]],
cf499cff 369[[%define parse.error verbose
8f3596a6 370%debug
f0f95a50 371%code {
55f48c48
AD
372]AT_YYERROR_DECLARE[
373]AT_YYLEX_DECLARE[
affac613 374# define USE(Var)
f0f95a50 375}
75d1fe16
AD
376
377%union
378{
379 int val;
380};
381
0ff67d71 382%type <val> a_1 a_2 a_5
378f4bd8 383 sum_of_the_five_previous_values
75d1fe16
AD
384
385%%
0ff67d71
PE
386exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
387 sum_of_the_five_previous_values
75d1fe16 388 {
84866159 389 USE (($1, $2, $<foo>3, $<foo>4, $5));
75d1fe16
AD
390 printf ("%d\n", $6);
391 }
392;
393a_1: { $$ = 1; };
394a_2: { $$ = 2; };
75d1fe16
AD
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%%
55f48c48 404]AT_YYERROR_DEFINE[
95361618 405]AT_YYLEX_DEFINE[
3ef9fa8f 406]AT_MAIN_DEFINE[
75d1fe16
AD
407]])
408
da730230 409AT_BISON_CHECK([-d -v -o input.c input.y], 0)
1154cced
AD
410AT_COMPILE([input])
411AT_PARSER_CHECK([./input], 0,
75d1fe16
AD
412[[15
413]])
414
82f3355e
JD
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%{
55f48c48
AD
421]AT_YYERROR_DECLARE[
422]AT_YYLEX_DECLARE[
82f3355e
JD
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%%
55f48c48 434]AT_YYERROR_DEFINE[
95361618 435]AT_YYLEX_DEFINE[
3ef9fa8f 436]AT_MAIN_DEFINE[
82f3355e
JD
437]])
438
3112e7a8 439AT_FULL_COMPILE([input])
82f3355e
JD
440AT_PARSER_CHECK([[./input]], [[0]],
441[[6
442]])
443
55f48c48 444AT_BISON_OPTION_POPDEFS
75d1fe16 445AT_CLEANUP
9280d3ef
AD
446
447
448
e776192e
AD
449## -------------------------- ##
450## Printers and Destructors. ##
451## -------------------------- ##
9280d3ef 452
8d6c1b5e
AD
453# _AT_CHECK_PRINTER_AND_DESTRUCTOR($1, $2, $3, $4,
454# BISON-DIRECTIVE, UNION-FLAG)
455# -------------------------------------------------------------
3df37415 456m4_define([_AT_CHECK_PRINTER_AND_DESTRUCTOR],
9c66f418 457[# Make sure complex $n work.
8d6c1b5e 458m4_if([$1$2$3$4], $[1]$[2]$[3]$[4], [],
3df37415
AD
459 [m4_fatal([$0: Invalid arguments: $@])])dnl
460
9c66f418
AD
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.
c2729758 463AT_BISON_OPTION_PUSHDEFS([$5])
9501dc6e 464AT_DATA_GRAMMAR([[input.y]],
16dc6a9e 465[[%code requires {
9280d3ef
AD
466#include <stdio.h>
467#include <stdlib.h>
cf806753 468#include <string.h>
9c66f418 469#include <assert.h>
80ce3401
PE
470
471#define YYINITDEPTH 10
472#define YYMAXDEPTH 10
8d6c1b5e
AD
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}
9c66f418 480
8d6c1b5e
AD
481$5
482]m4_ifval([$6], [%union
9280d3ef
AD
483{
484 int ival;
ac700aa6 485}])
16dc6a9e
JD
486AT_LALR1_CC_IF([%define global_tokens_and_yystype])
487m4_ifval([$6], [[%code provides {]], [[%code {]])
230a3db4
AD
488AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])[
489]AT_YYLEX_DECLARE[
55f48c48 490]AT_LALR1_CC_IF([], [AT_YYERROR_DECLARE])
9bc0dd67 491[}
c2729758 492
868d2d96 493]m4_ifval([$6], [%type <ival> '(' 'x' 'y' ')' ';' thing line input END])[
e3170060 494
868d2d96 495/* FIXME: This %printer isn't actually tested. */
a5eb1ed2
AD
496%printer
497 {
9a1e9989 498 ]AT_LALR1_CC_IF([debug_stream () << $$;],
3fc16193 499 [fprintf (yyoutput, "%d", $$)])[;
a5eb1ed2 500 }
9c66f418 501 input line thing 'x' 'y'
e3170060
AD
502
503%destructor
8d6c1b5e 504 { fprintf (stderr, "Freeing nterm input (%d@%d-%d)\n", $$, RANGE (@$)); }
7bd6c77e 505 input
5719c109 506
7bd6c77e 507%destructor
8d6c1b5e 508 { fprintf (stderr, "Freeing nterm line (%d@%d-%d)\n", $$, RANGE (@$)); }
7bd6c77e
AD
509 line
510
511%destructor
8d6c1b5e 512 { fprintf (stderr, "Freeing nterm thing (%d@%d-%d)\n", $$, RANGE (@$)); }
7bd6c77e
AD
513 thing
514
515%destructor
8d6c1b5e 516 { fprintf (stderr, "Freeing token 'x' (%d@%d-%d)\n", $$, RANGE (@$)); }
7bd6c77e 517 'x'
5719c109 518
9c66f418 519%destructor
8d6c1b5e 520 { fprintf (stderr, "Freeing token 'y' (%d@%d-%d)\n", $$, RANGE (@$)); }
9c66f418
AD
521 'y'
522
868d2d96
JD
523%token END 0
524%destructor
8d6c1b5e 525 { fprintf (stderr, "Freeing token END (%d@%d-%d)\n", $$, RANGE (@$)); }
868d2d96
JD
526 END
527
9280d3ef 528%%
9c66f418
AD
529/*
530 This grammar is made to exercise error recovery.
4c9b8f13 531 "Lines" starting with '(' support error recovery, with
9c66f418
AD
532 ')' as synchronizing token. Lines starting with 'x' can never
533 be recovered from if in error.
534*/
535
9280d3ef
AD
536input:
537 /* Nothing. */
5719c109
AD
538 {
539 $$ = 0;
8d6c1b5e 540 V(input, $$, @$, ": /* Nothing */\n");
5719c109
AD
541 }
542| line input /* Right recursive to load the stack so that popping at
e9690142 543 END can be exercised. */
5719c109
AD
544 {
545 $$ = 2;
8d6c1b5e
AD
546 V(input, $$, @$, ": ");
547 V(line, $1, @1, " ");
548 V(input, $2, @2, "\n");
5719c109 549 }
9280d3ef
AD
550;
551
552line:
553 thing thing thing ';'
5719c109
AD
554 {
555 $$ = $1;
8d6c1b5e
AD
556 V(line, $$, @$, ": ");
557 V(thing, $1, @1, " ");
558 V(thing, $2, @2, " ");
559 V(thing, $3, @3, " ");
560 V(;, $4, @4, "\n");
5719c109 561 }
9c66f418 562| '(' thing thing ')'
5719c109
AD
563 {
564 $$ = $1;
8d6c1b5e
AD
565 V(line, $$, @$, ": ");
566 V('(', $1, @1, " ");
567 V(thing, $2, @2, " ");
568 V(thing, $3, @3, " ");
569 V(')', $4, @4, "\n");
5719c109 570 }
9c66f418 571| '(' thing ')'
5719c109
AD
572 {
573 $$ = $1;
8d6c1b5e
AD
574 V(line, $$, @$, ": ");
575 V('(', $1, @1, " ");
576 V(thing, $2, @2, " ");
577 V(')', $3, @3, "\n");
5719c109 578 }
9c66f418 579| '(' error ')'
5719c109
AD
580 {
581 $$ = -1;
8d6c1b5e
AD
582 V(line, $$, @$, ": ");
583 V('(', $1, @1, " ");
584 fprintf (stderr, "error (@%d-%d) ", RANGE(@2));
585 V(')', $3, @3, "\n");
5719c109 586 }
9280d3ef
AD
587;
588
589thing:
5719c109
AD
590 'x'
591 {
592 $$ = $1;
8d6c1b5e
AD
593 V(thing, $$, @$, ": ");
594 V('x', $1, @1, "\n");
5719c109 595 }
9280d3ef
AD
596;
597%%
9c66f418 598/* Alias to ARGV[1]. */
ef51bfa7 599const char *source = YY_NULL;
9c66f418 600
8d6c1b5e
AD
601]AT_YYERROR_DEFINE[
602
230a3db4
AD
603static
604]AT_YYLEX_PROTOTYPE[
9280d3ef 605{
5a08f1ce 606 static unsigned int counter = 0;
9280d3ef 607
7ba01e11 608 unsigned int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++;
9c66f418 609 /* As in BASIC, line numbers go from 10 to 10. */
8d6c1b5e
AD
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;
7ba01e11 612 assert (c <= strlen (source));
a9739e7c 613 if (source[c])
8d6c1b5e 614 fprintf (stderr, "sending: '%c'", source[c]);
9280d3ef 615 else
8d6c1b5e
AD
616 fprintf (stderr, "sending: END");
617 fprintf (stderr, " (%d@%d-%d)\n", c, RANGE (]AT_LOC[));
a9739e7c 618 return source[c];
9280d3ef 619}
c2729758 620]AT_LALR1_CC_IF(
8d6c1b5e 621[static bool yydebug;
c2729758
ADL
622int
623yyparse ()
624{
99880de5 625 yy::parser parser;
a3cb6248 626 parser.set_debug_level (yydebug);
c2729758
ADL
627 return parser.parse ();
628}
8d6c1b5e 629])[
9280d3ef 630
9280d3ef 631int
9c66f418 632main (int argc, const char *argv[])
9280d3ef 633{
6100a9aa 634 int status;
9280d3ef 635 yydebug = !!getenv ("YYDEBUG");
9c66f418 636 assert (argc == 2);
a9739e7c 637 source = argv[1];
6100a9aa
PE
638 status = yyparse ();
639 switch (status)
9280d3ef 640 {
8d6c1b5e
AD
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;
9280d3ef 644 }
6100a9aa 645 return status;
9280d3ef
AD
646}
647]])
648
7ca2266a 649AT_FULL_COMPILE([input])
9c66f418
AD
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?
8d6c1b5e 657AT_PARSER_CHECK([./input '(x)'], 0, [],
9c66f418
AD
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)
868d2d96 663sending: END (3@30-39)
b4a20338
AD
664input (0@29-29): /* Nothing */
665input (2@0-29): line (0@0-29) input (0@29-29)
868d2d96 666Freeing token END (3@30-39)
258b75ca 667Freeing nterm input (2@0-29)
9c66f418
AD
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)').
8d6c1b5e 676AT_PARSER_CHECK([./input '(y)'], 0, [],
9c66f418
AD
677[[sending: '(' (0@0-9)
678sending: 'y' (1@10-19)
8d6c1b5e 67910.10-19.18: syntax error, unexpected 'y', expecting 'x'
9c66f418
AD
680Freeing token 'y' (1@10-19)
681sending: ')' (2@20-29)
682line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
868d2d96 683sending: END (3@30-39)
b4a20338
AD
684input (0@29-29): /* Nothing */
685input (2@0-29): line (-1@0-29) input (0@29-29)
868d2d96 686Freeing token END (3@30-39)
258b75ca 687Freeing nterm input (2@0-29)
9c66f418
AD
688Successful parse.
689]])
690
691
692# Syntax errors caught by the parser
693# ----------------------------------
4c9b8f13 694# Exercise the discarding of stack top and input until 'error'
9c66f418
AD
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'
8d6c1b5e 706AT_PARSER_CHECK([./input '(xxxxx)(x)(x)y'], 1, [],
9c66f418 707[[sending: '(' (0@0-9)
4c6cc1db
AD
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)
8d6c1b5e 71330.30-39.38: syntax error, unexpected 'x', expecting ')'
4c6cc1db
AD
714Freeing nterm thing (2@20-29)
715Freeing nterm thing (1@10-19)
4c6cc1db
AD
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)
9c66f418
AD
721sending: ')' (6@60-69)
722line (-1@0-69): '(' (0@0-9) error (@10-59) ')' (6@60-69)
723sending: '(' (7@70-79)
4c6cc1db
AD
724sending: 'x' (8@80-89)
725thing (8@80-89): 'x' (8@80-89)
9c66f418
AD
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)
b4a20338
AD
734input (0@129-129): /* Nothing */
735input (2@100-129): line (10@100-129) input (0@129-129)
9c66f418
AD
736input (2@70-129): line (7@70-99) input (2@100-129)
737input (2@0-129): line (-1@0-69) input (2@70-129)
8d6c1b5e 738130.130-139.138: syntax error, unexpected 'y', expecting END
9c66f418
AD
739Freeing nterm input (2@0-129)
740Freeing token 'y' (13@130-139)
5719c109 741Parsing FAILED.
9280d3ef
AD
742]])
743
868d2d96
JD
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'
8d6c1b5e 754AT_PARSER_CHECK([./input '(x)(x)x'], 1, [],
868d2d96
JD
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)
8d6c1b5e 76870.70-79.78: syntax error, unexpected END, expecting 'x'
868d2d96
JD
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
80ce3401
PE
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([
8d6c1b5e 782AT_PARSER_CHECK([./input '(x)(x)(x)(x)(x)(x)(x)'], 2, [],
80ce3401
PE
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)
8d6c1b5e 817200.200-209.208: memory exhausted
80ce3401
PE
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)
6100a9aa 825Parsing FAILED (status 2).
80ce3401
PE
826]])
827])
828
55f48c48
AD
829AT_BISON_OPTION_POPDEFS
830])# _AT_CHECK_PRINTER_AND_DESTRUCTOR
3df37415
AD
831
832
a14a26fa 833# AT_CHECK_PRINTER_AND_DESTRUCTOR([BISON-OPTIONS], [UNION-FLAG], [SKIP_FLAG])
046ac74e 834# ---------------------------------------------------------------------------
3df37415 835m4_define([AT_CHECK_PRINTER_AND_DESTRUCTOR],
623a5147 836[AT_SETUP([Printers and Destructors$2]m4_ifval([$1], [[: $1]]))
9c66f418 837
a14a26fa 838$3
9c66f418 839_AT_CHECK_PRINTER_AND_DESTRUCTOR($[1], $[2], $[3], $[4],
cf499cff 840[%define parse.error verbose
9c66f418
AD
841%debug
842%verbose
843%locations
844$1], [$2])
845
846AT_CLEANUP
3df37415
AD
847])
848
849
ac700aa6 850AT_CHECK_PRINTER_AND_DESTRUCTOR([])
7ba01e11 851AT_CHECK_PRINTER_AND_DESTRUCTOR([], [ with union])
046ac74e 852
fd19f271 853AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"])
7ba01e11 854AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"], [ with union])
046ac74e 855
1576d44d 856AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser])
7ba01e11 857AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [ with union])
ec5479ce
JD
858
859
860
12e35840
JD
861## ----------------------------------------- ##
862## Default tagless %printer and %destructor. ##
863## ----------------------------------------- ##
ec5479ce
JD
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
12e35840 868AT_SETUP([Default tagless %printer and %destructor])
f42c012f 869AT_BISON_OPTION_PUSHDEFS([%locations %debug])
ec5479ce 870AT_DATA_GRAMMAR([[input.y]],
cf499cff 871[[%define parse.error verbose
ec5479ce
JD
872%debug
873%locations
ec5479ce 874
f0f95a50 875%code {
55f48c48
AD
876]AT_YYLEX_DECLARE[
877]AT_YYERROR_DECLARE[
ec5479ce 878# define USE(SYM)
f0f95a50 879}
ec5479ce
JD
880
881%printer {
12e35840
JD
882 fprintf (yyoutput, "<*> printer should not be called.\n");
883} <*>
884
885%printer {
3ebecc24
JD
886 fprintf (yyoutput, "<> printer for '%c' @ %d", $$, @$.first_column);
887} <>
ec5479ce 888%destructor {
3ebecc24
JD
889 fprintf (stdout, "<> destructor for '%c' @ %d.\n", $$, @$.first_column);
890} <>
ec5479ce
JD
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
12e35840
JD
899%destructor {
900 fprintf (yyoutput, "<*> destructor should not be called.\n");
901} <*>
902
ec5479ce
JD
903%%
904
905start: 'a' 'b' 'c' 'd' 'e' { $$ = 'S'; USE(($1, $2, $3, $4, $5)); } ;
906
907%%
55f48c48 908]AT_YYERROR_DEFINE[
95361618 909]AT_YYLEX_DEFINE(["abcd"], [[yylval = res]])[
f42c012f 910]AT_MAIN_DEFINE[
ec5479ce
JD
911]])
912
9534d2be 913AT_BISON_CHECK([-o input.c input.y], [], [],
f0f95a50
AD
914[[input.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
915input.y:30.3-5: warning: useless %printer for type <*> [-Wother]
9534d2be 916]])
ec5479ce 917AT_COMPILE([input])
f42c012f 918AT_PARSER_CHECK([./input --debug], 1,
3ebecc24 919[[<> destructor for 'd' @ 4.
ec5479ce
JD
920'b'/'c' destructor for 'c' @ 3.
921'b'/'c' destructor for 'b' @ 2.
3ebecc24 922<> destructor for 'a' @ 1.
ec5479ce
JD
923]],
924[[Starting parse
925Entering state 0
3237f570
AD
926Reading a token: Next token is token 'a' (1.1: <> printer for 'a' @ 1)
927Shifting token 'a' (1.1: <> printer for 'a' @ 1)
ec5479ce 928Entering state 1
3237f570
AD
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)
ec5479ce 931Entering state 3
3237f570
AD
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)
ec5479ce 934Entering state 5
3237f570
AD
935Reading a token: Next token is token 'd' (1.4: <> printer for 'd' @ 4)
936Shifting token 'd' (1.4: <> printer for 'd' @ 4)
ec5479ce
JD
937Entering state 6
938Reading a token: Now at end of input.
7dbb8d8a 9391.5: syntax error, unexpected $end, expecting 'e'
3237f570 940Error: popping token 'd' (1.4: <> printer for 'd' @ 4)
ec5479ce 941Stack now 0 1 3 5
3237f570 942Error: popping token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
ec5479ce 943Stack now 0 1 3
3237f570 944Error: popping token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
ec5479ce 945Stack now 0 1
3237f570 946Error: popping token 'a' (1.1: <> printer for 'a' @ 1)
ec5479ce 947Stack now 0
3237f570 948Cleanup: discarding lookahead token $end (1.5: )
ec5479ce
JD
949Stack now 0
950]])
951
55f48c48 952AT_BISON_OPTION_POPDEFS
ec5479ce
JD
953AT_CLEANUP
954
955
956
12e35840
JD
957## ------------------------------------------------------ ##
958## Default tagged and per-type %printer and %destructor. ##
959## ------------------------------------------------------ ##
b2a0b7ca 960
12e35840 961AT_SETUP([Default tagged and per-type %printer and %destructor])
f42c012f 962AT_BISON_OPTION_PUSHDEFS([%debug])
b2a0b7ca 963AT_DATA_GRAMMAR([[input.y]],
cf499cff 964[[%define parse.error verbose
b2a0b7ca
JD
965%debug
966
967%{
55f48c48
AD
968]AT_YYERROR_DECLARE[
969]AT_YYLEX_DECLARE[
b2a0b7ca
JD
970# define USE(SYM)
971%}
972
12e35840 973%printer {
3ebecc24
JD
974 fprintf (yyoutput, "<> printer should not be called.\n");
975} <>
12e35840 976
b2a0b7ca
JD
977%union { int field0; int field1; int field2; }
978%type <field0> start 'a' 'g'
979%type <field1> 'e'
980%type <field2> 'f'
981%printer {
12e35840
JD
982 fprintf (yyoutput, "<*>/<field2>/e printer");
983} <*> 'e' <field2>
b2a0b7ca 984%destructor {
12e35840
JD
985 fprintf (stdout, "<*>/<field2>/e destructor.\n");
986} <*> 'e' <field2>
b2a0b7ca
JD
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
12e35840 1000%destructor {
3ebecc24
JD
1001 fprintf (yyoutput, "<> destructor should not be called.\n");
1002} <>
12e35840 1003
b2a0b7ca
JD
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%%
55f48c48 1015]AT_YYERROR_DEFINE[
95361618 1016]AT_YYLEX_DEFINE(["abcdef"])[
f42c012f 1017]AT_MAIN_DEFINE[
b2a0b7ca
JD
1018]])
1019
9534d2be
AD
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]])
b2a0b7ca 1024AT_COMPILE([input])
f42c012f 1025AT_PARSER_CHECK([./input --debug], 1,
12e35840
JD
1026[[<*>/<field2>/e destructor.
1027<*>/<field2>/e destructor.
b2a0b7ca
JD
1028'd' destructor.
1029'c' destructor.
1030<field1> destructor.
12e35840 1031<*>/<field2>/e destructor.
b2a0b7ca
JD
1032]],
1033[[Starting parse
1034Entering state 0
12e35840
JD
1035Reading a token: Next token is token 'a' (<*>/<field2>/e printer)
1036Shifting token 'a' (<*>/<field2>/e printer)
b2a0b7ca
JD
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
12e35840
JD
1047Reading a token: Next token is token 'e' (<*>/<field2>/e printer)
1048Shifting token 'e' (<*>/<field2>/e printer)
b2a0b7ca 1049Entering state 7
12e35840
JD
1050Reading a token: Next token is token 'f' (<*>/<field2>/e printer)
1051Shifting token 'f' (<*>/<field2>/e printer)
b2a0b7ca
JD
1052Entering state 8
1053Reading a token: Now at end of input.
1054syntax error, unexpected $end, expecting 'g'
12e35840 1055Error: popping token 'f' (<*>/<field2>/e printer)
b2a0b7ca 1056Stack now 0 1 3 5 6 7
12e35840 1057Error: popping token 'e' (<*>/<field2>/e printer)
b2a0b7ca
JD
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
12e35840 1065Error: popping token 'a' (<*>/<field2>/e printer)
b2a0b7ca
JD
1066Stack now 0
1067Cleanup: discarding lookahead token $end ()
1068Stack now 0
1069]])
1070
55f48c48 1071AT_BISON_OPTION_POPDEFS
b2a0b7ca
JD
1072AT_CLEANUP
1073
1074
1075
ec5479ce 1076## ------------------------------------------------------------- ##
12e35840 1077## Default %printer and %destructor for user-defined end token. ##
ec5479ce
JD
1078## ------------------------------------------------------------- ##
1079
3508ce36 1080AT_SETUP([Default %printer and %destructor for user-defined end token])
ec5479ce 1081
9534d2be
AD
1082# AT_TEST(TYPED)
1083# --------------
1084m4_pushdef([AT_TEST],
12e35840 1085[m4_if($1, 0,
3ebecc24
JD
1086 [m4_pushdef([kind], []) m4_pushdef([not_kind], [*])],
1087 [m4_pushdef([kind], [*]) m4_pushdef([not_kind], [])])
12e35840 1088
f42c012f 1089AT_BISON_OPTION_PUSHDEFS([%locations %debug])
12e35840 1090AT_DATA_GRAMMAR([[input]]$1[[.y]],
cf499cff 1091[[%define parse.error verbose
ec5479ce
JD
1092%debug
1093%locations
ec5479ce 1094
f0f95a50 1095%code {
55f48c48
AD
1096]AT_YYERROR_DECLARE[
1097]AT_YYLEX_DECLARE[
ec5479ce 1098# define USE(SYM)
f0f95a50 1099}
ec5479ce 1100
12e35840
JD
1101%destructor {
1102 fprintf (yyoutput, "<]]not_kind[[> destructor should not be called.\n");
1103} <]]not_kind[[>
1104
ec5479ce
JD
1105%token END 0
1106%printer {
12e35840
JD
1107 fprintf (yyoutput, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
1108} <]]kind[[>
ec5479ce 1109%destructor {
12e35840
JD
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]]])[[
ec5479ce
JD
1121
1122%%
1123
1124start: { $$ = 'S'; } ;
1125
1126%%
312c0cff 1127#include <stdlib.h> /* abort */
ec5479ce
JD
1128static int
1129yylex (void)
1130{
cf806753
PE
1131 static int called;
1132 if (called++)
1133 abort ();
12e35840 1134 yylval]]m4_if($1, 0,, [[[.tag]]])[[ = 'E';
ec5479ce
JD
1135 yylloc.first_line = yylloc.last_line = 1;
1136 yylloc.first_column = yylloc.last_column = 1;
1137 return 0;
1138}
55f48c48 1139]AT_YYERROR_DEFINE[
f42c012f 1140]AT_MAIN_DEFINE[
ec5479ce 1141]])
55f48c48 1142AT_BISON_OPTION_POPDEFS
ec5479ce 1143
9534d2be
AD
1144AT_BISON_CHECK([-o input$1.c input$1.y], [], [],
1145[m4_if([$1], [0],
f0f95a50
AD
1146[[input0.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
1147input0.y:30.3-5: warning: useless %printer for type <*> [-Wother]
9534d2be 1148]],
f0f95a50
AD
1149[[input1.y:30.3-4: warning: useless %destructor for type <> [-Wother]
1150input1.y:30.3-4: warning: useless %printer for type <> [-Wother]
9534d2be
AD
1151]])])
1152
12e35840 1153AT_COMPILE([input$1])
9534d2be 1154
f42c012f 1155AT_PARSER_CHECK([./input$1 --debug], 0,
12e35840
JD
1156[[<]]kind[[> for 'E' @ 1.
1157<]]kind[[> for 'S' @ 1.
ec5479ce
JD
1158]],
1159[[Starting parse
1160Entering state 0
f0f95a50 1161Reducing stack by rule 1 (line 49):
3237f570 1162-> $$ = nterm start (1.1: <]]kind[[> for 'S' @ 1)
ec5479ce
JD
1163Stack now 0
1164Entering state 1
1165Reading a token: Now at end of input.
3237f570 1166Shifting token END (1.1: <]]kind[[> for 'E' @ 1)
ec5479ce
JD
1167Entering state 2
1168Stack now 0 1 2
3237f570
AD
1169Cleanup: popping token END (1.1: <]]kind[[> for 'E' @ 1)
1170Cleanup: popping nterm start (1.1: <]]kind[[> for 'S' @ 1)
ec5479ce
JD
1171]])
1172
12e35840
JD
1173m4_popdef([kind])
1174m4_popdef([not_kind])
1175])
1176
9534d2be
AD
1177AT_TEST(0)
1178AT_TEST(1)
1179
1180m4_popdef([AT_TEST])
12e35840 1181
ec5479ce 1182AT_CLEANUP
9350499c
JD
1183
1184
1185
1186## ------------------------------------------------------------------ ##
1187## Default %printer and %destructor are not for error or $undefined. ##
1188## ------------------------------------------------------------------ ##
1189
287b314e 1190AT_SETUP([Default %printer and %destructor are not for error or $undefined])
9350499c
JD
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.
f42c012f 1200AT_BISON_OPTION_PUSHDEFS([%debug])
9350499c
JD
1201AT_DATA_GRAMMAR([[input.y]],
1202[[%debug
1203
1204%{
1205# include <stdio.h>
cf806753 1206# include <stdlib.h>
55f48c48
AD
1207]AT_YYERROR_DECLARE[
1208]AT_YYLEX_DECLARE[
9350499c
JD
1209# define USE(SYM)
1210%}
1211
1212%printer {
1213 fprintf (yyoutput, "'%c'", $$);
3ebecc24 1214} <> <*>
9350499c
JD
1215%destructor {
1216 fprintf (stderr, "DESTROY '%c'\n", $$);
3ebecc24 1217} <> <*>
9350499c
JD
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%%
55f48c48 1229]AT_YYERROR_DEFINE[
95361618 1230]AT_YYLEX_DEFINE(["abd"], [yylval = res])[
f42c012f 1231]AT_MAIN_DEFINE[
9350499c 1232]])
55f48c48 1233AT_BISON_OPTION_POPDEFS
9350499c 1234
9534d2be 1235AT_BISON_CHECK([-o input.c input.y], [], [],
f0f95a50
AD
1236[[input.y:23.6-8: warning: useless %destructor for type <*> [-Wother]
1237input.y:23.6-8: warning: useless %printer for type <*> [-Wother]
9534d2be 1238]])
9350499c 1239AT_COMPILE([input])
f42c012f 1240AT_PARSER_CHECK([./input --debug], [1], [],
9350499c
JD
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
287b314e 1283AT_SETUP([Default %printer and %destructor are not for $accept])
9350499c
JD
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
4c9b8f13 1290# to declare '%type <field> $accept'. (Also true for $undefined.)
9350499c
JD
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
f42c012f 1298AT_BISON_OPTION_PUSHDEFS([%debug])
9350499c
JD
1299AT_DATA_GRAMMAR([[input.y]],
1300[[%debug /* So that %printer is actually compiled. */
1301
1302%{
1303# include <stdio.h>
cf806753 1304# include <stdlib.h>
55f48c48
AD
1305]AT_YYERROR_DECLARE[
1306]AT_YYLEX_DECLARE[
9350499c
JD
1307# define USE(SYM)
1308%}
1309
1310%printer {
1311 char chr = $$;
1312 fprintf (yyoutput, "'%c'", chr);
3ebecc24 1313} <> <*>
9350499c
JD
1314%destructor {
1315 char chr = $$;
1316 fprintf (stderr, "DESTROY '%c'\n", chr);
3ebecc24 1317} <> <*>
9350499c
JD
1318
1319%union { char chr; }
1320%type <chr> start
1321
1322%%
1323
1324start: { USE($$); } ;
1325
1326%%
55f48c48 1327]AT_YYERROR_DEFINE[
95361618 1328]AT_YYLEX_DEFINE[
3ef9fa8f 1329]AT_MAIN_DEFINE[
9350499c 1330]])
55f48c48 1331AT_BISON_OPTION_POPDEFS
9350499c 1332
9534d2be 1333AT_BISON_CHECK([-o input.c input.y], [], [],
f0f95a50
AD
1334[[input.y:24.3-4: warning: useless %destructor for type <> [-Wother]
1335input.y:24.3-4: warning: useless %printer for type <> [-Wother]
9534d2be 1336]])
9350499c
JD
1337AT_COMPILE([input])
1338
1339AT_CLEANUP
f91b1629
JD
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
f42c012f 1349AT_BISON_OPTION_PUSHDEFS([%debug])
f91b1629
JD
1350AT_DATA_GRAMMAR([[input.y]],
1351[[%debug /* So that %printer is actually compiled. */
1352
1353%{
55f48c48
AD
1354]AT_YYERROR_DECLARE[
1355]AT_YYLEX_DECLARE[
f91b1629
JD
1356# define USE(SYM)
1357# define YYLTYPE int
9fc4c025 1358# define YYLLOC_DEFAULT(Current, Rhs, N) (void)(Rhs)
f0f95a50 1359# define LOCATION_PRINT(File, Loc)
f91b1629
JD
1360%}
1361
3ebecc24
JD
1362%printer { fprintf (yyoutput, "%d", @$); } <>
1363%destructor { fprintf (stderr, "DESTROY %d\n", @$); } <>
12e35840
JD
1364%printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1365%destructor { fprintf (yyoutput, "<*> destructor should not be called"); } <*>
f91b1629
JD
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%%
55f48c48 1379]AT_YYERROR_DEFINE[
95361618 1380]AT_YYLEX_DEFINE[
f42c012f 1381]AT_MAIN_DEFINE[
f91b1629 1382]])
55f48c48 1383AT_BISON_OPTION_POPDEFS
f91b1629 1384
da730230 1385AT_BISON_CHECK([-o input.c input.y], 0,,
9534d2be
AD
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]
0906b12c 1389input.y:32.3-23: warning: unused value: $3 [-Wother]
f91b1629
JD
1390]])
1391
505ece51 1392AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
f3ead217
TR
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]
505ece51
TR
1400 { @$ = 4; } // Only used.
1401 ^^^^^^^^^^^^^^^^^^^^^
0906b12c 1402input.y:32.3-23: warning: unused value: $3 [-Wother]
23589235
AD
1403 { USE ($$); @$ = 3; } // Only set.
1404 ^^^^^^^^^^^^^^^^^^^^^
505ece51
TR
1405]])
1406
f91b1629 1407AT_COMPILE([input])
f42c012f 1408AT_PARSER_CHECK([./input --debug], 1,,
f91b1629
JD
1409[[Starting parse
1410Entering state 0
12e35840 1411Reducing stack by rule 1 (line 30):
f91b1629
JD
1412-> $$ = nterm $@1 (: )
1413Stack now 0
1414Entering state 2
12e35840 1415Reducing stack by rule 2 (line 31):
f91b1629
JD
1416-> $$ = nterm @2 (: 2)
1417Stack now 0 2
1418Entering state 4
12e35840 1419Reducing stack by rule 3 (line 32):
f91b1629
JD
1420-> $$ = nterm @3 (: 3)
1421Stack now 0 2 4
1422Entering state 5
12e35840 1423Reducing stack by rule 4 (line 33):
f91b1629
JD
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
e785ccf7
JD
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)
55f48c48 1454# -------------------------------------------
e785ccf7
JD
1455m4_define([AT_CHECK_ACTION_LOCATIONS],
1456[AT_SETUP([[@$ in ]$1[ implies %locations]])
f42c012f 1457AT_BISON_OPTION_PUSHDEFS([%debug])
e785ccf7
JD
1458AT_DATA_GRAMMAR([[input.y]],
1459[[%code {
1460 #include <stdio.h>
55f48c48
AD
1461]AT_YYERROR_DECLARE[
1462]AT_YYLEX_DECLARE[
e785ccf7
JD
1463}
1464
1465%debug
1466
1467]$1[ {
8d6c1b5e 1468 fprintf (stderr, "%d\n", @$.first_line);
e785ccf7
JD
1469} ]m4_if($1, [%initial-action], [], [[start]])[
1470
1471%%
1472
1473start: ;
1474
1475%%
1476
1477static int
1478yylex (void)
1479{
1480 return 0;
1481}
1482
55f48c48 1483]AT_YYERROR_DEFINE[
3ef9fa8f 1484]AT_MAIN_DEFINE[
e785ccf7
JD
1485]])
1486
da730230 1487AT_BISON_CHECK([[-o input.c input.y]])
e785ccf7 1488AT_COMPILE([[input]])
55f48c48 1489AT_BISON_OPTION_POPDEFS
e785ccf7
JD
1490AT_CLEANUP])
1491
1492AT_CHECK_ACTION_LOCATIONS([[%initial-action]])
1493AT_CHECK_ACTION_LOCATIONS([[%destructor]])
1494AT_CHECK_ACTION_LOCATIONS([[%printer]])
e8cd1ad6
DJ
1495
1496
4982f078
AD
1497## ------------------------- ##
1498## Qualified $$ in actions. ##
1499## ------------------------- ##
1500
3edfae04
AD
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.
4982f078 1504#
3edfae04 1505# FIXME: Not actually checking %destructor, but it's the same code as
4982f078
AD
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
f42c012f 1516AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %debug])
4982f078
AD
1517
1518AT_DATA_GRAMMAR([[input.y]],
1519[[%skeleton "$1"
4982f078
AD
1520%debug
1521%code requires
1522{
4982f078
AD
1523 typedef struct sem_type
1524 {
1525 int ival;
1526 float fval;
1527 } sem_type;
1528
1529# define YYSTYPE sem_type
1530
4acc22e5 1531]AT_SKEL_CC_IF([[
4982f078
AD
1532# include <iostream>
1533 static void
1534 report (std::ostream& yyo, int ival, float fval)
1535 {
1536 yyo << "ival: " << ival << ", fval: " << fval;
1537 }
4acc22e5
AD
1538]], [[
1539# include <stdio.h>
4982f078
AD
1540 static void
1541 report (FILE* yyo, int ival, float fval)
1542 {
1543 fprintf (yyo, "ival: %d, fval: %1.1f", ival, fval);
1544 }
4acc22e5 1545]])[
4982f078
AD
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
cd735a8c
AD
1561%initial-action
1562{
1563 $<ival>$ = 42;
1564 $<fval>$ = 4.2;
1565}
4982f078
AD
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;])[
f42c012f 1580]AT_MAIN_DEFINE[
4982f078
AD
1581]])
1582
1583AT_FULL_COMPILE([[input]])
f42c012f 1584AT_PARSER_CHECK([./input --debug], 0, [], [stderr])
4982f078
AD
1585# Don't be too picky on the traces, GLR is not exactly the same. Keep
1586# only the lines from the printer.
34904c57 1587AT_CHECK([[sed -ne '/ival:/p' stderr]], 0,
4982f078
AD
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
df222dfa
JD
1610## -------------------------------------------------- ##
1611## Destroying lookahead assigned by semantic action. ##
1612## -------------------------------------------------- ##
1613
1614AT_SETUP([[Destroying lookahead assigned by semantic action]])
1615
55f48c48 1616AT_BISON_OPTION_PUSHDEFS
df222dfa
JD
1617AT_DATA_GRAMMAR([input.y],
1618[[
1619%code {
1620 #include <assert.h>
1621 #include <stdio.h>
55f48c48
AD
1622]AT_YYERROR_DECLARE[
1623]AT_YYLEX_DECLARE[
df222dfa
JD
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); } ;
684083f0 1644accept: %empty {
df222dfa
JD
1645 assert (yychar == YYEMPTY);
1646 yychar = 'b';
1647 YYACCEPT;
1648} ;
1649
1650%%
55f48c48 1651]AT_YYERROR_DEFINE[
95361618 1652]AT_YYLEX_DEFINE(["a"])[
3ef9fa8f 1653]AT_MAIN_DEFINE[
df222dfa 1654]])
55f48c48 1655AT_BISON_OPTION_POPDEFS
df222dfa
JD
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
d115aad9
AD
1664
1665## ---------- ##
1666## YYBACKUP. ##
1667## ---------- ##
1668
1669AT_SETUP([[YYBACKUP]])
1670
f42c012f 1671AT_BISON_OPTION_PUSHDEFS([%pure-parser %debug])
55f48c48 1672
d115aad9
AD
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
55f48c48 1683 ]AT_YYERROR_DECLARE[
087dcd78 1684 ]AT_YYLEX_DECLARE[
d115aad9
AD
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%%
55f48c48 1698]AT_YYERROR_DEFINE[
087dcd78 1699]AT_YYLEX_DEFINE(["bcd"], [*lvalp = (toknum + 1) * 10])[
3ef9fa8f 1700]AT_MAIN_DEFINE[
d115aad9 1701]])
55f48c48 1702AT_BISON_OPTION_POPDEFS
d115aad9
AD
1703
1704AT_BISON_CHECK([[-o input.c input.y]])
1705AT_COMPILE([[input]])
1706AT_PARSER_CHECK([[./input]], [[0]],
1707[[a: 123
1708a: 456
d115aad9
AD
1709]])
1710
1711AT_CLEANUP