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