]> git.saurik.com Git - bison.git/blame - tests/actions.at
tests: improve factoring of the main function
[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
AD
34%debug
35%{
55f48c48
AD
36]AT_YYERROR_DECLARE[
37]AT_YYLEX_DECLARE[
82c035a8
AD
38%}
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]],
95 [[YY_LOCATION_PRINT(stderr, @$); fputc ('\n', stderr)]])[; }
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
149# define YY_LOCATION_PRINT(Stream, Loc) \
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
160# define YY_LOCATION_PRINT(Stream, Loc) \
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{
193# include <stdio.h>
1127a75a 194# include <stdlib.h> /* getenv */
3804aa26
AD
195]AT_YYERROR_DECLARE[
196]AT_YYLEX_DECLARE[
197}
198%%
199exp:;
200%%
201]AT_YYERROR_DEFINE[
202]AT_YYLEX_DEFINE[
203
204int
205main (void)
206{
207#define TEST(L1, C1, L2, C2) \
208 ]AT_LOC_FIRST_LINE[ = L1; \
209 ]AT_LOC_FIRST_COLUMN[ = C1; \
210 ]AT_LOC_LAST_LINE[ = L2; \
211 ]AT_LOC_LAST_COLUMN[ = C2; \
212 ]YY_LOCATION_PRINT(stdout, AT_LOC)[;\
213 putchar ('\n');
214
215 TEST(1, 1, 1, 1);
216 TEST(2, 1, 2, 10);
217 TEST(3, 1, 4, 1);
218 TEST(5, 1, 6, 10);
219
220 TEST(7, 2, 0, 2);
221 TEST(8, 0, 8, 0);
1127a75a 222 return 0;
3804aa26
AD
223}
224]])
225
226AT_FULL_COMPILE([input])
227AT_PARSER_CHECK([./input], 0,
228[[1.1
2292.1-9
2303.1-4.0
2315.1-6.9
2327.2
2338.0
234]])
235AT_BISON_OPTION_POPDEFS
236AT_CLEANUP
237])
238
239## FIXME: test Java, and iterate over skeletons.
240AT_TEST([yacc.c])
241AT_TEST([glr.c])
242#AT_TEST([lalr1.cc])
243#AT_TEST([glr.cc])
244
245m4_popdef([AT_TEST])
246
247
248
75d1fe16
AD
249## ---------------- ##
250## Exotic Dollars. ##
251## ---------------- ##
252
253AT_SETUP([Exotic Dollars])
254
55f48c48 255AT_BISON_OPTION_PUSHDEFS
9501dc6e 256AT_DATA_GRAMMAR([[input.y]],
cf499cff 257[[%define parse.error verbose
8f3596a6
AD
258%debug
259%{
55f48c48
AD
260]AT_YYERROR_DECLARE[
261]AT_YYLEX_DECLARE[
affac613 262# define USE(Var)
75d1fe16
AD
263%}
264
265%union
266{
267 int val;
268};
269
0ff67d71 270%type <val> a_1 a_2 a_5
378f4bd8 271 sum_of_the_five_previous_values
75d1fe16
AD
272
273%%
0ff67d71
PE
274exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
275 sum_of_the_five_previous_values
75d1fe16 276 {
84866159 277 USE (($1, $2, $<foo>3, $<foo>4, $5));
75d1fe16
AD
278 printf ("%d\n", $6);
279 }
280;
281a_1: { $$ = 1; };
282a_2: { $$ = 2; };
75d1fe16
AD
283a_5: { $$ = 5; };
284
285sum_of_the_five_previous_values:
286 {
287 $$ = $<val>0 + $<val>-1 + $<val>-2 + $<val>-3 + $<val>-4;
288 }
289;
290
291%%
55f48c48 292]AT_YYERROR_DEFINE[
95361618 293]AT_YYLEX_DEFINE[
3ef9fa8f 294]AT_MAIN_DEFINE[
75d1fe16
AD
295]])
296
da730230 297AT_BISON_CHECK([-d -v -o input.c input.y], 0)
1154cced
AD
298AT_COMPILE([input])
299AT_PARSER_CHECK([./input], 0,
75d1fe16
AD
300[[15
301]])
302
82f3355e
JD
303# Make sure that fields after $n or $-n are parsed correctly. At one
304# point while implementing dashes in symbol names, we were dropping
305# fields after $-n.
306AT_DATA_GRAMMAR([[input.y]],
307[[
308%{
309# include <stdio.h>
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
JD
763
764%{
765# include <stdio.h>
766# include <stdlib.h>
55f48c48
AD
767]AT_YYLEX_DECLARE[
768]AT_YYERROR_DECLARE[
ec5479ce
JD
769# define USE(SYM)
770%}
771
772%printer {
12e35840
JD
773 fprintf (yyoutput, "<*> printer should not be called.\n");
774} <*>
775
776%printer {
3ebecc24
JD
777 fprintf (yyoutput, "<> printer for '%c' @ %d", $$, @$.first_column);
778} <>
ec5479ce 779%destructor {
3ebecc24
JD
780 fprintf (stdout, "<> destructor for '%c' @ %d.\n", $$, @$.first_column);
781} <>
ec5479ce
JD
782
783%printer {
784 fprintf (yyoutput, "'b'/'c' printer for '%c' @ %d", $$, @$.first_column);
785} 'b' 'c'
786%destructor {
787 fprintf (stdout, "'b'/'c' destructor for '%c' @ %d.\n", $$, @$.first_column);
788} 'b' 'c'
789
12e35840
JD
790%destructor {
791 fprintf (yyoutput, "<*> destructor should not be called.\n");
792} <*>
793
ec5479ce
JD
794%%
795
796start: 'a' 'b' 'c' 'd' 'e' { $$ = 'S'; USE(($1, $2, $3, $4, $5)); } ;
797
798%%
55f48c48 799]AT_YYERROR_DEFINE[
95361618 800]AT_YYLEX_DEFINE(["abcd"], [[yylval = res]])[
f42c012f 801]AT_MAIN_DEFINE[
ec5479ce
JD
802]])
803
9534d2be 804AT_BISON_CHECK([-o input.c input.y], [], [],
e42906f7
AD
805[[input.y:23.3-5: warning: useless %destructor for type <*> [-Wother]
806input.y:23.3-5: warning: useless %printer for type <*> [-Wother]
9534d2be 807]])
ec5479ce 808AT_COMPILE([input])
f42c012f 809AT_PARSER_CHECK([./input --debug], 1,
3ebecc24 810[[<> destructor for 'd' @ 4.
ec5479ce
JD
811'b'/'c' destructor for 'c' @ 3.
812'b'/'c' destructor for 'b' @ 2.
3ebecc24 813<> destructor for 'a' @ 1.
ec5479ce
JD
814]],
815[[Starting parse
816Entering state 0
3237f570
AD
817Reading a token: Next token is token 'a' (1.1: <> printer for 'a' @ 1)
818Shifting token 'a' (1.1: <> printer for 'a' @ 1)
ec5479ce 819Entering state 1
3237f570
AD
820Reading a token: Next token is token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
821Shifting token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
ec5479ce 822Entering state 3
3237f570
AD
823Reading a token: Next token is token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
824Shifting token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
ec5479ce 825Entering state 5
3237f570
AD
826Reading a token: Next token is token 'd' (1.4: <> printer for 'd' @ 4)
827Shifting token 'd' (1.4: <> printer for 'd' @ 4)
ec5479ce
JD
828Entering state 6
829Reading a token: Now at end of input.
7dbb8d8a 8301.5: syntax error, unexpected $end, expecting 'e'
3237f570 831Error: popping token 'd' (1.4: <> printer for 'd' @ 4)
ec5479ce 832Stack now 0 1 3 5
3237f570 833Error: popping token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
ec5479ce 834Stack now 0 1 3
3237f570 835Error: popping token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
ec5479ce 836Stack now 0 1
3237f570 837Error: popping token 'a' (1.1: <> printer for 'a' @ 1)
ec5479ce 838Stack now 0
3237f570 839Cleanup: discarding lookahead token $end (1.5: )
ec5479ce
JD
840Stack now 0
841]])
842
55f48c48 843AT_BISON_OPTION_POPDEFS
ec5479ce
JD
844AT_CLEANUP
845
846
847
12e35840
JD
848## ------------------------------------------------------ ##
849## Default tagged and per-type %printer and %destructor. ##
850## ------------------------------------------------------ ##
b2a0b7ca 851
12e35840 852AT_SETUP([Default tagged and per-type %printer and %destructor])
f42c012f 853AT_BISON_OPTION_PUSHDEFS([%debug])
b2a0b7ca 854AT_DATA_GRAMMAR([[input.y]],
cf499cff 855[[%define parse.error verbose
b2a0b7ca
JD
856%debug
857
858%{
859# include <stdio.h>
860# include <stdlib.h>
55f48c48
AD
861]AT_YYERROR_DECLARE[
862]AT_YYLEX_DECLARE[
b2a0b7ca
JD
863# define USE(SYM)
864%}
865
12e35840 866%printer {
3ebecc24
JD
867 fprintf (yyoutput, "<> printer should not be called.\n");
868} <>
12e35840 869
b2a0b7ca
JD
870%union { int field0; int field1; int field2; }
871%type <field0> start 'a' 'g'
872%type <field1> 'e'
873%type <field2> 'f'
874%printer {
12e35840
JD
875 fprintf (yyoutput, "<*>/<field2>/e printer");
876} <*> 'e' <field2>
b2a0b7ca 877%destructor {
12e35840
JD
878 fprintf (stdout, "<*>/<field2>/e destructor.\n");
879} <*> 'e' <field2>
b2a0b7ca
JD
880
881%type <field1> 'b'
882%printer { fprintf (yyoutput, "<field1> printer"); } <field1>
883%destructor { fprintf (stdout, "<field1> destructor.\n"); } <field1>
884
885%type <field0> 'c'
886%printer { fprintf (yyoutput, "'c' printer"); } 'c'
887%destructor { fprintf (stdout, "'c' destructor.\n"); } 'c'
888
889%type <field1> 'd'
890%printer { fprintf (yyoutput, "'d' printer"); } 'd'
891%destructor { fprintf (stdout, "'d' destructor.\n"); } 'd'
892
12e35840 893%destructor {
3ebecc24
JD
894 fprintf (yyoutput, "<> destructor should not be called.\n");
895} <>
12e35840 896
b2a0b7ca
JD
897%%
898
899start:
900 'a' 'b' 'c' 'd' 'e' 'f' 'g'
901 {
902 USE(($1, $2, $3, $4, $5, $6, $7));
903 $$ = 'S';
904 }
905 ;
906
907%%
55f48c48 908]AT_YYERROR_DEFINE[
95361618 909]AT_YYLEX_DEFINE(["abcdef"])[
f42c012f 910]AT_MAIN_DEFINE[
b2a0b7ca
JD
911]])
912
9534d2be
AD
913AT_BISON_CHECK([-o input.c input.y], [], [],
914[[input.y:22.3-4: warning: useless %destructor for type <> [-Wother]
915input.y:22.3-4: warning: useless %printer for type <> [-Wother]
916]])
b2a0b7ca 917AT_COMPILE([input])
f42c012f 918AT_PARSER_CHECK([./input --debug], 1,
12e35840
JD
919[[<*>/<field2>/e destructor.
920<*>/<field2>/e destructor.
b2a0b7ca
JD
921'd' destructor.
922'c' destructor.
923<field1> destructor.
12e35840 924<*>/<field2>/e destructor.
b2a0b7ca
JD
925]],
926[[Starting parse
927Entering state 0
12e35840
JD
928Reading a token: Next token is token 'a' (<*>/<field2>/e printer)
929Shifting token 'a' (<*>/<field2>/e printer)
b2a0b7ca
JD
930Entering state 1
931Reading a token: Next token is token 'b' (<field1> printer)
932Shifting token 'b' (<field1> printer)
933Entering state 3
934Reading a token: Next token is token 'c' ('c' printer)
935Shifting token 'c' ('c' printer)
936Entering state 5
937Reading a token: Next token is token 'd' ('d' printer)
938Shifting token 'd' ('d' printer)
939Entering state 6
12e35840
JD
940Reading a token: Next token is token 'e' (<*>/<field2>/e printer)
941Shifting token 'e' (<*>/<field2>/e printer)
b2a0b7ca 942Entering state 7
12e35840
JD
943Reading a token: Next token is token 'f' (<*>/<field2>/e printer)
944Shifting token 'f' (<*>/<field2>/e printer)
b2a0b7ca
JD
945Entering state 8
946Reading a token: Now at end of input.
947syntax error, unexpected $end, expecting 'g'
12e35840 948Error: popping token 'f' (<*>/<field2>/e printer)
b2a0b7ca 949Stack now 0 1 3 5 6 7
12e35840 950Error: popping token 'e' (<*>/<field2>/e printer)
b2a0b7ca
JD
951Stack now 0 1 3 5 6
952Error: popping token 'd' ('d' printer)
953Stack now 0 1 3 5
954Error: popping token 'c' ('c' printer)
955Stack now 0 1 3
956Error: popping token 'b' (<field1> printer)
957Stack now 0 1
12e35840 958Error: popping token 'a' (<*>/<field2>/e printer)
b2a0b7ca
JD
959Stack now 0
960Cleanup: discarding lookahead token $end ()
961Stack now 0
962]])
963
55f48c48 964AT_BISON_OPTION_POPDEFS
b2a0b7ca
JD
965AT_CLEANUP
966
967
968
ec5479ce 969## ------------------------------------------------------------- ##
12e35840 970## Default %printer and %destructor for user-defined end token. ##
ec5479ce
JD
971## ------------------------------------------------------------- ##
972
3508ce36 973AT_SETUP([Default %printer and %destructor for user-defined end token])
ec5479ce 974
9534d2be
AD
975# AT_TEST(TYPED)
976# --------------
977m4_pushdef([AT_TEST],
12e35840 978[m4_if($1, 0,
3ebecc24
JD
979 [m4_pushdef([kind], []) m4_pushdef([not_kind], [*])],
980 [m4_pushdef([kind], [*]) m4_pushdef([not_kind], [])])
12e35840 981
f42c012f 982AT_BISON_OPTION_PUSHDEFS([%locations %debug])
12e35840 983AT_DATA_GRAMMAR([[input]]$1[[.y]],
cf499cff 984[[%define parse.error verbose
ec5479ce
JD
985%debug
986%locations
ec5479ce
JD
987
988%{
989# include <stdio.h>
990# include <stdlib.h>
55f48c48
AD
991]AT_YYERROR_DECLARE[
992]AT_YYLEX_DECLARE[
ec5479ce
JD
993# define USE(SYM)
994%}
995
12e35840
JD
996%destructor {
997 fprintf (yyoutput, "<]]not_kind[[> destructor should not be called.\n");
998} <]]not_kind[[>
999
ec5479ce
JD
1000%token END 0
1001%printer {
12e35840
JD
1002 fprintf (yyoutput, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
1003} <]]kind[[>
ec5479ce 1004%destructor {
12e35840
JD
1005 fprintf (stdout, "<]]kind[[> for '%c' @ %d.\n", $$, @$.first_column);
1006} <]]kind[[>
1007
1008%printer {
1009 fprintf (yyoutput, "<]]not_kind[[> printer should not be called.\n");
1010} <]]not_kind[[>
1011
1012]]m4_if($1, 0, [[[
1013]]],
1014[[[%union { char tag; }
1015%type <tag> start END]]])[[
ec5479ce
JD
1016
1017%%
1018
1019start: { $$ = 'S'; } ;
1020
1021%%
1022
1023static int
1024yylex (void)
1025{
cf806753
PE
1026 static int called;
1027 if (called++)
1028 abort ();
12e35840 1029 yylval]]m4_if($1, 0,, [[[.tag]]])[[ = 'E';
ec5479ce
JD
1030 yylloc.first_line = yylloc.last_line = 1;
1031 yylloc.first_column = yylloc.last_column = 1;
1032 return 0;
1033}
55f48c48 1034]AT_YYERROR_DEFINE[
f42c012f 1035]AT_MAIN_DEFINE[
ec5479ce 1036]])
55f48c48 1037AT_BISON_OPTION_POPDEFS
ec5479ce 1038
9534d2be
AD
1039AT_BISON_CHECK([-o input$1.c input$1.y], [], [],
1040[m4_if([$1], [0],
e42906f7
AD
1041[[input0.y:23.3-5: warning: useless %destructor for type <*> [-Wother]
1042input0.y:23.3-5: warning: useless %printer for type <*> [-Wother]
9534d2be 1043]],
e42906f7
AD
1044[[input1.y:23.3-4: warning: useless %destructor for type <> [-Wother]
1045input1.y:23.3-4: warning: useless %printer for type <> [-Wother]
9534d2be
AD
1046]])])
1047
12e35840 1048AT_COMPILE([input$1])
9534d2be 1049
f42c012f 1050AT_PARSER_CHECK([./input$1 --debug], 0,
12e35840
JD
1051[[<]]kind[[> for 'E' @ 1.
1052<]]kind[[> for 'S' @ 1.
ec5479ce
JD
1053]],
1054[[Starting parse
1055Entering state 0
d03c0413 1056Reducing stack by rule 1 (line 42):
3237f570 1057-> $$ = nterm start (1.1: <]]kind[[> for 'S' @ 1)
ec5479ce
JD
1058Stack now 0
1059Entering state 1
1060Reading a token: Now at end of input.
3237f570 1061Shifting token END (1.1: <]]kind[[> for 'E' @ 1)
ec5479ce
JD
1062Entering state 2
1063Stack now 0 1 2
3237f570
AD
1064Cleanup: popping token END (1.1: <]]kind[[> for 'E' @ 1)
1065Cleanup: popping nterm start (1.1: <]]kind[[> for 'S' @ 1)
ec5479ce
JD
1066]])
1067
12e35840
JD
1068m4_popdef([kind])
1069m4_popdef([not_kind])
1070])
1071
9534d2be
AD
1072AT_TEST(0)
1073AT_TEST(1)
1074
1075m4_popdef([AT_TEST])
12e35840 1076
ec5479ce 1077AT_CLEANUP
9350499c
JD
1078
1079
1080
1081## ------------------------------------------------------------------ ##
1082## Default %printer and %destructor are not for error or $undefined. ##
1083## ------------------------------------------------------------------ ##
1084
287b314e 1085AT_SETUP([Default %printer and %destructor are not for error or $undefined])
9350499c
JD
1086
1087# If Bison were to apply the default %printer and %destructor to the error
1088# token or to $undefined:
1089# - For the error token:
1090# - It would generate warnings for unused $n.
1091# - It would invoke the %printer and %destructor on the error token's
1092# semantic value, which would be initialized from the lookahead, which
1093# would be destroyed separately.
1094# - For $undefined, who knows what the semantic value would be.
f42c012f 1095AT_BISON_OPTION_PUSHDEFS([%debug])
9350499c
JD
1096AT_DATA_GRAMMAR([[input.y]],
1097[[%debug
1098
1099%{
1100# include <stdio.h>
cf806753 1101# include <stdlib.h>
55f48c48
AD
1102]AT_YYERROR_DECLARE[
1103]AT_YYLEX_DECLARE[
9350499c
JD
1104# define USE(SYM)
1105%}
1106
1107%printer {
1108 fprintf (yyoutput, "'%c'", $$);
3ebecc24 1109} <> <*>
9350499c
JD
1110%destructor {
1111 fprintf (stderr, "DESTROY '%c'\n", $$);
3ebecc24 1112} <> <*>
9350499c
JD
1113
1114%%
1115
1116start:
1117 { $$ = 'S'; }
1118 /* In order to reveal the problems that this bug caused during parsing, add
1119 * $2 to USE. */
1120 | 'a' error 'b' 'c' { USE(($1, $3, $4)); $$ = 'S'; }
1121 ;
1122
1123%%
55f48c48 1124]AT_YYERROR_DEFINE[
95361618 1125]AT_YYLEX_DEFINE(["abd"], [yylval = res])[
f42c012f 1126]AT_MAIN_DEFINE[
9350499c 1127]])
55f48c48 1128AT_BISON_OPTION_POPDEFS
9350499c 1129
9534d2be
AD
1130AT_BISON_CHECK([-o input.c input.y], [], [],
1131[[input.y:21.6-8: warning: useless %destructor for type <*> [-Wother]
1132input.y:21.6-8: warning: useless %printer for type <*> [-Wother]
1133]])
9350499c 1134AT_COMPILE([input])
f42c012f 1135AT_PARSER_CHECK([./input --debug], [1], [],
9350499c
JD
1136[[Starting parse
1137Entering state 0
1138Reading a token: Next token is token 'a' ('a')
1139Shifting token 'a' ('a')
1140Entering state 1
1141Reading a token: Next token is token 'b' ('b')
1142syntax error
1143Shifting token error ()
1144Entering state 3
1145Next token is token 'b' ('b')
1146Shifting token 'b' ('b')
1147Entering state 5
1148Reading a token: Next token is token $undefined ()
1149Error: popping token 'b' ('b')
1150DESTROY 'b'
1151Stack now 0 1 3
1152Error: popping token error ()
1153Stack now 0 1
1154Shifting token error ()
1155Entering state 3
1156Next token is token $undefined ()
1157Error: discarding token $undefined ()
1158Error: popping token error ()
1159Stack now 0 1
1160Shifting token error ()
1161Entering state 3
1162Reading a token: Now at end of input.
1163Cleanup: discarding lookahead token $end ()
1164Stack now 0 1 3
1165Cleanup: popping token error ()
1166Cleanup: popping token 'a' ('a')
1167DESTROY 'a'
1168]])
1169
1170AT_CLEANUP
1171
1172
1173
1174## ------------------------------------------------------ ##
1175## Default %printer and %destructor are not for $accept. ##
1176## ------------------------------------------------------ ##
1177
287b314e 1178AT_SETUP([Default %printer and %destructor are not for $accept])
9350499c
JD
1179
1180# If YYSTYPE is a union and Bison were to apply the default %printer and
1181# %destructor to $accept:
1182# - The %printer and %destructor code generated for $accept would always be
1183# dead code because $accept is currently never shifted onto the stack.
1184# - $$ for $accept would always be of type YYSTYPE because it's not possible
1185# to declare `%type <field> $accept'. (Also true for $undefined.)
1186# - Thus, the compiler might complain that the user code assumes the wrong
1187# type for $$ since the code might assume the type associated with a
1188# specific union field, which is especially reasonable in C++ since that
1189# type may be a base type. This test case checks for this problem. (Also
1190# true for $undefined and the error token, so there are three warnings for
1191# %printer and three for %destructor.)
1192
f42c012f 1193AT_BISON_OPTION_PUSHDEFS([%debug])
9350499c
JD
1194AT_DATA_GRAMMAR([[input.y]],
1195[[%debug /* So that %printer is actually compiled. */
1196
1197%{
1198# include <stdio.h>
cf806753 1199# include <stdlib.h>
55f48c48
AD
1200]AT_YYERROR_DECLARE[
1201]AT_YYLEX_DECLARE[
9350499c
JD
1202# define USE(SYM)
1203%}
1204
1205%printer {
1206 char chr = $$;
1207 fprintf (yyoutput, "'%c'", chr);
3ebecc24 1208} <> <*>
9350499c
JD
1209%destructor {
1210 char chr = $$;
1211 fprintf (stderr, "DESTROY '%c'\n", chr);
3ebecc24 1212} <> <*>
9350499c
JD
1213
1214%union { char chr; }
1215%type <chr> start
1216
1217%%
1218
1219start: { USE($$); } ;
1220
1221%%
55f48c48 1222]AT_YYERROR_DEFINE[
95361618 1223]AT_YYLEX_DEFINE[
3ef9fa8f 1224]AT_MAIN_DEFINE[
9350499c 1225]])
55f48c48 1226AT_BISON_OPTION_POPDEFS
9350499c 1227
9534d2be
AD
1228AT_BISON_CHECK([-o input.c input.y], [], [],
1229[[input.y:22.3-4: warning: useless %destructor for type <> [-Wother]
1230input.y:22.3-4: warning: useless %printer for type <> [-Wother]
1231]])
9350499c
JD
1232AT_COMPILE([input])
1233
1234AT_CLEANUP
f91b1629
JD
1235
1236
1237
1238## ------------------------------------------------------ ##
1239## Default %printer and %destructor for mid-rule values. ##
1240## ------------------------------------------------------ ##
1241
1242AT_SETUP([Default %printer and %destructor for mid-rule values])
1243
f42c012f 1244AT_BISON_OPTION_PUSHDEFS([%debug])
f91b1629
JD
1245AT_DATA_GRAMMAR([[input.y]],
1246[[%debug /* So that %printer is actually compiled. */
1247
1248%{
1249# include <stdio.h>
1250# include <stdlib.h>
55f48c48
AD
1251]AT_YYERROR_DECLARE[
1252]AT_YYLEX_DECLARE[
f91b1629
JD
1253# define USE(SYM)
1254# define YYLTYPE int
9fc4c025 1255# define YYLLOC_DEFAULT(Current, Rhs, N) (void)(Rhs)
f91b1629
JD
1256# define YY_LOCATION_PRINT(File, Loc)
1257%}
1258
3ebecc24
JD
1259%printer { fprintf (yyoutput, "%d", @$); } <>
1260%destructor { fprintf (stderr, "DESTROY %d\n", @$); } <>
12e35840
JD
1261%printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1262%destructor { fprintf (yyoutput, "<*> destructor should not be called"); } <*>
f91b1629
JD
1263
1264%%
1265
1266start:
1267 { @$ = 1; } // Not set or used.
1268 { USE ($$); @$ = 2; } // Both set and used.
1269 { USE ($$); @$ = 3; } // Only set.
1270 { @$ = 4; } // Only used.
1271 'c'
1272 { USE (($$, $2, $4, $5)); @$ = 0; }
1273 ;
1274
1275%%
55f48c48 1276]AT_YYERROR_DEFINE[
95361618 1277]AT_YYLEX_DEFINE[
f42c012f 1278]AT_MAIN_DEFINE[
f91b1629 1279]])
55f48c48 1280AT_BISON_OPTION_POPDEFS
f91b1629 1281
da730230 1282AT_BISON_CHECK([-o input.c input.y], 0,,
9534d2be
AD
1283[[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
1284input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
1285input.y:33.3-23: warning: unset value: $$ [-Wother]
0906b12c 1286input.y:32.3-23: warning: unused value: $3 [-Wother]
f91b1629
JD
1287]])
1288
505ece51 1289AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
f3ead217
TR
1290[[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
1291 %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1292 ^^^
1293input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
1294 %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1295 ^^^
1296input.y:33.3-23: warning: unset value: $$ [-Wother]
505ece51
TR
1297 { @$ = 4; } // Only used.
1298 ^^^^^^^^^^^^^^^^^^^^^
0906b12c 1299input.y:32.3-23: warning: unused value: $3 [-Wother]
23589235
AD
1300 { USE ($$); @$ = 3; } // Only set.
1301 ^^^^^^^^^^^^^^^^^^^^^
505ece51
TR
1302]])
1303
f91b1629 1304AT_COMPILE([input])
f42c012f 1305AT_PARSER_CHECK([./input --debug], 1,,
f91b1629
JD
1306[[Starting parse
1307Entering state 0
12e35840 1308Reducing stack by rule 1 (line 30):
f91b1629
JD
1309-> $$ = nterm $@1 (: )
1310Stack now 0
1311Entering state 2
12e35840 1312Reducing stack by rule 2 (line 31):
f91b1629
JD
1313-> $$ = nterm @2 (: 2)
1314Stack now 0 2
1315Entering state 4
12e35840 1316Reducing stack by rule 3 (line 32):
f91b1629
JD
1317-> $$ = nterm @3 (: 3)
1318Stack now 0 2 4
1319Entering state 5
12e35840 1320Reducing stack by rule 4 (line 33):
f91b1629
JD
1321-> $$ = nterm @4 (: 4)
1322Stack now 0 2 4 5
1323Entering state 6
1324Reading a token: Now at end of input.
1325syntax error
1326Error: popping nterm @4 (: 4)
1327DESTROY 4
1328Stack now 0 2 4 5
1329Error: popping nterm @3 (: 3)
1330DESTROY 3
1331Stack now 0 2 4
1332Error: popping nterm @2 (: 2)
1333DESTROY 2
1334Stack now 0 2
1335Error: popping nterm $@1 (: )
1336Stack now 0
1337Cleanup: discarding lookahead token $end (: )
1338Stack now 0
1339]])
1340
1341AT_CLEANUP
e785ccf7
JD
1342
1343
1344## ----------------------- ##
1345## @$ implies %locations. ##
1346## ----------------------- ##
1347
1348# Bison once forgot to check for @$ in actions other than semantic actions.
1349
1350# AT_CHECK_ACTION_LOCATIONS(ACTION-DIRECTIVE)
55f48c48 1351# -------------------------------------------
e785ccf7
JD
1352m4_define([AT_CHECK_ACTION_LOCATIONS],
1353[AT_SETUP([[@$ in ]$1[ implies %locations]])
f42c012f 1354AT_BISON_OPTION_PUSHDEFS([%debug])
e785ccf7
JD
1355AT_DATA_GRAMMAR([[input.y]],
1356[[%code {
1357 #include <stdio.h>
55f48c48
AD
1358]AT_YYERROR_DECLARE[
1359]AT_YYLEX_DECLARE[
e785ccf7
JD
1360}
1361
1362%debug
1363
1364]$1[ {
8d6c1b5e 1365 fprintf (stderr, "%d\n", @$.first_line);
e785ccf7
JD
1366} ]m4_if($1, [%initial-action], [], [[start]])[
1367
1368%%
1369
1370start: ;
1371
1372%%
1373
1374static int
1375yylex (void)
1376{
1377 return 0;
1378}
1379
55f48c48 1380]AT_YYERROR_DEFINE[
3ef9fa8f 1381]AT_MAIN_DEFINE[
e785ccf7
JD
1382]])
1383
da730230 1384AT_BISON_CHECK([[-o input.c input.y]])
e785ccf7 1385AT_COMPILE([[input]])
55f48c48 1386AT_BISON_OPTION_POPDEFS
e785ccf7
JD
1387AT_CLEANUP])
1388
1389AT_CHECK_ACTION_LOCATIONS([[%initial-action]])
1390AT_CHECK_ACTION_LOCATIONS([[%destructor]])
1391AT_CHECK_ACTION_LOCATIONS([[%printer]])
e8cd1ad6
DJ
1392
1393
4982f078
AD
1394## ------------------------- ##
1395## Qualified $$ in actions. ##
1396## ------------------------- ##
1397
3edfae04
AD
1398# Check that we can use qualified $$ (v.g., $<type>$) not only in rule
1399# actions, but also where $$ is valid: %destructor/%printer and
1400# %initial-action.
4982f078 1401#
3edfae04 1402# FIXME: Not actually checking %destructor, but it's the same code as
4982f078
AD
1403# %printer...
1404#
1405# To do that, use a semantic value that has two fields (sem_type),
1406# declare symbols to have only one of these types (INT, float), and
1407# use $<type>$ to get the other one. Including for symbols that are
1408# not typed (UNTYPED).
1409
1410m4_pushdef([AT_TEST],
1411[AT_SETUP([[Qualified $$ in actions: $1]])
1412
f42c012f 1413AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %debug])
4982f078
AD
1414
1415AT_DATA_GRAMMAR([[input.y]],
1416[[%skeleton "$1"
4982f078
AD
1417%debug
1418%code requires
1419{
4982f078
AD
1420 typedef struct sem_type
1421 {
1422 int ival;
1423 float fval;
1424 } sem_type;
1425
1426# define YYSTYPE sem_type
1427
4acc22e5 1428]AT_SKEL_CC_IF([[
4982f078
AD
1429# include <iostream>
1430 static void
1431 report (std::ostream& yyo, int ival, float fval)
1432 {
1433 yyo << "ival: " << ival << ", fval: " << fval;
1434 }
4acc22e5
AD
1435]], [[
1436# include <stdio.h>
4982f078
AD
1437 static void
1438 report (FILE* yyo, int ival, float fval)
1439 {
1440 fprintf (yyo, "ival: %d, fval: %1.1f", ival, fval);
1441 }
4acc22e5 1442]])[
4982f078
AD
1443}
1444
1445%code
1446{
1447 ]AT_YYERROR_DECLARE[
1448 ]AT_YYLEX_DECLARE[
1449}
1450
1451%token UNTYPED
1452%token <ival> INT
1453%type <fval> float
1454%printer { report (yyo, $$, $<fval>$); } <ival>;
1455%printer { report (yyo, $<ival>$, $$ ); } <fval>;
1456%printer { report (yyo, $<ival>$, $<fval>$); } <>;
1457
cd735a8c
AD
1458%initial-action
1459{
1460 $<ival>$ = 42;
1461 $<fval>$ = 4.2;
1462}
4982f078
AD
1463
1464%%
1465float: UNTYPED INT
1466{
1467 $$ = $<fval>1 + $<fval>2;
1468 $<ival>$ = $<ival>1 + $][2;
1469};
1470%%
1471]AT_YYERROR_DEFINE[
1472]AT_YYLEX_DEFINE(AT_SKEL_CC_IF([[{yy::parser::token::UNTYPED,
1473 yy::parser::token::INT,
1474 EOF}]],
1475 [[{UNTYPED, INT, EOF}]]),
1476 [AT_VAL.ival = toknum * 10; AT_VAL.fval = toknum / 10.0;])[
f42c012f 1477]AT_MAIN_DEFINE[
4982f078
AD
1478]])
1479
1480AT_FULL_COMPILE([[input]])
f42c012f 1481AT_PARSER_CHECK([./input --debug], 0, [], [stderr])
4982f078
AD
1482# Don't be too picky on the traces, GLR is not exactly the same. Keep
1483# only the lines from the printer.
34904c57 1484AT_CHECK([[sed -ne '/ival:/p' stderr]], 0,
4982f078
AD
1485[[Reading a token: Next token is token UNTYPED (ival: 10, fval: 0.1)
1486Shifting token UNTYPED (ival: 10, fval: 0.1)
1487Reading a token: Next token is token INT (ival: 20, fval: 0.2)
1488Shifting token INT (ival: 20, fval: 0.2)
1489 $][1 = token UNTYPED (ival: 10, fval: 0.1)
1490 $][2 = token INT (ival: 20, fval: 0.2)
1491-> $$ = nterm float (ival: 30, fval: 0.3)
1492Cleanup: popping nterm float (ival: 30, fval: 0.3)
1493]])
1494
1495AT_BISON_OPTION_POPDEFS
1496
1497AT_CLEANUP
1498])
1499
1500AT_TEST([yacc.c])
1501AT_TEST([glr.c])
1502AT_TEST([lalr1.cc])
1503AT_TEST([glr.cc])
1504
1505m4_popdef([AT_TEST])
1506
e8cd1ad6
DJ
1507## ----------------------------------------------- ##
1508## Fix user actions without a trailing semicolon. ##
1509## ----------------------------------------------- ##
1510
1511AT_SETUP([[Fix user actions without a trailing semicolon]])
1512
1513# This feature is undocumented, but we accidentally broke it in 2.3a,
1514# and there was a complaint at:
1515# <http://lists.gnu.org/archive/html/bug-bison/2008-11/msg00001.html>.
55f48c48 1516AT_BISON_OPTION_PUSHDEFS
e8cd1ad6
DJ
1517AT_DATA([input.y],
1518[[%%
1519start: test2 test1 test0 testc;
1520
1521test2
e9690142
JD
1522: 'a' { semi; /* TEST:N:2 */ }
1523| 'b' { if (0) {no_semi} /* TEST:N:2 */ }
1524| 'c' { if (0) {semi;} /* TEST:N:2 */ }
1525| 'd' { semi; no_semi /* TEST:Y:2 */ }
1526| 'e' { semi(); no_semi() /* TEST:Y:2 */ }
1527| 'f' { semi[]; no_semi[] /* TEST:Y:2 */ }
1528| 'g' { semi++; no_semi++ /* TEST:Y:2 */ }
1529| 'h' { {no_semi} no_semi /* TEST:Y:2 */ }
1530| 'i' { {semi;} no_semi /* TEST:Y:2 */ }
e8cd1ad6
DJ
1531;
1532test1
e9690142
JD
1533 : 'a' { semi; // TEST:N:1 ;
1534} | 'b' { if (0) {no_semi} // TEST:N:1 ;
1535} | 'c' { if (0) {semi;} // TEST:N:1 ;
1536} | 'd' { semi; no_semi // TEST:Y:1 ;
1537} | 'e' { semi(); no_semi() // TEST:Y:1 ;
1538} | 'f' { semi[]; no_semi[] // TEST:Y:1 ;
1539} | 'g' { semi++; no_semi++ // TEST:Y:1 ;
1540} | 'h' { {no_semi} no_semi // TEST:Y:1 ;
1541} | 'i' { {semi;} no_semi // TEST:Y:1 ;
e8cd1ad6
DJ
1542} ;
1543test0
e9690142
JD
1544 : 'a' { semi; // TEST:N:1 {}
1545} | 'b' { if (0) {no_semi} // TEST:N:1 {}
1546} | 'c' { if (0) {semi;} // TEST:N:1 {}
1547} | 'd' { semi; no_semi // TEST:Y:1 {}
1548} | 'e' { semi(); no_semi() // TEST:Y:1 {}
1549} | 'f' { semi[]; no_semi[] // TEST:Y:1 {}
1550} | 'g' { semi++; no_semi++ // TEST:Y:1 {}
1551} | 'h' { {no_semi} no_semi // TEST:Y:1 {}
1552} | 'i' { {semi;} no_semi // TEST:Y:1 {}
e8cd1ad6
DJ
1553} ;
1554
1555testc
1556: 'a' {
1557#define TEST_MACRO_N \
1558[]"broken\" $ @ $$ @$ [];\
1559string;"}
1560| 'b' {
1561no_semi
1562#define TEST_MACRO_N \
1563[]"broken\" $ @ $$ @$ [];\
1564string;"}
1565]])
55f48c48 1566AT_BISON_OPTION_POPDEFS
e8cd1ad6
DJ
1567
1568AT_BISON_CHECK([[-o input.c input.y]], [0], [],
518e8830 1569[[input.y:8.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1570input.y:8.48: future versions of Bison will not add the ';'
518e8830 1571input.y:9.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1572input.y:9.48: future versions of Bison will not add the ';'
518e8830 1573input.y:10.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1574input.y:10.48: future versions of Bison will not add the ';'
518e8830 1575input.y:11.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1576input.y:11.48: future versions of Bison will not add the ';'
518e8830 1577input.y:12.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1578input.y:12.48: future versions of Bison will not add the ';'
518e8830 1579input.y:13.48: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1580input.y:13.48: future versions of Bison will not add the ';'
518e8830 1581input.y:20.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1582input.y:20.1: future versions of Bison will not add the ';'
518e8830 1583input.y:21.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1584input.y:21.1: future versions of Bison will not add the ';'
518e8830 1585input.y:22.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1586input.y:22.1: future versions of Bison will not add the ';'
518e8830 1587input.y:23.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1588input.y:23.1: future versions of Bison will not add the ';'
518e8830 1589input.y:24.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1590input.y:24.1: future versions of Bison will not add the ';'
518e8830 1591input.y:25.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1592input.y:25.1: future versions of Bison will not add the ';'
518e8830 1593input.y:31.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1594input.y:31.1: future versions of Bison will not add the ';'
518e8830 1595input.y:32.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1596input.y:32.1: future versions of Bison will not add the ';'
518e8830 1597input.y:33.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1598input.y:33.1: future versions of Bison will not add the ';'
518e8830 1599input.y:34.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1600input.y:34.1: future versions of Bison will not add the ';'
518e8830 1601input.y:35.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1602input.y:35.1: future versions of Bison will not add the ';'
518e8830 1603input.y:36.1: warning: a ';' might be needed at the end of action code [-Wdeprecated]
d4e985d5 1604input.y:36.1: future versions of Bison will not add the ';'
e8cd1ad6 1605]])
6617622c
AD
1606
1607AT_MATCHES_CHECK([input.c], [[/\* TEST:N:2 \*/ \}$]], [[3]])
1608AT_MATCHES_CHECK([input.c], [[/\* TEST:Y:2 \*/ ;\}$]], [[6]])
1609AT_MATCHES_CHECK([input.c], [[// TEST:N:1 [;{}]*\n\}$]], [[6]])
1610AT_MATCHES_CHECK([input.c], [[// TEST:Y:1 [;{}]*\n;\}$]], [[12]])
1611AT_MATCHES_CHECK([input.c], [[#define TEST_MACRO_N \\\n\[\]"broken\\" \$ \@ \$\$ \@\$ \[\];\\\nstring;"\}]], [[2]])
e8cd1ad6
DJ
1612
1613AT_CLEANUP
df222dfa
JD
1614
1615
1616## -------------------------------------------------- ##
1617## Destroying lookahead assigned by semantic action. ##
1618## -------------------------------------------------- ##
1619
1620AT_SETUP([[Destroying lookahead assigned by semantic action]])
1621
55f48c48 1622AT_BISON_OPTION_PUSHDEFS
df222dfa
JD
1623AT_DATA_GRAMMAR([input.y],
1624[[
1625%code {
1626 #include <assert.h>
1627 #include <stdio.h>
55f48c48
AD
1628]AT_YYERROR_DECLARE[
1629]AT_YYLEX_DECLARE[
df222dfa
JD
1630 #define USE(Var)
1631}
1632
1633%destructor { fprintf (stderr, "'a' destructor\n"); } 'a'
1634%destructor { fprintf (stderr, "'b' destructor\n"); } 'b'
1635
1636%%
1637
1638// In a previous version of Bison, yychar assigned by the semantic
1639// action below was not translated into yytoken before the lookahead was
1640// discarded and thus before its destructor (selected according to
1641// yytoken) was called in order to return from yyparse. This would
1642// happen even if YYACCEPT was performed in a later semantic action as
1643// long as only consistent states with default reductions were visited
1644// in between. However, we leave YYACCEPT in the same semantic action
1645// for this test in order to show that skeletons cannot simply translate
1646// immediately after every semantic action because a semantic action
1647// that has set yychar might not always return normally. Instead,
1648// skeletons must translate before every use of yytoken.
1649start: 'a' accept { USE($1); } ;
1650accept: /*empty*/ {
1651 assert (yychar == YYEMPTY);
1652 yychar = 'b';
1653 YYACCEPT;
1654} ;
1655
1656%%
55f48c48 1657]AT_YYERROR_DEFINE[
95361618 1658]AT_YYLEX_DEFINE(["a"])[
3ef9fa8f 1659]AT_MAIN_DEFINE[
df222dfa 1660]])
55f48c48 1661AT_BISON_OPTION_POPDEFS
df222dfa
JD
1662AT_BISON_CHECK([[-o input.c input.y]])
1663AT_COMPILE([[input]])
1664AT_PARSER_CHECK([[./input]], [[0]], [],
1665[['b' destructor
1666'a' destructor
1667]])
1668
1669AT_CLEANUP
d115aad9
AD
1670
1671## ---------- ##
1672## YYBACKUP. ##
1673## ---------- ##
1674
1675AT_SETUP([[YYBACKUP]])
1676
f42c012f 1677AT_BISON_OPTION_PUSHDEFS([%pure-parser %debug])
55f48c48 1678
d115aad9
AD
1679AT_DATA_GRAMMAR([input.y],
1680[[
1681%error-verbose
1682%debug
1683%pure-parser
1684%code {
1685# include <stdio.h>
1686# include <stdlib.h>
1687# include <assert.h>
1688
55f48c48 1689 ]AT_YYERROR_DECLARE[
087dcd78 1690 ]AT_YYLEX_DECLARE[
d115aad9
AD
1691}
1692%%
1693input:
1694 exp exp {}
1695;
1696
1697exp:
1698 'a' { printf ("a: %d\n", $1); }
1699| 'b' { YYBACKUP('a', 123); }
1700| 'c' 'd' { YYBACKUP('a', 456); }
1701;
1702
1703%%
55f48c48 1704]AT_YYERROR_DEFINE[
087dcd78 1705]AT_YYLEX_DEFINE(["bcd"], [*lvalp = (toknum + 1) * 10])[
3ef9fa8f 1706]AT_MAIN_DEFINE[
d115aad9 1707]])
55f48c48 1708AT_BISON_OPTION_POPDEFS
d115aad9
AD
1709
1710AT_BISON_CHECK([[-o input.c input.y]])
1711AT_COMPILE([[input]])
1712AT_PARSER_CHECK([[./input]], [[0]],
1713[[a: 123
1714a: 456
d115aad9
AD
1715]])
1716
1717AT_CLEANUP