]> git.saurik.com Git - bison.git/blame_incremental - tests/actions.at
gnulib: update
[bison.git] / tests / actions.at
... / ...
CommitLineData
1e# Executing Actions. -*- Autotest -*-
2
3# Copyright (C) 2001-2015 Free Software Foundation, Inc.
4
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18AT_BANNER([[User Actions.]])
19
20## ------------------ ##
21## Mid-rule actions. ##
22## ------------------ ##
23
24AT_SETUP([Mid-rule actions])
25
26# Bison once forgot the mid-rule actions. It was because the action
27# was attached to the host rule (the one with the mid-rule action),
28# instead of being attached to the empty rule dedicated to this
29# action.
30
31AT_BISON_OPTION_PUSHDEFS
32AT_DATA_GRAMMAR([[input.y]],
33[[%define parse.error verbose
34%debug
35%code {
36]AT_YYERROR_DECLARE[
37]AT_YYLEX_DECLARE[
38}
39%%
40exp: { putchar ('0'); }
41 '1' { putchar ('1'); }
42 '2' { putchar ('2'); }
43 '3' { putchar ('3'); }
44 '4' { putchar ('4'); }
45 '5' { putchar ('5'); }
46 '6' { putchar ('6'); }
47 '7' { putchar ('7'); }
48 '8' { putchar ('8'); }
49 '9' { putchar ('9'); }
50 { putchar ('\n'); }
51 ;
52%%
53]AT_YYERROR_DEFINE[
54]AT_YYLEX_DEFINE(["123456789"])[
55]AT_MAIN_DEFINE[
56]])
57AT_BISON_OPTION_POPDEFS
58
59AT_BISON_CHECK([-d -v -o input.c input.y])
60AT_COMPILE([input])
61AT_PARSER_CHECK([./input], 0,
62[[0123456789
63]])
64
65AT_CLEANUP
66
67## ----------------------- ##
68## Implicitly empty rule. ##
69## ----------------------- ##
70
71AT_SETUP([Implicitly empty rule])
72
73AT_DATA_GRAMMAR([[1.y]],
74[[%%
75exp: a b;
76a: /* empty. */ {};
77// A mid-rule action does not count as an empty rule.
78b: {} {};
79]])
80
81AT_BISON_CHECK([-fcaret -Wempty-rule 1.y], [0], [],
82[[1.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
83 a: /* empty. */ {};
84 ^^
85]])
86
87AT_DATA_GRAMMAR([[2.y]],
88[[%%
89exp: a b c;
90a: /* empty. */ {};
91b: %empty {};
92c: /* empty. */ {};
93]])
94
95AT_BISON_CHECK([-fcaret 2.y], [0], [],
96[[2.y:11.17-18: warning: empty rule without %empty [-Wempty-rule]
97 a: /* empty. */ {};
98 ^^
992.y:13.17-18: warning: empty rule without %empty [-Wempty-rule]
100 c: /* empty. */ {};
101 ^^
102]])
103
104AT_BISON_CHECK([-fcaret -Wno-empty-rule 2.y], [0])
105
106AT_CLEANUP
107
108## ------------------------ ##
109## Invalid uses of %empty. ##
110## ------------------------ ##
111
112AT_SETUP([Invalid uses of %empty])
113
114AT_DATA_GRAMMAR([[one.y]],
115[[%%
116exp:
117 %empty {} %empty
118;
119]])
120
121AT_BISON_CHECK([-fcaret one.y], [1], [],
122[[one.y:11.13-18: error: only one %empty allowed per rule
123 %empty {} %empty
124 ^^^^^^
125one.y:11.3-8: previous declaration
126 %empty {} %empty
127 ^^^^^^
128]])
129
130AT_DATA_GRAMMAR([[two.y]],
131[[%%
132exp:
133 'a' %empty {}
134| %empty 'a' {}
135| %empty {} {}
136;
137]])
138
139AT_BISON_CHECK([-fcaret two.y], [1], [],
140[[two.y:11.7-12: error: %empty on non-empty rule
141 'a' %empty {}
142 ^^^^^^
143two.y:12.3-8: error: %empty on non-empty rule
144 | %empty 'a' {}
145 ^^^^^^
146two.y:13.3-8: error: %empty on non-empty rule
147 | %empty {} {}
148 ^^^^^^
149]])
150
151AT_CLEANUP
152
153## ---------------------- ##
154## Valid uses of %empty. ##
155## ---------------------- ##
156
157AT_SETUP([Valid uses of %empty])
158
159AT_BISON_OPTION_PUSHDEFS
160AT_DATA_GRAMMAR([[input.y]],
161[[
162%debug
163%code
164{
165]AT_YYERROR_DECLARE[
166]AT_YYLEX_DECLARE[
167}
168%%
169exp: %empty {}
170%%
171]AT_YYERROR_DEFINE[
172]AT_YYLEX_DEFINE[
173]AT_MAIN_DEFINE[
174]])
175
176AT_FULL_COMPILE([input])
177AT_PARSER_CHECK([./input])
178AT_BISON_OPTION_POPDEFS
179AT_CLEANUP
180
181## ------------------ ##
182## Initial location. ##
183## ------------------ ##
184
185# AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES], [LOCATION = 1.1])
186# -----------------------------------------------------------------------
187# Check that the initial location is correct.
188m4_pushdef([AT_TEST],
189[AT_SETUP([Initial location: $1 $2])
190
191AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
192AT_DATA_GRAMMAR([[input.y]],
193[[%locations
194%debug
195%skeleton "$1"
196]$2[
197]$3[
198%code
199{
200# include <stdio.h>
201# include <stdlib.h> /* getenv */
202]AT_YYERROR_DECLARE[
203]AT_YYLEX_DECLARE[
204}
205%%
206exp: { ]AT_SKEL_CC_IF([[std::cerr << @$ << std::endl]],
207 [[LOCATION_PRINT(stderr, @$); fputc ('\n', stderr)]])[; }
208%%
209]AT_YYERROR_DEFINE[
210
211]AT_YYLEX_PROTOTYPE[
212{]AT_PURE_IF([
213 YYUSE(lvalp);
214 YYUSE(llocp);], [AT_SKEL_CC_IF([
215 YYUSE(lvalp);
216 YYUSE(llocp);])])[
217 return 'x';
218}
219
220int
221main (void)
222{]AT_SKEL_CC_IF([[
223 yy::parser p;
224 p.set_debug_level (!!getenv("YYDEBUG"));
225 return p.parse ();]], [[
226 yydebug = !!getenv("YYDEBUG");
227 return !!yyparse (]AT_PARAM_IF([0])[);]])[
228}
229]])
230
231AT_FULL_COMPILE([input])
232AT_PARSER_CHECK([./input], 1, [],
233[m4_default([$4], [1.1])
234m4_default([$4], [1.1])[: syntax error
235]])
236AT_BISON_OPTION_POPDEFS
237AT_CLEANUP
238])
239
240## FIXME: test Java, and iterate over skeletons.
241AT_TEST([yacc.c])
242AT_TEST([yacc.c], [%define api.pure full])
243AT_TEST([yacc.c], [%define api.pure %parse-param { int x }])
244AT_TEST([yacc.c], [%define api.push-pull both])
245AT_TEST([yacc.c], [%define api.push-pull both %define api.pure full])
246AT_TEST([glr.c])
247AT_TEST([glr.c], [%define api.pure])
248AT_TEST([lalr1.cc])
249AT_TEST([glr.cc])
250
251## A very different test, based on PostgreSQL's implementation of the
252## locations. See
253## http://lists.gnu.org/archive/html/bug-bison/2012-11/msg00023.html
254##
255## Weirdly enough, to trigger the warning with GCC 4.7, we must not
256## use fprintf, so run the test twice: once to check the warning
257## (absence thereof), and another time to check the value.
258AT_TEST([yacc.c], [%define api.pure full],
259[[%{
260# define YYLTYPE int
261# define LOCATION_PRINT(Stream, Loc) \
262 (void) (Loc)
263# define YYLLOC_DEFAULT(Current, Rhs, N) \
264 (Current) = ((Rhs)[N ? 1 : 0])
265%}
266]],
267[@&t@])
268
269AT_TEST([yacc.c], [%define api.pure full],
270[[%{
271# define YYLTYPE int
272# define LOCATION_PRINT(Stream, Loc) \
273 fprintf ((Stream), "%d", (Loc))
274# define YYLLOC_DEFAULT(Current, Rhs, N) \
275 (Current) = ((Rhs)[N ? 1 : 0])
276%}
277]],
278[0])
279
280
281m4_popdef([AT_TEST])
282
283
284
285## ---------------- ##
286## Location Print. ##
287## ---------------- ##
288
289# AT_TEST(SKELETON-NAME, DIRECTIVES, [MORE-DIRECTIVES])
290# -----------------------------------------------------
291# Check that the initial location is correct.
292m4_pushdef([AT_TEST],
293[AT_SETUP([Location print: $1 $2])
294
295AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2])
296AT_DATA_GRAMMAR([[input.y]],
297[[%locations
298%debug
299%skeleton "$1"
300]$2[
301]$3[
302%code
303{
304]AT_YYERROR_DECLARE[
305]AT_YYLEX_DECLARE[
306}
307%%
308exp: %empty;
309%%
310]AT_YYERROR_DEFINE[
311]AT_YYLEX_DEFINE[
312
313int
314main (void)
315{
316 ]AT_YYLTYPE[ loc;
317]AT_GLR_CC_IF([loc.initialize();])[
318#define TEST(L1, C1, L2, C2) \
319 loc.]AT_FIRST_LINE[ = L1; \
320 loc.]AT_FIRST_COLUMN[ = C1; \
321 loc.]AT_LAST_LINE[ = L2; \
322 loc.]AT_LAST_COLUMN[ = C2; \
323 ]AT_SKEL_CC_IF([std::cout << loc],
324 [LOCATION_PRINT(stdout, loc)])[;\
325 putchar ('\n');
326
327 TEST(1, 1, 1, 1);
328 TEST(2, 1, 2, 10);
329 TEST(3, 1, 4, 1);
330 TEST(5, 1, 6, 10);
331
332 TEST(7, 2, 0, 2);
333 TEST(8, 0, 8, 0);
334 return 0;
335}
336]])
337
338AT_FULL_COMPILE([input])
339AT_PARSER_CHECK([./input], 0,
340[[1.1
3412.1-9
3423.1-4.0
3435.1-6.9
3447.2
3458.0
346]])
347AT_BISON_OPTION_POPDEFS
348AT_CLEANUP
349])
350
351## FIXME: test Java, and iterate over skeletons.
352AT_TEST([yacc.c])
353AT_TEST([glr.c])
354AT_TEST([lalr1.cc])
355AT_TEST([glr.cc])
356
357m4_popdef([AT_TEST])
358
359
360
361## ---------------- ##
362## Exotic Dollars. ##
363## ---------------- ##
364
365AT_SETUP([Exotic Dollars])
366
367AT_BISON_OPTION_PUSHDEFS
368AT_DATA_GRAMMAR([[input.y]],
369[[%define parse.error verbose
370%debug
371%code {
372]AT_YYERROR_DECLARE[
373]AT_YYLEX_DECLARE[
374# define USE(Var)
375}
376
377%union
378{
379 int val;
380};
381
382%type <val> a_1 a_2 a_5
383 sum_of_the_five_previous_values
384
385%%
386exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
387 sum_of_the_five_previous_values
388 {
389 USE (($1, $2, $<foo>3, $<foo>4, $5));
390 printf ("%d\n", $6);
391 }
392;
393a_1: { $$ = 1; };
394a_2: { $$ = 2; };
395a_5: { $$ = 5; };
396
397sum_of_the_five_previous_values:
398 {
399 $$ = $<val>0 + $<val>-1 + $<val>-2 + $<val>-3 + $<val>-4;
400 }
401;
402
403%%
404]AT_YYERROR_DEFINE[
405]AT_YYLEX_DEFINE[
406]AT_MAIN_DEFINE[
407]])
408
409AT_BISON_CHECK([-d -v -o input.c input.y], 0)
410AT_COMPILE([input])
411AT_PARSER_CHECK([./input], 0,
412[[15
413]])
414
415# Make sure that fields after $n or $-n are parsed correctly. At one
416# point while implementing dashes in symbol names, we were dropping
417# fields after $-n.
418AT_DATA_GRAMMAR([[input.y]],
419[[
420%{
421]AT_YYERROR_DECLARE[
422]AT_YYLEX_DECLARE[
423 typedef struct { int val; } stype;
424# define YYSTYPE stype
425%}
426
427%%
428start: one two { $$.val = $1.val + $2.val; } sum ;
429one: { $$.val = 1; } ;
430two: { $$.val = 2; } ;
431sum: { printf ("%d\n", $0.val + $-1.val + $-2.val); } ;
432
433%%
434]AT_YYERROR_DEFINE[
435]AT_YYLEX_DEFINE[
436]AT_MAIN_DEFINE[
437]])
438
439AT_FULL_COMPILE([input])
440AT_PARSER_CHECK([[./input]], [[0]],
441[[6
442]])
443
444AT_BISON_OPTION_POPDEFS
445AT_CLEANUP
446
447
448
449## -------------------------- ##
450## Printers and Destructors. ##
451## -------------------------- ##
452
453# _AT_CHECK_PRINTER_AND_DESTRUCTOR($1, $2, $3, $4,
454# BISON-DIRECTIVE, UNION-FLAG)
455# -------------------------------------------------------------
456m4_define([_AT_CHECK_PRINTER_AND_DESTRUCTOR],
457[# Make sure complex $n work.
458m4_if([$1$2$3$4], $[1]$[2]$[3]$[4], [],
459 [m4_fatal([$0: Invalid arguments: $@])])dnl
460
461# Be sure to pass all the %directives to this macro to have correct
462# helping macros. So don't put any directly in the Bison file.
463AT_BISON_OPTION_PUSHDEFS([$5])
464AT_DATA_GRAMMAR([[input.y]],
465[[%code requires {
466#include <stdio.h>
467#include <stdlib.h>
468#include <string.h>
469#include <assert.h>
470
471#define YYINITDEPTH 10
472#define YYMAXDEPTH 10
473#define RANGE(Location) ]AT_LALR1_CC_IF([(Location).begin.line, (Location).end.line],
474 [(Location).first_line, (Location).last_line])[
475
476/* Display the symbol type Symbol. */
477#define V(Symbol, Value, Location, Sep) \
478 fprintf (stderr, #Symbol " (%d@%d-%d)%s", Value, RANGE(Location), Sep)
479}
480
481$5
482]m4_ifval([$6], [%union
483{
484 int ival;
485}])
486AT_LALR1_CC_IF([%define global_tokens_and_yystype])
487m4_ifval([$6], [[%code provides {]], [[%code {]])
488AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])[
489]AT_YYLEX_DECLARE[
490]AT_LALR1_CC_IF([], [AT_YYERROR_DECLARE])
491[}
492
493]m4_ifval([$6],
494[%type <ival> '(' 'x' 'y' ')' ';' thing line input
495 '!' raise check-spontaneous-errors END])[
496
497/* FIXME: This %printer isn't actually tested. */
498%printer
499 {
500 ]AT_LALR1_CC_IF([yyo << $$;],
501 [fprintf (yyo, "%d", $$)])[;
502 }
503 '(' 'x' 'y' ')' ';' thing line input '!' raise check-spontaneous-errors END
504
505%destructor
506 { fprintf (stderr, "Freeing nterm input (%d@%d-%d)\n", $$, RANGE (@$)); }
507 input
508
509%destructor
510 { fprintf (stderr, "Freeing nterm line (%d@%d-%d)\n", $$, RANGE (@$)); }
511 line
512
513%destructor
514 { fprintf (stderr, "Freeing nterm thing (%d@%d-%d)\n", $$, RANGE (@$)); }
515 thing
516
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
525%destructor
526 { fprintf (stderr, "Freeing token 'x' (%d@%d-%d)\n", $$, RANGE (@$)); }
527 'x'
528
529%destructor
530 { fprintf (stderr, "Freeing token 'y' (%d@%d-%d)\n", $$, RANGE (@$)); }
531 'y'
532
533%token END 0
534%destructor
535 { fprintf (stderr, "Freeing token END (%d@%d-%d)\n", $$, RANGE (@$)); }
536 END
537
538%%
539/*
540 This grammar is made to exercise error recovery.
541 "Lines" starting with '(' support error recovery, with
542 ')' as synchronizing token. Lines starting with 'x' can never
543 be recovered from if in error.
544*/
545
546input:
547 %empty
548 {
549 $$ = 0;
550 V(input, $$, @$, ": /* Nothing */\n");
551 }
552| line input /* Right recursive to load the stack so that popping at
553 END can be exercised. */
554 {
555 $$ = 2;
556 V(input, $$, @$, ": ");
557 V(line, $1, @1, " ");
558 V(input, $2, @2, "\n");
559 }
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 }
592;
593
594line:
595 thing thing thing ';'
596 {
597 $$ = $1;
598 V(line, $$, @$, ": ");
599 V(thing, $1, @1, " ");
600 V(thing, $2, @2, " ");
601 V(thing, $3, @3, " ");
602 V(;, $4, @4, "\n");
603 }
604| '(' thing thing ')'
605 {
606 $$ = $1;
607 V(line, $$, @$, ": ");
608 V('(', $1, @1, " ");
609 V(thing, $2, @2, " ");
610 V(thing, $3, @3, " ");
611 V(')', $4, @4, "\n");
612 }
613| '(' thing ')'
614 {
615 $$ = $1;
616 V(line, $$, @$, ": ");
617 V('(', $1, @1, " ");
618 V(thing, $2, @2, " ");
619 V(')', $3, @3, "\n");
620 }
621| '(' error ')'
622 {
623 $$ = -1;
624 V(line, $$, @$, ": ");
625 V('(', $1, @1, " ");
626 fprintf (stderr, "error (@%d-%d) ", RANGE(@2));
627 V(')', $3, @3, "\n");
628 }
629;
630
631thing:
632 'x'
633 {
634 $$ = $1;
635 V(thing, $$, @$, ": ");
636 V('x', $1, @1, "\n");
637 }
638;
639%%
640/* Alias to ARGV[1]. */
641const char *source = YY_NULLPTR;
642
643]AT_YYERROR_DEFINE[
644
645static
646]AT_YYLEX_PROTOTYPE[
647{
648 static unsigned int counter = 0;
649
650 unsigned int c = ]AT_VAL[]m4_ifval([$6], [.ival])[ = counter++;
651 /* As in BASIC, line numbers go from 10 to 10. */
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;
654 assert (c <= strlen (source));
655 if (source[c])
656 fprintf (stderr, "sending: '%c'", source[c]);
657 else
658 fprintf (stderr, "sending: END");
659 fprintf (stderr, " (%d@%d-%d)\n", c, RANGE (]AT_LOC[));
660 return source[c];
661}
662]AT_LALR1_CC_IF(
663[static bool yydebug;
664int
665yyparse ()
666{
667 yy::parser parser;
668 parser.set_debug_level (yydebug);
669 return parser.parse ();
670}
671])[
672
673int
674main (int argc, const char *argv[])
675{
676 int status;
677 yydebug = !!getenv ("YYDEBUG");
678 assert (argc == 2); (void) argc;
679 source = argv[1];
680 status = yyparse ();
681 switch (status)
682 {
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;
686 }
687 return status;
688}
689]])
690
691AT_FULL_COMPILE([input])
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?
699AT_PARSER_CHECK([./input '(x)'], 0, [],
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)
705sending: END (3@30-39)
706input (0@29-29): /* Nothing */
707input (2@0-29): line (0@0-29) input (0@29-29)
708Freeing token END (3@30-39)
709Freeing nterm input (2@0-29)
710Successful parse.
711]])
712
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]])
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)').
750AT_PARSER_CHECK([./input '(y)'], 0, [],
751[[sending: '(' (0@0-9)
752sending: 'y' (1@10-19)
75310.10-19.18: syntax error, unexpected 'y', expecting 'x'
754Freeing token 'y' (1@10-19)
755sending: ')' (2@20-29)
756line (-1@0-29): '(' (0@0-9) error (@10-19) ')' (2@20-29)
757sending: END (3@30-39)
758input (0@29-29): /* Nothing */
759input (2@0-29): line (-1@0-29) input (0@29-29)
760Freeing token END (3@30-39)
761Freeing nterm input (2@0-29)
762Successful parse.
763]])
764
765
766# Syntax errors caught by the parser
767# ----------------------------------
768# Exercise the discarding of stack top and input until 'error'
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'
780AT_PARSER_CHECK([./input '(xxxxx)(x)(x)y'], 1, [],
781[[sending: '(' (0@0-9)
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)
78730.30-39.38: syntax error, unexpected 'x', expecting ')'
788Freeing nterm thing (2@20-29)
789Freeing nterm thing (1@10-19)
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)
795sending: ')' (6@60-69)
796line (-1@0-69): '(' (0@0-9) error (@10-59) ')' (6@60-69)
797sending: '(' (7@70-79)
798sending: 'x' (8@80-89)
799thing (8@80-89): 'x' (8@80-89)
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)
808input (0@129-129): /* Nothing */
809input (2@100-129): line (10@100-129) input (0@129-129)
810input (2@70-129): line (7@70-99) input (2@100-129)
811input (2@0-129): line (-1@0-69) input (2@70-129)
812130.130-139.138: syntax error, unexpected 'y', expecting END
813Freeing nterm input (2@0-129)
814Freeing token 'y' (13@130-139)
815Parsing FAILED.
816]])
817
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'
828AT_PARSER_CHECK([./input '(x)(x)x'], 1, [],
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)
84270.70-79.78: syntax error, unexpected END, expecting 'x'
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
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([
856AT_PARSER_CHECK([./input '(x)(x)(x)(x)(x)(x)(x)'], 2, [],
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)
891200.200-209.208: memory exhausted
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)
899Parsing FAILED (status 2).
900]])
901])
902
903AT_BISON_OPTION_POPDEFS
904])# _AT_CHECK_PRINTER_AND_DESTRUCTOR
905
906
907# AT_CHECK_PRINTER_AND_DESTRUCTOR([BISON-OPTIONS], [UNION-FLAG], [SKIP_FLAG])
908# ---------------------------------------------------------------------------
909m4_define([AT_CHECK_PRINTER_AND_DESTRUCTOR],
910[AT_SETUP([Printers and Destructors$2]m4_ifval([$1], [[: $1]]))
911
912$3
913_AT_CHECK_PRINTER_AND_DESTRUCTOR($[1], $[2], $[3], $[4],
914[%define parse.error verbose
915%debug
916%verbose
917%locations
918$1], [$2])
919
920AT_CLEANUP
921])
922
923
924AT_CHECK_PRINTER_AND_DESTRUCTOR([])
925AT_CHECK_PRINTER_AND_DESTRUCTOR([], [ with union])
926
927AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"])
928AT_CHECK_PRINTER_AND_DESTRUCTOR([%defines %skeleton "lalr1.cc"], [ with union])
929
930AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser])
931AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser], [ with union])
932
933
934
935## ----------------------------------------- ##
936## Default tagless %printer and %destructor. ##
937## ----------------------------------------- ##
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
942AT_SETUP([Default tagless %printer and %destructor])
943AT_BISON_OPTION_PUSHDEFS([%locations %debug])
944AT_DATA_GRAMMAR([[input.y]],
945[[%define parse.error verbose
946%debug
947%locations
948
949%code {
950]AT_YYLEX_DECLARE[
951]AT_YYERROR_DECLARE[
952# define USE(SYM)
953}
954
955%printer {
956 fprintf (yyoutput, "<*> printer should not be called.\n");
957} <*>
958
959%printer {
960 fprintf (yyoutput, "<> printer for '%c' @ %d", $$, @$.first_column);
961} <>
962%destructor {
963 fprintf (stdout, "<> destructor for '%c' @ %d.\n", $$, @$.first_column);
964} <>
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
973%destructor {
974 fprintf (yyoutput, "<*> destructor should not be called.\n");
975} <*>
976
977%%
978
979start: 'a' 'b' 'c' 'd' 'e' { $$ = 'S'; USE(($1, $2, $3, $4, $5)); } ;
980
981%%
982]AT_YYERROR_DEFINE[
983]AT_YYLEX_DEFINE(["abcd"], [[yylval = res]])[
984]AT_MAIN_DEFINE[
985]])
986
987AT_BISON_CHECK([-o input.c input.y], [], [],
988[[input.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
989input.y:30.3-5: warning: useless %printer for type <*> [-Wother]
990]])
991AT_COMPILE([input])
992AT_PARSER_CHECK([./input --debug], 1,
993[[<> destructor for 'd' @ 4.
994'b'/'c' destructor for 'c' @ 3.
995'b'/'c' destructor for 'b' @ 2.
996<> destructor for 'a' @ 1.
997]],
998[[Starting parse
999Entering state 0
1000Reading a token: Next token is token 'a' (1.1: <> printer for 'a' @ 1)
1001Shifting token 'a' (1.1: <> printer for 'a' @ 1)
1002Entering state 1
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)
1005Entering state 3
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)
1008Entering state 5
1009Reading a token: Next token is token 'd' (1.4: <> printer for 'd' @ 4)
1010Shifting token 'd' (1.4: <> printer for 'd' @ 4)
1011Entering state 6
1012Reading a token: Now at end of input.
10131.5: syntax error, unexpected $end, expecting 'e'
1014Error: popping token 'd' (1.4: <> printer for 'd' @ 4)
1015Stack now 0 1 3 5
1016Error: popping token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
1017Stack now 0 1 3
1018Error: popping token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
1019Stack now 0 1
1020Error: popping token 'a' (1.1: <> printer for 'a' @ 1)
1021Stack now 0
1022Cleanup: discarding lookahead token $end (1.5: )
1023Stack now 0
1024]])
1025
1026AT_BISON_OPTION_POPDEFS
1027AT_CLEANUP
1028
1029
1030
1031## ------------------------------------------------------ ##
1032## Default tagged and per-type %printer and %destructor. ##
1033## ------------------------------------------------------ ##
1034
1035AT_SETUP([Default tagged and per-type %printer and %destructor])
1036AT_BISON_OPTION_PUSHDEFS([%debug])
1037AT_DATA_GRAMMAR([[input.y]],
1038[[%define parse.error verbose
1039%debug
1040
1041%{
1042]AT_YYERROR_DECLARE[
1043]AT_YYLEX_DECLARE[
1044# define USE(SYM)
1045%}
1046
1047%printer {
1048 fprintf (yyoutput, "<> printer should not be called.\n");
1049} <>
1050
1051%union { int field0; int field1; int field2; }
1052%type <field0> start 'a' 'g'
1053%type <field1> 'e'
1054%type <field2> 'f'
1055%printer {
1056 fprintf (yyoutput, "<*>/<field2>/e printer");
1057} <*> 'e' <field2>
1058%destructor {
1059 fprintf (stdout, "<*>/<field2>/e destructor.\n");
1060} <*> 'e' <field2>
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
1074%destructor {
1075 fprintf (yyoutput, "<> destructor should not be called.\n");
1076} <>
1077
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%%
1089]AT_YYERROR_DEFINE[
1090]AT_YYLEX_DEFINE(["abcdef"])[
1091]AT_MAIN_DEFINE[
1092]])
1093
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]])
1098AT_COMPILE([input])
1099AT_PARSER_CHECK([./input --debug], 1,
1100[[<*>/<field2>/e destructor.
1101<*>/<field2>/e destructor.
1102'd' destructor.
1103'c' destructor.
1104<field1> destructor.
1105<*>/<field2>/e destructor.
1106]],
1107[[Starting parse
1108Entering state 0
1109Reading a token: Next token is token 'a' (<*>/<field2>/e printer)
1110Shifting token 'a' (<*>/<field2>/e printer)
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
1121Reading a token: Next token is token 'e' (<*>/<field2>/e printer)
1122Shifting token 'e' (<*>/<field2>/e printer)
1123Entering state 7
1124Reading a token: Next token is token 'f' (<*>/<field2>/e printer)
1125Shifting token 'f' (<*>/<field2>/e printer)
1126Entering state 8
1127Reading a token: Now at end of input.
1128syntax error, unexpected $end, expecting 'g'
1129Error: popping token 'f' (<*>/<field2>/e printer)
1130Stack now 0 1 3 5 6 7
1131Error: popping token 'e' (<*>/<field2>/e printer)
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
1139Error: popping token 'a' (<*>/<field2>/e printer)
1140Stack now 0
1141Cleanup: discarding lookahead token $end ()
1142Stack now 0
1143]])
1144
1145AT_BISON_OPTION_POPDEFS
1146AT_CLEANUP
1147
1148
1149
1150## ------------------------------------------------------------- ##
1151## Default %printer and %destructor for user-defined end token. ##
1152## ------------------------------------------------------------- ##
1153
1154AT_SETUP([Default %printer and %destructor for user-defined end token])
1155
1156# AT_TEST(TYPED)
1157# --------------
1158m4_pushdef([AT_TEST],
1159[m4_if($1, 0,
1160 [m4_pushdef([kind], []) m4_pushdef([not_kind], [*])],
1161 [m4_pushdef([kind], [*]) m4_pushdef([not_kind], [])])
1162
1163AT_BISON_OPTION_PUSHDEFS([%locations %debug])
1164AT_DATA_GRAMMAR([[input]]$1[[.y]],
1165[[%define parse.error verbose
1166%debug
1167%locations
1168
1169%code {
1170]AT_YYERROR_DECLARE[
1171]AT_YYLEX_DECLARE[
1172# define USE(SYM)
1173}
1174
1175%destructor {
1176 fprintf (yyoutput, "<]]not_kind[[> destructor should not be called.\n");
1177} <]]not_kind[[>
1178
1179%token END 0
1180%printer {
1181 fprintf (yyoutput, "<]]kind[[> for '%c' @ %d", $$, @$.first_column);
1182} <]]kind[[>
1183%destructor {
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]]])[[
1195
1196%%
1197
1198start: { $$ = 'S'; } ;
1199
1200%%
1201#include <stdlib.h> /* abort */
1202static int
1203yylex (void)
1204{
1205 static int called;
1206 if (called++)
1207 abort ();
1208 yylval]]m4_if($1, 0,, [[[.tag]]])[[ = 'E';
1209 yylloc.first_line = yylloc.last_line = 1;
1210 yylloc.first_column = yylloc.last_column = 1;
1211 return 0;
1212}
1213]AT_YYERROR_DEFINE[
1214]AT_MAIN_DEFINE[
1215]])
1216AT_BISON_OPTION_POPDEFS
1217
1218AT_BISON_CHECK([-o input$1.c input$1.y], [], [],
1219[m4_if([$1], [0],
1220[[input0.y:30.3-5: warning: useless %destructor for type <*> [-Wother]
1221input0.y:30.3-5: warning: useless %printer for type <*> [-Wother]
1222]],
1223[[input1.y:30.3-4: warning: useless %destructor for type <> [-Wother]
1224input1.y:30.3-4: warning: useless %printer for type <> [-Wother]
1225]])])
1226
1227AT_COMPILE([input$1])
1228
1229AT_PARSER_CHECK([./input$1 --debug], 0,
1230[[<]]kind[[> for 'E' @ 1.
1231<]]kind[[> for 'S' @ 1.
1232]],
1233[[Starting parse
1234Entering state 0
1235Reducing stack by rule 1 (line 49):
1236-> $$ = nterm start (1.1: <]]kind[[> for 'S' @ 1)
1237Stack now 0
1238Entering state 1
1239Reading a token: Now at end of input.
1240Shifting token END (1.1: <]]kind[[> for 'E' @ 1)
1241Entering state 2
1242Stack now 0 1 2
1243Cleanup: popping token END (1.1: <]]kind[[> for 'E' @ 1)
1244Cleanup: popping nterm start (1.1: <]]kind[[> for 'S' @ 1)
1245]])
1246
1247m4_popdef([kind])
1248m4_popdef([not_kind])
1249])
1250
1251AT_TEST(0)
1252AT_TEST(1)
1253
1254m4_popdef([AT_TEST])
1255
1256AT_CLEANUP
1257
1258
1259
1260## ------------------------------------------------------------------ ##
1261## Default %printer and %destructor are not for error or $undefined. ##
1262## ------------------------------------------------------------------ ##
1263
1264AT_SETUP([Default %printer and %destructor are not for error or $undefined])
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.
1274AT_BISON_OPTION_PUSHDEFS([%debug])
1275AT_DATA_GRAMMAR([[input.y]],
1276[[%debug
1277
1278%{
1279# include <stdio.h>
1280# include <stdlib.h>
1281]AT_YYERROR_DECLARE[
1282]AT_YYLEX_DECLARE[
1283# define USE(SYM)
1284%}
1285
1286%printer {
1287 fprintf (yyoutput, "'%c'", $$);
1288} <> <*>
1289%destructor {
1290 fprintf (stderr, "DESTROY '%c'\n", $$);
1291} <> <*>
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%%
1303]AT_YYERROR_DEFINE[
1304]AT_YYLEX_DEFINE(["abd"], [yylval = res])[
1305]AT_MAIN_DEFINE[
1306]])
1307AT_BISON_OPTION_POPDEFS
1308
1309AT_BISON_CHECK([-o input.c input.y], [], [],
1310[[input.y:23.6-8: warning: useless %destructor for type <*> [-Wother]
1311input.y:23.6-8: warning: useless %printer for type <*> [-Wother]
1312]])
1313AT_COMPILE([input])
1314AT_PARSER_CHECK([./input --debug], [1], [],
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
1357AT_SETUP([Default %printer and %destructor are not for $accept])
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
1364# to declare '%type <field> $accept'. (Also true for $undefined.)
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
1372AT_BISON_OPTION_PUSHDEFS([%debug])
1373AT_DATA_GRAMMAR([[input.y]],
1374[[%debug /* So that %printer is actually compiled. */
1375
1376%{
1377# include <stdio.h>
1378# include <stdlib.h>
1379]AT_YYERROR_DECLARE[
1380]AT_YYLEX_DECLARE[
1381# define USE(SYM)
1382%}
1383
1384%printer {
1385 char chr = $$;
1386 fprintf (yyoutput, "'%c'", chr);
1387} <> <*>
1388%destructor {
1389 char chr = $$;
1390 fprintf (stderr, "DESTROY '%c'\n", chr);
1391} <> <*>
1392
1393%union { char chr; }
1394%type <chr> start
1395
1396%%
1397
1398start: { USE($$); } ;
1399
1400%%
1401]AT_YYERROR_DEFINE[
1402]AT_YYLEX_DEFINE[
1403]AT_MAIN_DEFINE[
1404]])
1405AT_BISON_OPTION_POPDEFS
1406
1407AT_BISON_CHECK([-o input.c input.y], [], [],
1408[[input.y:24.3-4: warning: useless %destructor for type <> [-Wother]
1409input.y:24.3-4: warning: useless %printer for type <> [-Wother]
1410]])
1411AT_COMPILE([input])
1412
1413AT_CLEANUP
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
1423AT_BISON_OPTION_PUSHDEFS([%debug])
1424AT_DATA_GRAMMAR([[input.y]],
1425[[%debug /* So that %printer is actually compiled. */
1426
1427%{
1428]AT_YYERROR_DECLARE[
1429]AT_YYLEX_DECLARE[
1430# define USE(SYM)
1431# define YYLTYPE int
1432# define YYLLOC_DEFAULT(Current, Rhs, N) (void)(Rhs)
1433# define LOCATION_PRINT(File, Loc)
1434%}
1435
1436%printer { fprintf (yyoutput, "%d", @$); } <>
1437%destructor { fprintf (stderr, "DESTROY %d\n", @$); } <>
1438%printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
1439%destructor { fprintf (yyoutput, "<*> destructor should not be called"); } <*>
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%%
1453]AT_YYERROR_DEFINE[
1454]AT_YYLEX_DEFINE[
1455]AT_MAIN_DEFINE[
1456]])
1457AT_BISON_OPTION_POPDEFS
1458
1459AT_BISON_CHECK([-o input.c input.y], 0,,
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]
1463input.y:32.3-23: warning: unused value: $3 [-Wother]
1464]])
1465
1466AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
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]
1474 { @$ = 4; } // Only used.
1475 ^^^^^^^^^^^^^^^^^^^^^
1476input.y:32.3-23: warning: unused value: $3 [-Wother]
1477 { USE ($$); @$ = 3; } // Only set.
1478 ^^^^^^^^^^^^^^^^^^^^^
1479]])
1480
1481AT_COMPILE([input])
1482AT_PARSER_CHECK([./input --debug], 1,,
1483[[Starting parse
1484Entering state 0
1485Reducing stack by rule 1 (line 30):
1486-> $$ = nterm $@1 (: )
1487Stack now 0
1488Entering state 2
1489Reducing stack by rule 2 (line 31):
1490-> $$ = nterm @2 (: 2)
1491Stack now 0 2
1492Entering state 4
1493Reducing stack by rule 3 (line 32):
1494-> $$ = nterm @3 (: 3)
1495Stack now 0 2 4
1496Entering state 5
1497Reducing stack by rule 4 (line 33):
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
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)
1528# -------------------------------------------
1529m4_define([AT_CHECK_ACTION_LOCATIONS],
1530[AT_SETUP([[@$ in ]$1[ implies %locations]])
1531AT_BISON_OPTION_PUSHDEFS([%debug])
1532AT_DATA_GRAMMAR([[input.y]],
1533[[%code {
1534 #include <stdio.h>
1535]AT_YYERROR_DECLARE[
1536]AT_YYLEX_DECLARE[
1537}
1538
1539%debug
1540
1541]$1[ {
1542 fprintf (stderr, "%d\n", @$.first_line);
1543} ]m4_if($1, [%initial-action], [], [[start]])[
1544
1545%%
1546
1547start: ;
1548
1549%%
1550
1551static int
1552yylex (void)
1553{
1554 return 0;
1555}
1556
1557]AT_YYERROR_DEFINE[
1558]AT_MAIN_DEFINE[
1559]])
1560
1561AT_BISON_CHECK([[-o input.c input.y]])
1562AT_COMPILE([[input]])
1563AT_BISON_OPTION_POPDEFS
1564AT_CLEANUP])
1565
1566AT_CHECK_ACTION_LOCATIONS([[%initial-action]])
1567AT_CHECK_ACTION_LOCATIONS([[%destructor]])
1568AT_CHECK_ACTION_LOCATIONS([[%printer]])
1569
1570
1571## ------------------------- ##
1572## Qualified $$ in actions. ##
1573## ------------------------- ##
1574
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.
1578#
1579# FIXME: Not actually checking %destructor, but it's the same code as
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
1590AT_BISON_OPTION_PUSHDEFS([%skeleton "$1" %debug])
1591
1592AT_DATA_GRAMMAR([[input.y]],
1593[[%skeleton "$1"
1594%debug
1595%code requires
1596{
1597 typedef struct sem_type
1598 {
1599 int ival;
1600 float fval;
1601 } sem_type;
1602
1603# define YYSTYPE sem_type
1604
1605]AT_SKEL_CC_IF([[
1606# include <iostream>
1607 namespace
1608 {
1609 void
1610 report (std::ostream& yyo, int ival, float fval)
1611 {
1612 yyo << "ival: " << ival << ", fval: " << fval;
1613 }
1614 }
1615]], [[
1616# include <stdio.h>
1617 static void
1618 report (FILE* yyo, int ival, float fval)
1619 {
1620 fprintf (yyo, "ival: %d, fval: %1.1f", ival, fval);
1621 }
1622]])[
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
1638%initial-action
1639{
1640 $<ival>$ = 42;
1641 $<fval>$ = 4.2;
1642}
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;])[
1657]AT_MAIN_DEFINE[
1658]])
1659
1660AT_FULL_COMPILE([[input]])
1661AT_PARSER_CHECK([./input --debug], 0, [], [stderr])
1662# Don't be too picky on the traces, GLR is not exactly the same. Keep
1663# only the lines from the printer.
1664AT_CHECK([[sed -ne '/ival:/p' stderr]], 0,
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
1687## -------------------------------------------------- ##
1688## Destroying lookahead assigned by semantic action. ##
1689## -------------------------------------------------- ##
1690
1691AT_SETUP([[Destroying lookahead assigned by semantic action]])
1692
1693AT_BISON_OPTION_PUSHDEFS
1694AT_DATA_GRAMMAR([input.y],
1695[[
1696%code {
1697 #include <assert.h>
1698 #include <stdio.h>
1699]AT_YYERROR_DECLARE[
1700]AT_YYLEX_DECLARE[
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); } ;
1721accept: %empty {
1722 assert (yychar == YYEMPTY);
1723 yychar = 'b';
1724 YYACCEPT;
1725} ;
1726
1727%%
1728]AT_YYERROR_DEFINE[
1729]AT_YYLEX_DEFINE(["a"])[
1730]AT_MAIN_DEFINE[
1731]])
1732AT_BISON_OPTION_POPDEFS
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
1741
1742## ---------- ##
1743## YYBACKUP. ##
1744## ---------- ##
1745
1746AT_SETUP([[YYBACKUP]])
1747
1748AT_BISON_OPTION_PUSHDEFS([%pure-parser %debug])
1749
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
1760 ]AT_YYERROR_DECLARE[
1761 ]AT_YYLEX_DECLARE[
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%%
1775]AT_YYERROR_DEFINE[
1776]AT_YYLEX_DEFINE(["bcd"], [*lvalp = (toknum + 1) * 10])[
1777]AT_MAIN_DEFINE[
1778]])
1779AT_BISON_OPTION_POPDEFS
1780
1781AT_BISON_CHECK([[-o input.c input.y]])
1782AT_COMPILE([[input]])
1783AT_PARSER_CHECK([[./input]], [[0]],
1784[[a: 123
1785a: 456
1786]])
1787
1788AT_CLEANUP