1 # Exercising Bison on conflicts. -*- Autotest -*- 2 3 # Copyright (C) 2002-2005, 2007, 2009-2012 Free Software Foundation, 4 # Inc. 5 6 # This program is free software: you can redistribute it and/or modify 7 # it under the terms of the GNU General Public License as published by 8 # the Free Software Foundation, either version 3 of the License, or 9 # (at your option) any later version. 10 # 11 # This program is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 # GNU General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 19 AT_BANNER([[Conflicts.]]) 20 21 22 ## ---------------- ## 23 ## S/R in initial. ## 24 ## ---------------- ## 25 26 # I once hacked Bison in such a way that it lost its reductions on the 27 # initial state (because it was confusing it with the last state). It 28 # took me a while to strip down my failures to this simple case. So 29 # make sure it finds the s/r conflict below. 30 31 AT_SETUP([S/R in initial]) 32 33 AT_DATA([[input.y]], 34 [[%expect 1 35 %% 36 exp: e 'e'; 37 e: 'e' | /* Nothing. */; 38 ]]) 39 40 AT_BISON_CHECK([-o input.c input.y], 0, [], 41 [[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */ 42 ]]) 43 44 AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [], 45 [[input.y:4.9: warning: rule useless in parser due to conflicts 46 e: 'e' | /* Nothing. */; 47 ^ 48 ]]) 49 50 AT_CLEANUP 51 52 53 ## ------------------- ## 54 ## %nonassoc and eof. ## 55 ## ------------------- ## 56 57 AT_SETUP([%nonassoc and eof]) 58 59 AT_BISON_OPTION_PUSHDEFS 60 AT_DATA_GRAMMAR([input.y], 61 [[ 62 %{ 63 #include <stdio.h> 64 #include <stdlib.h> 65 #include <string.h> 66 #include <assert.h> 67 68 #define YYERROR_VERBOSE 1 69 ]AT_YYERROR_DEFINE[ 70 /* The current argument. */ 71 static const char *input; 72 73 static int 74 yylex (void) 75 { 76 static size_t toknum; 77 assert (toknum <= strlen (input)); 78 return input[toknum++]; 79 } 80 81 %} 82 83 %nonassoc '<' '>' 84 85 %% 86 expr: expr '<' expr 87 | expr '>' expr 88 | '0' 89 ; 90 %% 91 int 92 main (int argc, const char *argv[]) 93 { 94 input = argc <= 1 ? "" : argv[1]; 95 return yyparse (); 96 } 97 ]]) 98 AT_BISON_OPTION_POPDEFS 99 100 m4_pushdef([AT_NONASSOC_AND_EOF_CHECK], 101 [AT_BISON_CHECK([$1[ -o input.c input.y]]) 102 AT_COMPILE([input]) 103 104 m4_pushdef([AT_EXPECTING], [m4_if($2, [correct], [[, expecting $end]])]) 105 106 AT_PARSER_CHECK([./input '0<0']) 107 AT_PARSER_CHECK([./input '0<0<0'], [1], [], 108 [syntax error, unexpected '<'AT_EXPECTING 109 ]) 110 111 AT_PARSER_CHECK([./input '0>0']) 112 AT_PARSER_CHECK([./input '0>0>0'], [1], [], 113 [syntax error, unexpected '>'AT_EXPECTING 114 ]) 115 116 AT_PARSER_CHECK([./input '0<0>0'], [1], [], 117 [syntax error, unexpected '>'AT_EXPECTING 118 ]) 119 120 m4_popdef([AT_EXPECTING])]) 121 122 # Expected token list is missing. 123 AT_NONASSOC_AND_EOF_CHECK([], [[incorrect]]) 124 125 # We must disable default reductions in inconsistent states in order to 126 # have an explicit list of all expected tokens. 127 AT_NONASSOC_AND_EOF_CHECK([[-Dlr.default-reductions=consistent]], 128 [[correct]]) 129 130 # lr.default-reductions=consistent happens to work for this test case. 131 # However, for other grammars, lookahead sets can be merged for 132 # different left contexts, so it is still possible to have an incorrect 133 # expected list. Canonical LR is almost a general solution (that is, it 134 # can fail only when %nonassoc is used), so make sure it gives the same 135 # result as above. 136 AT_NONASSOC_AND_EOF_CHECK([[-Dlr.type=canonical-lr]], [[correct]]) 137 138 # parse.lac=full is a completely general solution that does not require 139 # any of the above sacrifices. Of course, it does not extend the 140 # language-recognition power of LALR to (IE)LR, but it does ensure that 141 # the reported list of expected tokens matches what the given parser 142 # would have accepted in place of the unexpected token. 143 AT_NONASSOC_AND_EOF_CHECK([[-Dparse.lac=full]], [[correct]]) 144 145 m4_popdef([AT_NONASSOC_AND_EOF_CHECK]) 146 147 AT_CLEANUP 148 149 150 151 ## -------------------------------------- ## 152 ## %error-verbose and consistent errors. ## 153 ## -------------------------------------- ## 154 155 AT_SETUP([[%error-verbose and consistent errors]]) 156 157 m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [ 158 159 AT_BISON_OPTION_PUSHDEFS([$1]) 160 161 m4_pushdef([AT_YYLEX_PROTOTYPE], 162 [AT_SKEL_CC_IF([[int yylex (yy::parser::semantic_type *lvalp)]], 163 [[int yylex (YYSTYPE *lvalp)]])]) 164 165 AT_SKEL_JAVA_IF([AT_DATA], [AT_DATA_GRAMMAR])([input.y], 166 [AT_SKEL_JAVA_IF([[ 167 168 %code imports { 169 import java.io.IOException; 170 }]], [[ 171 172 %code {]AT_SKEL_CC_IF([[ 173 #include <cassert> 174 #include <string>]], [[ 175 #include <assert.h> 176 #include <stdio.h> 177 ]AT_YYERROR_DECLARE])[ 178 ]AT_YYLEX_PROTOTYPE[; 179 #define USE(Var) 180 } 181 182 ]AT_SKEL_CC_IF([[%defines]], [[%define api.pure]])])[ 183 184 ]$1[ 185 186 %error-verbose 187 188 %% 189 190 ]$2[ 191 192 ]AT_SKEL_JAVA_IF([[%code lexer {]], [[%%]])[ 193 194 /*--------. 195 | yylex. | 196 `--------*/]AT_SKEL_JAVA_IF([[ 197 198 public String input = "]$3["; 199 public int index = 0; 200 public int yylex () 201 { 202 if (index < input.length ()) 203 return input.charAt (index++); 204 else 205 return 0; 206 } 207 public Object getLVal () 208 { 209 return new Integer(1); 210 }]], [[ 211 212 ]AT_YYLEX_PROTOTYPE[ 213 { 214 static char const *input = "]$3["; 215 *lvalp = 1; 216 return *input++; 217 }]])[ 218 ]AT_YYERROR_DEFINE[ 219 ]AT_SKEL_JAVA_IF([[ 220 }; 221 222 %%]])[ 223 224 /*-------. 225 | main. | 226 `-------*/]AT_SKEL_JAVA_IF([[ 227 228 class input 229 { 230 public static void main (String args[]) throws IOException 231 { 232 YYParser p = new YYParser (); 233 p.parse (); 234 } 235 }]], [AT_SKEL_CC_IF([[ 236 237 int 238 main (void) 239 { 240 yy::parser parser; 241 return parser.parse (); 242 }]], [[ 243 244 int 245 main (void) 246 { 247 return yyparse (); 248 }]])])[ 249 ]]) 250 251 AT_FULL_COMPILE([[input]]) 252 253 m4_pushdef([AT_EXPECTING], [m4_if($5, [ab], [[, expecting 'a' or 'b']], 254 $5, [a], [[, expecting 'a']], 255 $5, [b], [[, expecting 'b']])]) 256 257 AT_SKEL_JAVA_IF([AT_JAVA_PARSER_CHECK([[input]], [[0]]], 258 [AT_PARSER_CHECK([[./input]], [[1]]]), 259 [[]], 260 [[syntax error, unexpected ]$4[]AT_EXPECTING[ 261 ]]) 262 263 m4_popdef([AT_EXPECTING]) 264 m4_popdef([AT_YYLEX_PROTOTYPE]) 265 AT_BISON_OPTION_POPDEFS 266 267 ]) 268 269 m4_pushdef([AT_PREVIOUS_STATE_GRAMMAR], 270 [[%nonassoc 'a'; 271 272 start: consistent-error-on-a-a 'a' ; 273 274 consistent-error-on-a-a: 275 'a' default-reduction 276 | 'a' default-reduction 'a' 277 | 'a' shift 278 ; 279 280 default-reduction: /*empty*/ ; 281 shift: 'b' ; 282 283 // Provide another context in which all rules are useful so that this 284 // test case looks a little more realistic. 285 start: 'b' consistent-error-on-a-a 'c' ; 286 ]]) 287 288 m4_pushdef([AT_PREVIOUS_STATE_INPUT], [[a]]) 289 290 # Unfortunately, no expected tokens are reported even though 'b' can be 291 # accepted. Nevertheless, the main point of this test is to make sure 292 # that at least the unexpected token is reported. In a previous version 293 # of Bison, it wasn't reported because the error is detected in a 294 # consistent state with an error action, and that case always triggered 295 # the simple "syntax error" message. 296 # 297 # The point isn't to test IELR here, but state merging happens to 298 # complicate this example. 299 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr]], 300 [AT_PREVIOUS_STATE_GRAMMAR], 301 [AT_PREVIOUS_STATE_INPUT], 302 [[$end]], [[none]]) 303 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr 304 %glr-parser]], 305 [AT_PREVIOUS_STATE_GRAMMAR], 306 [AT_PREVIOUS_STATE_INPUT], 307 [[$end]], [[none]]) 308 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr 309 %language "c++"]], 310 [AT_PREVIOUS_STATE_GRAMMAR], 311 [AT_PREVIOUS_STATE_INPUT], 312 [[$end]], [[none]]) 313 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr 314 %language "java"]], 315 [AT_PREVIOUS_STATE_GRAMMAR], 316 [AT_PREVIOUS_STATE_INPUT], 317 [[end of input]], [[none]]) 318 319 # Even canonical LR doesn't foresee the error for 'a'! 320 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr 321 %define lr.default-reductions consistent]], 322 [AT_PREVIOUS_STATE_GRAMMAR], 323 [AT_PREVIOUS_STATE_INPUT], 324 [[$end]], [[ab]]) 325 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr 326 %define lr.default-reductions accepting]], 327 [AT_PREVIOUS_STATE_GRAMMAR], 328 [AT_PREVIOUS_STATE_INPUT], 329 [[$end]], [[ab]]) 330 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]], 331 [AT_PREVIOUS_STATE_GRAMMAR], 332 [AT_PREVIOUS_STATE_INPUT], 333 [[$end]], [[ab]]) 334 335 # Only LAC gets it right. 336 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr 337 %define parse.lac full]], 338 [AT_PREVIOUS_STATE_GRAMMAR], 339 [AT_PREVIOUS_STATE_INPUT], 340 [[$end]], [[b]]) 341 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr 342 %define parse.lac full]], 343 [AT_PREVIOUS_STATE_GRAMMAR], 344 [AT_PREVIOUS_STATE_INPUT], 345 [[$end]], [[b]]) 346 347 m4_popdef([AT_PREVIOUS_STATE_GRAMMAR]) 348 m4_popdef([AT_PREVIOUS_STATE_INPUT]) 349 350 m4_pushdef([AT_USER_ACTION_GRAMMAR], 351 [[%nonassoc 'a'; 352 353 // If $$ = 0 here, then we know that the 'a' destructor is being invoked 354 // incorrectly for the 'b' set in the semantic action below. All 'a' 355 // tokens are returned by yylex, which sets $$ = 1. 356 %destructor { 357 if (!$$) 358 fprintf (stderr, "Wrong destructor.\n"); 359 } 'a'; 360 361 // Rather than depend on an inconsistent state to induce reading a 362 // lookahead as in the previous grammar, just assign the lookahead in a 363 // semantic action. That lookahead isn't needed before either error 364 // action is encountered. In a previous version of Bison, this was a 365 // problem as it meant yychar was not translated into yytoken before 366 // either error action. The second error action thus invoked a 367 // destructor that it selected according to the incorrect yytoken. The 368 // first error action would have reported an incorrect unexpected token 369 // except that, due to the bug described in the previous grammar, the 370 // unexpected token was not reported at all. 371 start: error-reduce consistent-error 'a' { USE ($][3); } ; 372 373 error-reduce: 374 'a' 'a' consistent-reduction consistent-error 'a' 375 { USE (($][1, $][2, $][5)); } 376 | 'a' error 377 { USE ($][1); } 378 ; 379 380 consistent-reduction: /*empty*/ { 381 assert (yychar == ]AT_SKEL_CC_IF([[yyempty_]], [[YYEMPTY]])[); 382 yylval = 0; 383 yychar = 'b'; 384 } ; 385 386 consistent-error: 387 'a' { USE ($][1); } 388 | /*empty*/ %prec 'a' 389 ; 390 391 // Provide another context in which all rules are useful so that this 392 // test case looks a little more realistic. 393 start: 'b' consistent-error 'b' ; 394 ]]) 395 m4_pushdef([AT_USER_ACTION_INPUT], [[aa]]) 396 397 AT_CONSISTENT_ERRORS_CHECK([[]], 398 [AT_USER_ACTION_GRAMMAR], 399 [AT_USER_ACTION_INPUT], 400 [['b']], [[none]]) 401 AT_CONSISTENT_ERRORS_CHECK([[%glr-parser]], 402 [AT_USER_ACTION_GRAMMAR], 403 [AT_USER_ACTION_INPUT], 404 [['b']], [[none]]) 405 AT_CONSISTENT_ERRORS_CHECK([[%language "c++"]], 406 [AT_USER_ACTION_GRAMMAR], 407 [AT_USER_ACTION_INPUT], 408 [['b']], [[none]]) 409 # No Java test because yychar cannot be manipulated by users. 410 411 AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions consistent]], 412 [AT_USER_ACTION_GRAMMAR], 413 [AT_USER_ACTION_INPUT], 414 [['b']], [[none]]) 415 416 # Canonical LR doesn't foresee the error for 'a'! 417 AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions accepting]], 418 [AT_USER_ACTION_GRAMMAR], 419 [AT_USER_ACTION_INPUT], 420 [[$end]], [[a]]) 421 AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]], 422 [AT_USER_ACTION_GRAMMAR], 423 [AT_USER_ACTION_INPUT], 424 [[$end]], [[a]]) 425 426 AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full]], 427 [AT_USER_ACTION_GRAMMAR], 428 [AT_USER_ACTION_INPUT], 429 [['b']], [[none]]) 430 AT_CONSISTENT_ERRORS_CHECK([[%define parse.lac full 431 %define lr.default-reductions accepting]], 432 [AT_USER_ACTION_GRAMMAR], 433 [AT_USER_ACTION_INPUT], 434 [[$end]], [[none]]) 435 436 m4_popdef([AT_USER_ACTION_GRAMMAR]) 437 m4_popdef([AT_USER_ACTION_INPUT]) 438 439 m4_popdef([AT_CONSISTENT_ERRORS_CHECK]) 440 441 AT_CLEANUP 442 443 444 445 ## ------------------------------------------------------- ## 446 ## LAC: %nonassoc requires splitting canonical LR states. ## 447 ## ------------------------------------------------------- ## 448 449 # This test case demonstrates that, when %nonassoc is used, canonical 450 # LR(1) parser table construction followed by conflict resolution 451 # without further state splitting is not always sufficient to produce a 452 # parser that can detect all syntax errors as soon as possible on one 453 # token of lookahead. However, LAC solves the problem completely even 454 # with minimal LR parser tables. 455 456 AT_SETUP([[LAC: %nonassoc requires splitting canonical LR states]]) 457 AT_BISON_OPTION_PUSHDEFS 458 AT_DATA_GRAMMAR([[input.y]], 459 [[%code { 460 #include <stdio.h> 461 ]AT_YYERROR_DECLARE[ 462 ]AT_YYLEX_DECLARE[ 463 } 464 465 %error-verbose 466 %nonassoc 'a' 467 468 %% 469 470 start: 471 'a' problem 'a' // First context. 472 | 'b' problem 'b' // Second context. 473 | 'c' reduce-nonassoc // Just makes reduce-nonassoc useful. 474 ; 475 476 problem: 477 look reduce-nonassoc 478 | look 'a' 479 | look 'b' 480 ; 481 482 // For the state reached after shifting the 'a' in these productions, 483 // lookahead sets are the same in both the first and second contexts. 484 // Thus, canonical LR reuses the same state for both contexts. However, 485 // the lookahead 'a' for the reduction "look: 'a'" later becomes an 486 // error action only in the first context. In order to immediately 487 // detect the syntax error on 'a' here for only the first context, this 488 // canonical LR state would have to be split into two states, and the 489 // 'a' lookahead would have to be removed from only one of the states. 490 look: 491 'a' // Reduction lookahead set is always ['a', 'b']. 492 | 'a' 'b' 493 | 'a' 'c' // 'c' is forgotten as an expected token. 494 ; 495 496 reduce-nonassoc: %prec 'a'; 497 498 %% 499 ]AT_YYERROR_DEFINE[ 500 ]AT_YYLEX_DEFINE(["aaa"])[ 501 502 int 503 main (void) 504 { 505 return yyparse (); 506 } 507 ]]) 508 AT_BISON_OPTION_POPDEFS 509 510 # Show canonical LR's failure. 511 AT_BISON_CHECK([[-Dlr.type=canonical-lr -o input.c input.y]], 512 [[0]], [[]], 513 [[input.y: conflicts: 2 shift/reduce 514 ]]) 515 AT_COMPILE([[input]]) 516 AT_PARSER_CHECK([[./input]], [[1]], [[]], 517 [[syntax error, unexpected 'a', expecting 'b' 518 ]]) 519 520 # It's corrected by LAC. 521 AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \ 522 -o input.c input.y]], [[0]], [[]], 523 [[input.y: conflicts: 2 shift/reduce 524 ]]) 525 AT_COMPILE([[input]]) 526 AT_PARSER_CHECK([[./input]], [[1]], [[]], 527 [[syntax error, unexpected 'a', expecting 'b' or 'c' 528 ]]) 529 530 # IELR is sufficient when LAC is used. 531 AT_BISON_CHECK([[-Dlr.type=ielr -Dparse.lac=full -o input.c input.y]], 532 [[0]], [[]], 533 [[input.y: conflicts: 2 shift/reduce 534 ]]) 535 AT_COMPILE([[input]]) 536 AT_PARSER_CHECK([[./input]], [[1]], [[]], 537 [[syntax error, unexpected 'a', expecting 'b' or 'c' 538 ]]) 539 540 AT_CLEANUP 541 542 ## ------------------------- ## 543 ## Unresolved SR Conflicts. ## 544 ## ------------------------- ## 545 546 AT_SETUP([Unresolved SR Conflicts]) 547 548 AT_KEYWORDS([report]) 549 550 AT_DATA([input.y], 551 [[%token NUM OP 552 %% 553 exp: exp OP exp | NUM; 554 ]]) 555 556 AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], 557 [input.y: conflicts: 1 shift/reduce 558 ]) 559 560 # Check the contents of the report. 561 AT_CHECK([cat input.output], [], 562 [[State 5 conflicts: 1 shift/reduce 563 564 565 Grammar 566 567 0 $accept: exp $end 568 569 1 exp: exp OP exp 570 2 | NUM 571 572 573 Terminals, with rules where they appear 574 575 $end (0) 0 576 error (256) 577 NUM (258) 2 578 OP (259) 1 579 580 581 Nonterminals, with rules where they appear 582 583 $accept (5) 584 on left: 0 585 exp (6) 586 on left: 1 2, on right: 0 1 587 588 589 State 0 590 591 0 $accept: . exp $end 592 1 exp: . exp OP exp 593 2 | . NUM 594 595 NUM shift, and go to state 1 596 597 exp go to state 2 598 599 600 State 1 601 602 2 exp: NUM . 603 604 $default reduce using rule 2 (exp) 605 606 607 State 2 608 609 0 $accept: exp . $end 610 1 exp: exp . OP exp 611 612 $end shift, and go to state 3 613 OP shift, and go to state 4 614 615 616 State 3 617 618 0 $accept: exp $end . 619 620 $default accept 621 622 623 State 4 624 625 1 exp: . exp OP exp 626 1 | exp OP . exp 627 2 | . NUM 628 629 NUM shift, and go to state 1 630 631 exp go to state 5 632 633 634 State 5 635 636 1 exp: exp . OP exp 637 1 | exp OP exp . [$end, OP] 638 639 OP shift, and go to state 4 640 641 OP [reduce using rule 1 (exp)] 642 $default reduce using rule 1 (exp) 643 ]]) 644 645 AT_CLEANUP 646 647 648 649 ## ----------------------- ## 650 ## Resolved SR Conflicts. ## 651 ## ----------------------- ## 652 653 AT_SETUP([Resolved SR Conflicts]) 654 655 AT_KEYWORDS([report]) 656 657 AT_DATA([input.y], 658 [[%token NUM OP 659 %left OP 660 %% 661 exp: exp OP exp | NUM; 662 ]]) 663 664 AT_BISON_CHECK([-o input.c --report=all input.y]) 665 666 # Check the contents of the report. 667 AT_CHECK([cat input.output], [], 668 [[Grammar 669 670 0 $accept: exp $end 671 672 1 exp: exp OP exp 673 2 | NUM 674 675 676 Terminals, with rules where they appear 677 678 $end (0) 0 679 error (256) 680 NUM (258) 2 681 OP (259) 1 682 683 684 Nonterminals, with rules where they appear 685 686 $accept (5) 687 on left: 0 688 exp (6) 689 on left: 1 2, on right: 0 1 690 691 692 State 0 693 694 0 $accept: . exp $end 695 1 exp: . exp OP exp 696 2 | . NUM 697 698 NUM shift, and go to state 1 699 700 exp go to state 2 701 702 703 State 1 704 705 2 exp: NUM . 706 707 $default reduce using rule 2 (exp) 708 709 710 State 2 711 712 0 $accept: exp . $end 713 1 exp: exp . OP exp 714 715 $end shift, and go to state 3 716 OP shift, and go to state 4 717 718 719 State 3 720 721 0 $accept: exp $end . 722 723 $default accept 724 725 726 State 4 727 728 1 exp: . exp OP exp 729 1 | exp OP . exp 730 2 | . NUM 731 732 NUM shift, and go to state 1 733 734 exp go to state 5 735 736 737 State 5 738 739 1 exp: exp . OP exp 740 1 | exp OP exp . [$end, OP] 741 742 $default reduce using rule 1 (exp) 743 744 Conflict between rule 1 and token OP resolved as reduce (%left OP). 745 ]]) 746 747 AT_CLEANUP 748 749 750 ## -------------------------------- ## 751 ## Defaulted Conflicted Reduction. ## 752 ## -------------------------------- ## 753 754 # When there are RR conflicts, some rules are disabled. Usually it is 755 # simply displayed as: 756 # 757 # $end reduce using rule 3 (num) 758 # $end [reduce using rule 4 (id)] 759 # 760 # But when `reduce 3' is the default action, we'd produce: 761 # 762 # $end [reduce using rule 4 (id)] 763 # $default reduce using rule 3 (num) 764 # 765 # In this precise case (a reduction is masked by the default 766 # reduction), we make the `reduce 3' explicit: 767 # 768 # $end reduce using rule 3 (num) 769 # $end [reduce using rule 4 (id)] 770 # $default reduce using rule 3 (num) 771 # 772 # Maybe that's not the best display, but then, please propose something 773 # else. 774 775 AT_SETUP([Defaulted Conflicted Reduction]) 776 AT_KEYWORDS([report]) 777 778 AT_DATA([input.y], 779 [[%% 780 exp: num | id; 781 num: '0'; 782 id : '0'; 783 %% 784 ]]) 785 786 AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], 787 [[input.y: conflicts: 1 reduce/reduce 788 input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0' 789 ]]) 790 791 # Check the contents of the report. 792 AT_CHECK([cat input.output], [], 793 [[Rules useless in parser due to conflicts 794 795 4 id: '0' 796 797 798 State 1 conflicts: 1 reduce/reduce 799 800 801 Grammar 802 803 0 $accept: exp $end 804 805 1 exp: num 806 2 | id 807 808 3 num: '0' 809 810 4 id: '0' 811 812 813 Terminals, with rules where they appear 814 815 $end (0) 0 816 '0' (48) 3 4 817 error (256) 818 819 820 Nonterminals, with rules where they appear 821 822 $accept (4) 823 on left: 0 824 exp (5) 825 on left: 1 2, on right: 0 826 num (6) 827 on left: 3, on right: 1 828 id (7) 829 on left: 4, on right: 2 830 831 832 State 0 833 834 0 $accept: . exp $end 835 1 exp: . num 836 2 | . id 837 3 num: . '0' 838 4 id: . '0' 839 840 '0' shift, and go to state 1 841 842 exp go to state 2 843 num go to state 3 844 id go to state 4 845 846 847 State 1 848 849 3 num: '0' . [$end] 850 4 id: '0' . [$end] 851 852 $end reduce using rule 3 (num) 853 $end [reduce using rule 4 (id)] 854 $default reduce using rule 3 (num) 855 856 857 State 2 858 859 0 $accept: exp . $end 860 861 $end shift, and go to state 5 862 863 864 State 3 865 866 1 exp: num . 867 868 $default reduce using rule 1 (exp) 869 870 871 State 4 872 873 2 exp: id . 874 875 $default reduce using rule 2 (exp) 876 877 878 State 5 879 880 0 $accept: exp $end . 881 882 $default accept 883 ]]) 884 885 AT_CLEANUP 886 887 888 889 890 ## -------------------- ## 891 ## %expect not enough. ## 892 ## -------------------- ## 893 894 AT_SETUP([%expect not enough]) 895 896 AT_DATA([input.y], 897 [[%token NUM OP 898 %expect 0 899 %% 900 exp: exp OP exp | NUM; 901 ]]) 902 903 AT_BISON_CHECK([-o input.c input.y], 1, [], 904 [input.y: conflicts: 1 shift/reduce 905 input.y: error: expected 0 shift/reduce conflicts 906 ]) 907 AT_CLEANUP 908 909 910 ## --------------- ## 911 ## %expect right. ## 912 ## --------------- ## 913 914 AT_SETUP([%expect right]) 915 916 AT_DATA([input.y], 917 [[%token NUM OP 918 %expect 1 919 %% 920 exp: exp OP exp | NUM; 921 ]]) 922 923 AT_BISON_CHECK([-o input.c input.y]) 924 AT_CLEANUP 925 926 927 ## ------------------ ## 928 ## %expect too much. ## 929 ## ------------------ ## 930 931 AT_SETUP([%expect too much]) 932 933 AT_DATA([input.y], 934 [[%token NUM OP 935 %expect 2 936 %% 937 exp: exp OP exp | NUM; 938 ]]) 939 940 AT_BISON_CHECK([-o input.c input.y], 1, [], 941 [input.y: conflicts: 1 shift/reduce 942 input.y: error: expected 2 shift/reduce conflicts 943 ]) 944 AT_CLEANUP 945 946 947 ## ------------------------------- ## 948 ## %expect with reduce conflicts. ## 949 ## ------------------------------- ## 950 951 AT_SETUP([%expect with reduce conflicts]) 952 953 AT_DATA([input.y], 954 [[%expect 0 955 %% 956 program: a 'a' | a a; 957 a: 'a'; 958 ]]) 959 960 AT_BISON_CHECK([-o input.c input.y], 1, [], 961 [input.y: conflicts: 1 reduce/reduce 962 input.y: error: expected 0 reduce/reduce conflicts 963 ]) 964 AT_CLEANUP 965 966 967 ## ------------------------- ## 968 ## %prec with user strings. ## 969 ## ------------------------- ## 970 971 AT_SETUP([%prec with user string]) 972 973 AT_DATA([[input.y]], 974 [[%% 975 exp: 976 "foo" %prec "foo" 977 ; 978 ]]) 979 980 AT_BISON_CHECK([-o input.c input.y]) 981 AT_CLEANUP 982 983 984 ## -------------------------------- ## 985 ## %no-default-prec without %prec. ## 986 ## -------------------------------- ## 987 988 AT_SETUP([%no-default-prec without %prec]) 989 990 AT_DATA([[input.y]], 991 [[%left '+' 992 %left '*' 993 994 %% 995 996 %no-default-prec; 997 998 e: e '+' e 999 | e '*' e 1000 | '0' 1001 ; 1002 ]]) 1003 1004 AT_BISON_CHECK([-o input.c input.y], 0, [], 1005 [[input.y: conflicts: 4 shift/reduce 1006 ]]) 1007 AT_CLEANUP 1008 1009 1010 ## ----------------------------- ## 1011 ## %no-default-prec with %prec. ## 1012 ## ----------------------------- ## 1013 1014 AT_SETUP([%no-default-prec with %prec]) 1015 1016 AT_DATA([[input.y]], 1017 [[%left '+' 1018 %left '*' 1019 1020 %% 1021 1022 %no-default-prec; 1023 1024 e: e '+' e %prec '+' 1025 | e '*' e %prec '*' 1026 | '0' 1027 ; 1028 ]]) 1029 1030 AT_BISON_CHECK([-o input.c input.y]) 1031 AT_CLEANUP 1032 1033 1034 ## --------------- ## 1035 ## %default-prec. ## 1036 ## --------------- ## 1037 1038 AT_SETUP([%default-prec]) 1039 1040 AT_DATA([[input.y]], 1041 [[%left '+' 1042 %left '*' 1043 1044 %% 1045 1046 %default-prec; 1047 1048 e: e '+' e 1049 | e '*' e 1050 | '0' 1051 ; 1052 ]]) 1053 1054 AT_BISON_CHECK([-o input.c input.y]) 1055 AT_CLEANUP 1056 1057 1058 ## ---------------------------------------------- ## 1059 ## Unreachable States After Conflict Resolution. ## 1060 ## ---------------------------------------------- ## 1061 1062 AT_SETUP([[Unreachable States After Conflict Resolution]]) 1063 1064 # If conflict resolution makes states unreachable, remove those states, report 1065 # rules that are then unused, and don't report conflicts in those states. Test 1066 # what happens when a nonterminal becomes useless as a result of state removal 1067 # since that causes lalr.o's goto map to be rewritten. 1068 1069 AT_DATA([[input.y]], 1070 [[%output "input.c" 1071 %left 'a' 1072 1073 %% 1074 1075 start: resolved_conflict 'a' reported_conflicts 'a' ; 1076 1077 /* S/R conflict resolved as reduce, so the state with item 1078 * (resolved_conflict: 'a' . unreachable1) and all it transition successors are 1079 * unreachable, and the associated production is useless. */ 1080 resolved_conflict: 1081 'a' unreachable1 1082 | %prec 'a' 1083 ; 1084 1085 /* S/R conflict that need not be reported since it is unreachable because of 1086 * the previous conflict resolution. Nonterminal unreachable1 and all its 1087 * productions are useless. */ 1088 unreachable1: 1089 'a' unreachable2 1090 | 1091 ; 1092 1093 /* Likewise for a R/R conflict and nonterminal unreachable2. */ 1094 unreachable2: | ; 1095 1096 /* Make sure remaining S/R and R/R conflicts are still reported correctly even 1097 * when their states are renumbered due to state removal. */ 1098 reported_conflicts: 1099 'a' 1100 | 'a' 1101 | 1102 ; 1103 1104 ]]) 1105 1106 AT_BISON_CHECK([[--report=all input.y]], 0, [], 1107 [[input.y: conflicts: 1 shift/reduce, 1 reduce/reduce 1108 input.y:12.5-20: warning: rule useless in parser due to conflicts: resolved_conflict: 'a' unreachable1 1109 input.y:20.5-20: warning: rule useless in parser due to conflicts: unreachable1: 'a' unreachable2 1110 input.y:21.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ 1111 input.y:25.13: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ 1112 input.y:25.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ 1113 input.y:31.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' 1114 input.y:32.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ 1115 ]]) 1116 1117 AT_CHECK([[cat input.output]], 0, 1118 [[Rules useless in parser due to conflicts 1119 1120 2 resolved_conflict: 'a' unreachable1 1121 1122 4 unreachable1: 'a' unreachable2 1123 5 | /* empty */ 1124 1125 6 unreachable2: /* empty */ 1126 7 | /* empty */ 1127 1128 9 reported_conflicts: 'a' 1129 10 | /* empty */ 1130 1131 1132 State 4 conflicts: 1 shift/reduce 1133 State 5 conflicts: 1 reduce/reduce 1134 1135 1136 Grammar 1137 1138 0 $accept: start $end 1139 1140 1 start: resolved_conflict 'a' reported_conflicts 'a' 1141 1142 2 resolved_conflict: 'a' unreachable1 1143 3 | /* empty */ 1144 1145 4 unreachable1: 'a' unreachable2 1146 5 | /* empty */ 1147 1148 6 unreachable2: /* empty */ 1149 7 | /* empty */ 1150 1151 8 reported_conflicts: 'a' 1152 9 | 'a' 1153 10 | /* empty */ 1154 1155 1156 Terminals, with rules where they appear 1157 1158 $end (0) 0 1159 'a' (97) 1 2 4 8 9 1160 error (256) 1161 1162 1163 Nonterminals, with rules where they appear 1164 1165 $accept (4) 1166 on left: 0 1167 start (5) 1168 on left: 1, on right: 0 1169 resolved_conflict (6) 1170 on left: 2 3, on right: 1 1171 unreachable1 (7) 1172 on left: 4 5, on right: 2 1173 unreachable2 (8) 1174 on left: 6 7, on right: 4 1175 reported_conflicts (9) 1176 on left: 8 9 10, on right: 1 1177 1178 1179 State 0 1180 1181 0 $accept: . start $end 1182 1 start: . resolved_conflict 'a' reported_conflicts 'a' 1183 2 resolved_conflict: . 'a' unreachable1 1184 3 | . ['a'] 1185 1186 $default reduce using rule 3 (resolved_conflict) 1187 1188 start go to state 1 1189 resolved_conflict go to state 2 1190 1191 Conflict between rule 3 and token 'a' resolved as reduce (%left 'a'). 1192 1193 1194 State 1 1195 1196 0 $accept: start . $end 1197 1198 $end shift, and go to state 3 1199 1200 1201 State 2 1202 1203 1 start: resolved_conflict . 'a' reported_conflicts 'a' 1204 1205 'a' shift, and go to state 4 1206 1207 1208 State 3 1209 1210 0 $accept: start $end . 1211 1212 $default accept 1213 1214 1215 State 4 1216 1217 1 start: resolved_conflict 'a' . reported_conflicts 'a' 1218 8 reported_conflicts: . 'a' 1219 9 | . 'a' 1220 10 | . ['a'] 1221 1222 'a' shift, and go to state 5 1223 1224 'a' [reduce using rule 10 (reported_conflicts)] 1225 1226 reported_conflicts go to state 6 1227 1228 1229 State 5 1230 1231 8 reported_conflicts: 'a' . ['a'] 1232 9 | 'a' . ['a'] 1233 1234 'a' reduce using rule 8 (reported_conflicts) 1235 'a' [reduce using rule 9 (reported_conflicts)] 1236 $default reduce using rule 8 (reported_conflicts) 1237 1238 1239 State 6 1240 1241 1 start: resolved_conflict 'a' reported_conflicts . 'a' 1242 1243 'a' shift, and go to state 7 1244 1245 1246 State 7 1247 1248 1 start: resolved_conflict 'a' reported_conflicts 'a' . 1249 1250 $default reduce using rule 1 (start) 1251 ]]) 1252 1253 AT_DATA([[input-keep.y]], 1254 [[%define lr.keep-unreachable-states 1255 ]]) 1256 AT_CHECK([[cat input.y >> input-keep.y]]) 1257 1258 AT_BISON_CHECK([[input-keep.y]], 0, [], 1259 [[input-keep.y: conflicts: 2 shift/reduce, 2 reduce/reduce 1260 input-keep.y:22.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ 1261 input-keep.y:26.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ 1262 input-keep.y:32.5-7: warning: rule useless in parser due to conflicts: reported_conflicts: 'a' 1263 input-keep.y:33.4: warning: rule useless in parser due to conflicts: reported_conflicts: /* empty */ 1264 ]]) 1265 1266 AT_CLEANUP 1267 1268 1269 ## ------------------------------------------------------------ ## 1270 ## Solved conflicts report for multiple reductions in a state. ## 1271 ## ------------------------------------------------------------ ## 1272 1273 AT_SETUP([[Solved conflicts report for multiple reductions in a state]]) 1274 1275 # Used to lose earlier solved conflict messages even within a single S/R/R. 1276 1277 AT_DATA([[input.y]], 1278 [[%left 'a' 1279 %right 'b' 1280 %right 'c' 1281 %right 'd' 1282 %% 1283 start: 1284 'a' 1285 | empty_a 'a' 1286 | 'b' 1287 | empty_b 'b' 1288 | 'c' 1289 | empty_c1 'c' 1290 | empty_c2 'c' 1291 | empty_c3 'c' 1292 ; 1293 empty_a: %prec 'a' ; 1294 empty_b: %prec 'b' ; 1295 empty_c1: %prec 'c' ; 1296 empty_c2: %prec 'c' ; 1297 empty_c3: %prec 'd' ; 1298 ]]) 1299 AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore]) 1300 AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0, 1301 [[State 0 1302 1303 0 $accept: . start $end 1304 1 start: . 'a' 1305 2 | . empty_a 'a' 1306 3 | . 'b' 1307 4 | . empty_b 'b' 1308 5 | . 'c' 1309 6 | . empty_c1 'c' 1310 7 | . empty_c2 'c' 1311 8 | . empty_c3 'c' 1312 9 empty_a: . ['a'] 1313 10 empty_b: . [] 1314 11 empty_c1: . [] 1315 12 empty_c2: . [] 1316 13 empty_c3: . ['c'] 1317 1318 'b' shift, and go to state 1 1319 1320 'c' reduce using rule 13 (empty_c3) 1321 $default reduce using rule 9 (empty_a) 1322 1323 start go to state 2 1324 empty_a go to state 3 1325 empty_b go to state 4 1326 empty_c1 go to state 5 1327 empty_c2 go to state 6 1328 empty_c3 go to state 7 1329 1330 Conflict between rule 9 and token 'a' resolved as reduce (%left 'a'). 1331 Conflict between rule 10 and token 'b' resolved as shift (%right 'b'). 1332 Conflict between rule 11 and token 'c' resolved as shift (%right 'c'). 1333 Conflict between rule 12 and token 'c' resolved as shift (%right 'c'). 1334 Conflict between rule 13 and token 'c' resolved as reduce ('c' < 'd'). 1335 1336 1337 State 1 1338 ]]) 1339 1340 AT_CLEANUP 1341 1342 1343 ## ------------------------------------------------------------ ## 1344 ## %nonassoc error actions for multiple reductions in a state. ## 1345 ## ------------------------------------------------------------ ## 1346 1347 # Used to abort when trying to resolve conflicts as %nonassoc error actions for 1348 # multiple reductions in a state. 1349 1350 # For a %nonassoc error action token, used to print the first remaining 1351 # reduction on that token without brackets. 1352 1353 AT_SETUP([[%nonassoc error actions for multiple reductions in a state]]) 1354 1355 AT_DATA([[input.y]], 1356 [[%nonassoc 'a' 'b' 'c' 1357 %% 1358 start: 1359 'a' 1360 | empty_a 'a' 1361 | 'b' 1362 | empty_b 'b' 1363 | 'c' 1364 | empty_c1 'c' 1365 | empty_c2 'c' 1366 | empty_c3 'c' 1367 ; 1368 empty_a: %prec 'a' ; 1369 empty_b: %prec 'b' ; 1370 empty_c1: %prec 'c' ; 1371 empty_c2: %prec 'c' ; 1372 empty_c3: %prec 'c' ; 1373 ]]) 1374 1375 AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore]) 1376 AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0, 1377 [[State 0 1378 1379 0 $accept: . start $end 1380 1 start: . 'a' 1381 2 | . empty_a 'a' 1382 3 | . 'b' 1383 4 | . empty_b 'b' 1384 5 | . 'c' 1385 6 | . empty_c1 'c' 1386 7 | . empty_c2 'c' 1387 8 | . empty_c3 'c' 1388 9 empty_a: . [] 1389 10 empty_b: . [] 1390 11 empty_c1: . [] 1391 12 empty_c2: . ['c'] 1392 13 empty_c3: . ['c'] 1393 1394 'a' error (nonassociative) 1395 'b' error (nonassociative) 1396 'c' error (nonassociative) 1397 1398 'c' [reduce using rule 12 (empty_c2)] 1399 'c' [reduce using rule 13 (empty_c3)] 1400 1401 start go to state 1 1402 empty_a go to state 2 1403 empty_b go to state 3 1404 empty_c1 go to state 4 1405 empty_c2 go to state 5 1406 empty_c3 go to state 6 1407 1408 Conflict between rule 9 and token 'a' resolved as an error (%nonassoc 'a'). 1409 Conflict between rule 10 and token 'b' resolved as an error (%nonassoc 'b'). 1410 Conflict between rule 11 and token 'c' resolved as an error (%nonassoc 'c'). 1411 1412 1413 State 1 1414 ]]) 1415 AT_CLEANUP 1416 1417 1418 ## --------------------------------- ## 1419 ## -W versus %expect and %expect-rr ## 1420 ## --------------------------------- ## 1421 1422 AT_SETUP([[-W versus %expect and %expect-rr]]) 1423 1424 AT_DATA([[sr-rr.y]], 1425 [[%glr-parser 1426 %% 1427 start: 'a' | A 'a' | B 'a' ; 1428 A: ; 1429 B: ; 1430 ]]) 1431 AT_DATA([[sr.y]], 1432 [[%glr-parser 1433 %% 1434 start: 'a' | A 'a' ; 1435 A: ; 1436 ]]) 1437 AT_DATA([[rr.y]], 1438 [[%glr-parser 1439 %% 1440 start: A | B ; 1441 A: ; 1442 B: ; 1443 ]]) 1444 1445 AT_BISON_CHECK([[sr-rr.y]], [[0]], [[]], 1446 [[sr-rr.y: conflicts: 1 shift/reduce, 1 reduce/reduce 1447 ]]) 1448 AT_BISON_CHECK([[-Wno-conflicts-sr sr-rr.y]], [[0]], [[]], 1449 [[sr-rr.y: conflicts: 1 reduce/reduce 1450 ]]) 1451 AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]], 1452 [[sr-rr.y: conflicts: 1 shift/reduce 1453 ]]) 1454 1455 [for gram in sr-rr sr rr; do 1456 for sr_exp_i in '' 0 1 2; do 1457 for rr_exp_i in '' 0 1 2; do 1458 test -z "$sr_exp_i" && test -z "$rr_exp_i" && continue 1459 1460 # Build grammar file. 1461 sr_exp=0 1462 rr_exp=0 1463 file=$gram 1464 directives= 1465 if test -n "$sr_exp_i"; then 1466 sr_exp=$sr_exp_i 1467 file=$file-expect-$sr_exp 1468 directives="%expect $sr_exp" 1469 fi 1470 if test -n "$rr_exp_i"; then 1471 rr_exp=$rr_exp_i 1472 file=$file-expect-rr-$rr_exp 1473 directives="$directives %expect-rr $rr_exp" 1474 fi 1475 file=$file.y 1476 echo "$directives" > $file 1477 cat $gram.y >> $file 1478 1479 # Count actual conflicts. 1480 conflicts= 1481 sr_count=0 1482 rr_count=0 1483 if test $gram = sr || test $gram = sr-rr; then 1484 conflicts="1 shift/reduce" 1485 sr_count=1 1486 fi 1487 if test $gram = rr || test $gram = sr-rr; then 1488 if test -n "$conflicts"; then 1489 conflicts="$conflicts, " 1490 fi 1491 conflicts="${conflicts}1 reduce/reduce" 1492 rr_count=1 1493 fi 1494 1495 # Run tests. 1496 if test $sr_count -eq $sr_exp && test $rr_count -eq $rr_exp; then 1497 ]AT_BISON_CHECK([[-Wnone $file]])[ 1498 ]AT_BISON_CHECK([[-Werror $file]])[ 1499 else 1500 echo "$file: conflicts: $conflicts" > experr 1501 if test $sr_count -ne $sr_exp; then 1502 if test $sr_exp -ne 1; then s=s; else s= ; fi 1503 echo "$file: error: expected $sr_exp shift/reduce conflict$s" >> experr 1504 fi 1505 if test $rr_count -ne $rr_exp; then 1506 if test $rr_exp -ne 1; then s=s; else s= ; fi 1507 echo "$file: error: expected $rr_exp reduce/reduce conflict$s" >> experr 1508 fi 1509 ]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[ 1510 ]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[ 1511 fi 1512 done 1513 done 1514 done] 1515 1516 AT_CLEANUP 1517