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