|
|
1.1 ! root 1: /* Find and resolve or report look-ahead conflicts for bison, ! 2: Copyright (C) 1984, 1989 Free Software Foundation, Inc. ! 3: ! 4: This file is part of Bison, the GNU Compiler Compiler. ! 5: ! 6: Bison 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 2, or (at your option) ! 9: any later version. ! 10: ! 11: Bison 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 Bison; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: #ifdef _AIX ! 21: #pragma alloca ! 22: #endif ! 23: #include <stdio.h> ! 24: #include "system.h" ! 25: #include "machine.h" ! 26: #include "new.h" ! 27: #include "files.h" ! 28: #include "gram.h" ! 29: #include "state.h" ! 30: ! 31: ! 32: #ifdef __GNUC__ ! 33: #ifdef alloca ! 34: #undef alloca ! 35: #endif ! 36: #define alloca __builtin_alloca ! 37: #else ! 38: #ifdef HAVE_ALLOCA_H ! 39: #include <alloca.h> ! 40: #else ! 41: #ifndef _AIX ! 42: extern char *alloca (); ! 43: #endif ! 44: #endif ! 45: #endif ! 46: ! 47: extern char **tags; ! 48: extern int tokensetsize; ! 49: extern char *consistent; ! 50: extern short *accessing_symbol; ! 51: extern shifts **shift_table; ! 52: extern unsigned *LA; ! 53: extern short *LAruleno; ! 54: extern short *lookaheads; ! 55: extern int verboseflag; ! 56: ! 57: void set_conflicts(); ! 58: void resolve_sr_conflict(); ! 59: void flush_shift(); ! 60: void log_resolution(); ! 61: void total_conflicts(); ! 62: void count_sr_conflicts(); ! 63: void count_rr_conflicts(); ! 64: ! 65: char any_conflicts; ! 66: char *conflicts; ! 67: errs **err_table; ! 68: int expected_conflicts; ! 69: ! 70: ! 71: static unsigned *shiftset; ! 72: static unsigned *lookaheadset; ! 73: static int src_total; ! 74: static int rrc_total; ! 75: static int src_count; ! 76: static int rrc_count; ! 77: ! 78: ! 79: void ! 80: initialize_conflicts() ! 81: { ! 82: register int i; ! 83: /* register errs *sp; JF unused */ ! 84: ! 85: conflicts = NEW2(nstates, char); ! 86: shiftset = NEW2(tokensetsize, unsigned); ! 87: lookaheadset = NEW2(tokensetsize, unsigned); ! 88: ! 89: err_table = NEW2(nstates, errs *); ! 90: ! 91: any_conflicts = 0; ! 92: ! 93: for (i = 0; i < nstates; i++) ! 94: set_conflicts(i); ! 95: } ! 96: ! 97: ! 98: void ! 99: set_conflicts(state) ! 100: int state; ! 101: { ! 102: register int i; ! 103: register int k; ! 104: register shifts *shiftp; ! 105: register unsigned *fp2; ! 106: register unsigned *fp3; ! 107: register unsigned *fp4; ! 108: register unsigned *fp1; ! 109: register int symbol; ! 110: ! 111: if (consistent[state]) return; ! 112: ! 113: for (i = 0; i < tokensetsize; i++) ! 114: lookaheadset[i] = 0; ! 115: ! 116: shiftp = shift_table[state]; ! 117: if (shiftp) ! 118: { ! 119: k = shiftp->nshifts; ! 120: for (i = 0; i < k; i++) ! 121: { ! 122: symbol = accessing_symbol[shiftp->shifts[i]]; ! 123: if (ISVAR(symbol)) break; ! 124: SETBIT(lookaheadset, symbol); ! 125: } ! 126: } ! 127: ! 128: k = lookaheads[state + 1]; ! 129: fp4 = lookaheadset + tokensetsize; ! 130: ! 131: /* loop over all rules which require lookahead in this state */ ! 132: /* first check for shift-reduce conflict, and try to resolve using precedence */ ! 133: ! 134: for (i = lookaheads[state]; i < k; i++) ! 135: if (rprec[LAruleno[i]]) ! 136: { ! 137: fp1 = LA + i * tokensetsize; ! 138: fp2 = fp1; ! 139: fp3 = lookaheadset; ! 140: ! 141: while (fp3 < fp4) ! 142: { ! 143: if (*fp2++ & *fp3++) ! 144: { ! 145: resolve_sr_conflict(state, i); ! 146: break; ! 147: } ! 148: } ! 149: } ! 150: ! 151: /* loop over all rules which require lookahead in this state */ ! 152: /* Check for conflicts not resolved above. */ ! 153: ! 154: for (i = lookaheads[state]; i < k; i++) ! 155: { ! 156: fp1 = LA + i * tokensetsize; ! 157: fp2 = fp1; ! 158: fp3 = lookaheadset; ! 159: ! 160: while (fp3 < fp4) ! 161: { ! 162: if (*fp2++ & *fp3++) ! 163: { ! 164: conflicts[state] = 1; ! 165: any_conflicts = 1; ! 166: } ! 167: } ! 168: ! 169: fp2 = fp1; ! 170: fp3 = lookaheadset; ! 171: ! 172: while (fp3 < fp4) ! 173: *fp3++ |= *fp2++; ! 174: } ! 175: } ! 176: ! 177: ! 178: ! 179: /* Attempt to resolve shift-reduce conflict for one rule ! 180: by means of precedence declarations. ! 181: It has already been checked that the rule has a precedence. ! 182: A conflict is resolved by modifying the shift or reduce tables ! 183: so that there is no longer a conflict. */ ! 184: ! 185: void ! 186: resolve_sr_conflict(state, lookaheadnum) ! 187: int state; ! 188: int lookaheadnum; ! 189: { ! 190: register int i; ! 191: register int mask; ! 192: register unsigned *fp1; ! 193: register unsigned *fp2; ! 194: register int redprec; ! 195: /* Extra parens avoid errors on Ultrix 4.3. */ ! 196: errs *errp = (errs *) alloca ((sizeof(errs) + ntokens * sizeof(short))); ! 197: short *errtokens = errp->errs; ! 198: ! 199: /* find the rule to reduce by to get precedence of reduction */ ! 200: redprec = rprec[LAruleno[lookaheadnum]]; ! 201: ! 202: mask = 1; ! 203: fp1 = LA + lookaheadnum * tokensetsize; ! 204: fp2 = lookaheadset; ! 205: for (i = 0; i < ntokens; i++) ! 206: { ! 207: if ((mask & *fp2 & *fp1) && sprec[i]) ! 208: /* Shift-reduce conflict occurs for token number i ! 209: and it has a precedence. ! 210: The precedence of shifting is that of token i. */ ! 211: { ! 212: if (sprec[i] < redprec) ! 213: { ! 214: if (verboseflag) log_resolution(state, lookaheadnum, i, "reduce"); ! 215: *fp2 &= ~mask; /* flush the shift for this token */ ! 216: flush_shift(state, i); ! 217: } ! 218: else if (sprec[i] > redprec) ! 219: { ! 220: if (verboseflag) log_resolution(state, lookaheadnum, i, "shift"); ! 221: *fp1 &= ~mask; /* flush the reduce for this token */ ! 222: } ! 223: else ! 224: { ! 225: /* Matching precedence levels. ! 226: For left association, keep only the reduction. ! 227: For right association, keep only the shift. ! 228: For nonassociation, keep neither. */ ! 229: ! 230: switch (sassoc[i]) ! 231: { ! 232: ! 233: case RIGHT_ASSOC: ! 234: if (verboseflag) log_resolution(state, lookaheadnum, i, "shift"); ! 235: break; ! 236: ! 237: case LEFT_ASSOC: ! 238: if (verboseflag) log_resolution(state, lookaheadnum, i, "reduce"); ! 239: break; ! 240: ! 241: case NON_ASSOC: ! 242: if (verboseflag) log_resolution(state, lookaheadnum, i, "an error"); ! 243: break; ! 244: } ! 245: ! 246: if (sassoc[i] != RIGHT_ASSOC) ! 247: { ! 248: *fp2 &= ~mask; /* flush the shift for this token */ ! 249: flush_shift(state, i); ! 250: } ! 251: if (sassoc[i] != LEFT_ASSOC) ! 252: { ! 253: *fp1 &= ~mask; /* flush the reduce for this token */ ! 254: } ! 255: if (sassoc[i] == NON_ASSOC) ! 256: { ! 257: /* Record an explicit error for this token. */ ! 258: *errtokens++ = i; ! 259: } ! 260: } ! 261: } ! 262: ! 263: mask <<= 1; ! 264: if (mask == 0) ! 265: { ! 266: mask = 1; ! 267: fp2++; fp1++; ! 268: } ! 269: } ! 270: errp->nerrs = errtokens - errp->errs; ! 271: if (errp->nerrs) ! 272: { ! 273: /* Some tokens have been explicitly made errors. Allocate ! 274: a permanent errs structure for this state, to record them. */ ! 275: i = (char *) errtokens - (char *) errp; ! 276: err_table[state] = (errs *) xmalloc ((unsigned int)i); ! 277: bcopy (errp, err_table[state], i); ! 278: } ! 279: else ! 280: err_table[state] = 0; ! 281: } ! 282: ! 283: ! 284: ! 285: /* turn off the shift recorded for the specified token in the specified state. ! 286: Used when we resolve a shift-reduce conflict in favor of the reduction. */ ! 287: ! 288: void ! 289: flush_shift(state, token) ! 290: int state; ! 291: int token; ! 292: { ! 293: register shifts *shiftp; ! 294: register int k, i; ! 295: /* register unsigned symbol; JF unused */ ! 296: ! 297: shiftp = shift_table[state]; ! 298: ! 299: if (shiftp) ! 300: { ! 301: k = shiftp->nshifts; ! 302: for (i = 0; i < k; i++) ! 303: { ! 304: if (shiftp->shifts[i] && token == accessing_symbol[shiftp->shifts[i]]) ! 305: (shiftp->shifts[i]) = 0; ! 306: } ! 307: } ! 308: } ! 309: ! 310: ! 311: void ! 312: log_resolution(state, LAno, token, resolution) ! 313: int state, LAno, token; ! 314: char *resolution; ! 315: { ! 316: fprintf(foutput, ! 317: "Conflict in state %d between rule %d and token %s resolved as %s.\n", ! 318: state, LAruleno[LAno], tags[token], resolution); ! 319: } ! 320: ! 321: ! 322: void ! 323: conflict_log() ! 324: { ! 325: register int i; ! 326: ! 327: src_total = 0; ! 328: rrc_total = 0; ! 329: ! 330: for (i = 0; i < nstates; i++) ! 331: { ! 332: if (conflicts[i]) ! 333: { ! 334: count_sr_conflicts(i); ! 335: count_rr_conflicts(i); ! 336: src_total += src_count; ! 337: rrc_total += rrc_count; ! 338: } ! 339: } ! 340: ! 341: total_conflicts(); ! 342: } ! 343: ! 344: ! 345: void ! 346: verbose_conflict_log() ! 347: { ! 348: register int i; ! 349: ! 350: src_total = 0; ! 351: rrc_total = 0; ! 352: ! 353: for (i = 0; i < nstates; i++) ! 354: { ! 355: if (conflicts[i]) ! 356: { ! 357: count_sr_conflicts(i); ! 358: count_rr_conflicts(i); ! 359: src_total += src_count; ! 360: rrc_total += rrc_count; ! 361: ! 362: fprintf(foutput, "State %d contains", i); ! 363: ! 364: if (src_count == 1) ! 365: fprintf(foutput, " 1 shift/reduce conflict"); ! 366: else if (src_count > 1) ! 367: fprintf(foutput, " %d shift/reduce conflicts", src_count); ! 368: ! 369: if (src_count > 0 && rrc_count > 0) ! 370: fprintf(foutput, " and"); ! 371: ! 372: if (rrc_count == 1) ! 373: fprintf(foutput, " 1 reduce/reduce conflict"); ! 374: else if (rrc_count > 1) ! 375: fprintf(foutput, " %d reduce/reduce conflicts", rrc_count); ! 376: ! 377: putc('.', foutput); ! 378: putc('\n', foutput); ! 379: } ! 380: } ! 381: ! 382: total_conflicts(); ! 383: } ! 384: ! 385: ! 386: void ! 387: total_conflicts() ! 388: { ! 389: extern int fixed_outfiles; ! 390: ! 391: if (src_total == expected_conflicts && rrc_total == 0) ! 392: return; ! 393: ! 394: if (fixed_outfiles) ! 395: { ! 396: /* If invoked under the name `yacc', use the output format ! 397: specified by POSIX. */ ! 398: fprintf(stderr, "conflicts: "); ! 399: if (src_total > 0) ! 400: fprintf(stderr, " %d shift/reduce", src_total); ! 401: if (src_total > 0 && rrc_total > 0) ! 402: fprintf(stderr, ","); ! 403: if (rrc_total > 0) ! 404: fprintf(stderr, " %d reduce/reduce", rrc_total); ! 405: putc('\n', stderr); ! 406: } ! 407: else ! 408: { ! 409: fprintf(stderr, "%s contains", infile); ! 410: ! 411: if (src_total == 1) ! 412: fprintf(stderr, " 1 shift/reduce conflict"); ! 413: else if (src_total > 1) ! 414: fprintf(stderr, " %d shift/reduce conflicts", src_total); ! 415: ! 416: if (src_total > 0 && rrc_total > 0) ! 417: fprintf(stderr, " and"); ! 418: ! 419: if (rrc_total == 1) ! 420: fprintf(stderr, " 1 reduce/reduce conflict"); ! 421: else if (rrc_total > 1) ! 422: fprintf(stderr, " %d reduce/reduce conflicts", rrc_total); ! 423: ! 424: putc('.', stderr); ! 425: putc('\n', stderr); ! 426: } ! 427: } ! 428: ! 429: ! 430: void ! 431: count_sr_conflicts(state) ! 432: int state; ! 433: { ! 434: register int i; ! 435: register int k; ! 436: register int mask; ! 437: register shifts *shiftp; ! 438: register unsigned *fp1; ! 439: register unsigned *fp2; ! 440: register unsigned *fp3; ! 441: register int symbol; ! 442: ! 443: src_count = 0; ! 444: ! 445: shiftp = shift_table[state]; ! 446: if (!shiftp) return; ! 447: ! 448: for (i = 0; i < tokensetsize; i++) ! 449: { ! 450: shiftset[i] = 0; ! 451: lookaheadset[i] = 0; ! 452: } ! 453: ! 454: k = shiftp->nshifts; ! 455: for (i = 0; i < k; i++) ! 456: { ! 457: if (! shiftp->shifts[i]) continue; ! 458: symbol = accessing_symbol[shiftp->shifts[i]]; ! 459: if (ISVAR(symbol)) break; ! 460: SETBIT(shiftset, symbol); ! 461: } ! 462: ! 463: k = lookaheads[state + 1]; ! 464: fp3 = lookaheadset + tokensetsize; ! 465: ! 466: for (i = lookaheads[state]; i < k; i++) ! 467: { ! 468: fp1 = LA + i * tokensetsize; ! 469: fp2 = lookaheadset; ! 470: ! 471: while (fp2 < fp3) ! 472: *fp2++ |= *fp1++; ! 473: } ! 474: ! 475: fp1 = shiftset; ! 476: fp2 = lookaheadset; ! 477: ! 478: while (fp2 < fp3) ! 479: *fp2++ &= *fp1++; ! 480: ! 481: mask = 1; ! 482: fp2 = lookaheadset; ! 483: for (i = 0; i < ntokens; i++) ! 484: { ! 485: if (mask & *fp2) ! 486: src_count++; ! 487: ! 488: mask <<= 1; ! 489: if (mask == 0) ! 490: { ! 491: mask = 1; ! 492: fp2++; ! 493: } ! 494: } ! 495: } ! 496: ! 497: ! 498: void ! 499: count_rr_conflicts(state) ! 500: int state; ! 501: { ! 502: register int i; ! 503: register int j; ! 504: register int count; ! 505: register unsigned mask; ! 506: register unsigned *baseword; ! 507: register unsigned *wordp; ! 508: register int m; ! 509: register int n; ! 510: ! 511: rrc_count = 0; ! 512: ! 513: m = lookaheads[state]; ! 514: n = lookaheads[state + 1]; ! 515: ! 516: if (n - m < 2) return; ! 517: ! 518: mask = 1; ! 519: baseword = LA + m * tokensetsize; ! 520: for (i = 0; i < ntokens; i++) ! 521: { ! 522: wordp = baseword; ! 523: ! 524: count = 0; ! 525: for (j = m; j < n; j++) ! 526: { ! 527: if (mask & *wordp) ! 528: count++; ! 529: ! 530: wordp += tokensetsize; ! 531: } ! 532: ! 533: if (count >= 2) rrc_count++; ! 534: ! 535: mask <<= 1; ! 536: if (mask == 0) ! 537: { ! 538: mask = 1; ! 539: baseword++; ! 540: } ! 541: } ! 542: } ! 543: ! 544: ! 545: void ! 546: print_reductions(state) ! 547: int state; ! 548: { ! 549: register int i; ! 550: register int j; ! 551: register int k; ! 552: register unsigned *fp1; ! 553: register unsigned *fp2; ! 554: register unsigned *fp3; ! 555: register unsigned *fp4; ! 556: register int rule; ! 557: register int symbol; ! 558: register unsigned mask; ! 559: register int m; ! 560: register int n; ! 561: register int default_LA; ! 562: register int default_rule; ! 563: register int cmax; ! 564: register int count; ! 565: register shifts *shiftp; ! 566: register errs *errp; ! 567: int nodefault = 0; ! 568: ! 569: for (i = 0; i < tokensetsize; i++) ! 570: shiftset[i] = 0; ! 571: ! 572: shiftp = shift_table[state]; ! 573: if (shiftp) ! 574: { ! 575: k = shiftp->nshifts; ! 576: for (i = 0; i < k; i++) ! 577: { ! 578: if (! shiftp->shifts[i]) continue; ! 579: symbol = accessing_symbol[shiftp->shifts[i]]; ! 580: if (ISVAR(symbol)) break; ! 581: /* if this state has a shift for the error token, ! 582: don't use a default rule. */ ! 583: if (symbol == error_token_number) nodefault = 1; ! 584: SETBIT(shiftset, symbol); ! 585: } ! 586: } ! 587: ! 588: errp = err_table[state]; ! 589: if (errp) ! 590: { ! 591: k = errp->nerrs; ! 592: for (i = 0; i < k; i++) ! 593: { ! 594: if (! errp->errs[i]) continue; ! 595: symbol = errp->errs[i]; ! 596: SETBIT(shiftset, symbol); ! 597: } ! 598: } ! 599: ! 600: m = lookaheads[state]; ! 601: n = lookaheads[state + 1]; ! 602: ! 603: if (n - m == 1 && ! nodefault) ! 604: { ! 605: default_rule = LAruleno[m]; ! 606: ! 607: fp1 = LA + m * tokensetsize; ! 608: fp2 = shiftset; ! 609: fp3 = lookaheadset; ! 610: fp4 = lookaheadset + tokensetsize; ! 611: ! 612: while (fp3 < fp4) ! 613: *fp3++ = *fp1++ & *fp2++; ! 614: ! 615: mask = 1; ! 616: fp3 = lookaheadset; ! 617: ! 618: for (i = 0; i < ntokens; i++) ! 619: { ! 620: if (mask & *fp3) ! 621: fprintf(foutput, " %-4s\t[reduce using rule %d (%s)]\n", ! 622: tags[i], default_rule, tags[rlhs[default_rule]]); ! 623: ! 624: mask <<= 1; ! 625: if (mask == 0) ! 626: { ! 627: mask = 1; ! 628: fp3++; ! 629: } ! 630: } ! 631: ! 632: fprintf(foutput, " $default\treduce using rule %d (%s)\n\n", ! 633: default_rule, tags[rlhs[default_rule]]); ! 634: } ! 635: else if (n - m >= 1) ! 636: { ! 637: cmax = 0; ! 638: default_LA = -1; ! 639: fp4 = lookaheadset + tokensetsize; ! 640: ! 641: if (! nodefault) ! 642: for (i = m; i < n; i++) ! 643: { ! 644: fp1 = LA + i * tokensetsize; ! 645: fp2 = shiftset; ! 646: fp3 = lookaheadset; ! 647: ! 648: while (fp3 < fp4) ! 649: *fp3++ = *fp1++ & ( ~ (*fp2++)); ! 650: ! 651: count = 0; ! 652: mask = 1; ! 653: fp3 = lookaheadset; ! 654: for (j = 0; j < ntokens; j++) ! 655: { ! 656: if (mask & *fp3) ! 657: count++; ! 658: ! 659: mask <<= 1; ! 660: if (mask == 0) ! 661: { ! 662: mask = 1; ! 663: fp3++; ! 664: } ! 665: } ! 666: ! 667: if (count > cmax) ! 668: { ! 669: cmax = count; ! 670: default_LA = i; ! 671: default_rule = LAruleno[i]; ! 672: } ! 673: ! 674: fp2 = shiftset; ! 675: fp3 = lookaheadset; ! 676: ! 677: while (fp3 < fp4) ! 678: *fp2++ |= *fp3++; ! 679: } ! 680: ! 681: for (i = 0; i < tokensetsize; i++) ! 682: shiftset[i] = 0; ! 683: ! 684: if (shiftp) ! 685: { ! 686: k = shiftp->nshifts; ! 687: for (i = 0; i < k; i++) ! 688: { ! 689: if (! shiftp->shifts[i]) continue; ! 690: symbol = accessing_symbol[shiftp->shifts[i]]; ! 691: if (ISVAR(symbol)) break; ! 692: SETBIT(shiftset, symbol); ! 693: } ! 694: } ! 695: ! 696: mask = 1; ! 697: fp1 = LA + m * tokensetsize; ! 698: fp2 = shiftset; ! 699: for (i = 0; i < ntokens; i++) ! 700: { ! 701: int defaulted = 0; ! 702: ! 703: if (mask & *fp2) ! 704: count = 1; ! 705: else ! 706: count = 0; ! 707: ! 708: fp3 = fp1; ! 709: for (j = m; j < n; j++) ! 710: { ! 711: if (mask & *fp3) ! 712: { ! 713: if (count == 0) ! 714: { ! 715: if (j != default_LA) ! 716: { ! 717: rule = LAruleno[j]; ! 718: fprintf(foutput, " %-4s\treduce using rule %d (%s)\n", ! 719: tags[i], rule, tags[rlhs[rule]]); ! 720: } ! 721: else defaulted = 1; ! 722: ! 723: count++; ! 724: } ! 725: else ! 726: { ! 727: if (defaulted) ! 728: { ! 729: rule = LAruleno[default_LA]; ! 730: fprintf(foutput, " %-4s\treduce using rule %d (%s)\n", ! 731: tags[i], rule, tags[rlhs[rule]]); ! 732: defaulted = 0; ! 733: } ! 734: rule = LAruleno[j]; ! 735: fprintf(foutput, " %-4s\t[reduce using rule %d (%s)]\n", ! 736: tags[i], rule, tags[rlhs[rule]]); ! 737: } ! 738: } ! 739: ! 740: fp3 += tokensetsize; ! 741: } ! 742: ! 743: mask <<= 1; ! 744: if (mask == 0) ! 745: { ! 746: mask = 1; ! 747: /* This used to be fp1, but I think fp2 is right ! 748: because fp2 is where the words are fetched to test with mask ! 749: in this loop. */ ! 750: fp2++; ! 751: } ! 752: } ! 753: ! 754: if (default_LA >= 0) ! 755: { ! 756: fprintf(foutput, " $default\treduce using rule %d (%s)\n", ! 757: default_rule, tags[rlhs[default_rule]]); ! 758: } ! 759: ! 760: putc('\n', foutput); ! 761: } ! 762: } ! 763: ! 764: ! 765: void ! 766: finalize_conflicts() ! 767: { ! 768: FREE(conflicts); ! 769: FREE(shiftset); ! 770: FREE(lookaheadset); ! 771: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.