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