|
|
1.1 ! root 1: static char *sccsid = "@(#)yyrecover.c 1.1 (Berkeley) 3/2/81"; ! 2: /* Copyright (c) 1979 Regents of the University of California */ ! 3: # ! 4: /* ! 5: * pi - Pascal interpreter code translator ! 6: * ! 7: * Charles Haley, Bill Joy UCB ! 8: * Version 1.1 February 1978 ! 9: * ! 10: * ! 11: * pxp - Pascal execution profiler ! 12: * ! 13: * Bill Joy UCB ! 14: * Version 1.1 February 1978 ! 15: */ ! 16: ! 17: #include "0.h" ! 18: #include "yy.h" ! 19: ! 20: /* ! 21: * Very simplified version of Graham-Rhodes error recovery ! 22: * method for LALR parsers. Backward move is embodied in ! 23: * default reductions of the yacc parser until an error condition ! 24: * is reached. Forward move is over a small number of input tokens ! 25: * and cannot "condense". The basic corrections are: ! 26: * ! 27: * 1) Delete the input token. ! 28: * ! 29: * 2) Replace the current input with a legal input. ! 30: * ! 31: * 3) Insert a legal token. ! 32: * ! 33: * All corrections are weighted, considered only if they allow ! 34: * at least two shifts, and the cost of a correction increases if ! 35: * it allows shifting over only a part of the lookahead. ! 36: * ! 37: * Another error situation is that which occurs when an identifier "fails" ! 38: * a reduction because it is not the required "class". ! 39: * In this case, we also consider replacing this identifier, which has ! 40: * already been shifted over, with an identifier of the correct class. ! 41: * ! 42: * Another correction performed here is unique symbol insertion. ! 43: * If the current state admits only one input, and no other alternative ! 44: * correction presents itself, then that symbol will be inserted. ! 45: * There is a danger in this of looping, and it is handled ! 46: * by counting true shifts over input (see below). ! 47: * ! 48: * ! 49: * A final class of corrections, considered only when the error ! 50: * occurred immediately after a shift over a terminal, involves ! 51: * the three basic corrections above, but with the point of error ! 52: * considered to be before this terminal was shifted over, effectively ! 53: * "unreading" this terminal. This is a feeble attempt at elimination ! 54: * of the left-right bias and because "if" has a low weight and some ! 55: * statements are quite simple i.e. ! 56: * ! 57: * cse ch of ... ! 58: * ! 59: * we can get a small number of errors. The major deficiency of ! 60: * this is that we back up only one token, and that the forward ! 61: * move is over a small number of tokens, often not enough to really ! 62: * tell what the input should be, e.g. in ! 63: * ! 64: * a[i] > a[i - 1] ... ! 65: * ! 66: * In such cases a bad identifier (misspelled keyword) or omitted ! 67: * keyword will be change or inserted as "if" as it has the lowest cost. ! 68: * This is not terribly bad, as "if"s are most common. ! 69: * This also allows the correction of other errors. ! 70: * ! 71: * This recovery depends on the default reductions which delay ! 72: * noticing the error until the parse reaches a state where the ! 73: * relevant "alternatives" are visible. Note that it does not ! 74: * consider tokens which will cause reductions before being ! 75: * shifted over. This requires the grammar to be written in a ! 76: * certain way for the recovery to work correctly. ! 77: * In some sense, also, the recovery suffers because we have ! 78: * LALR(1) tables rather than LR(1) tables, e.g. in ! 79: * ! 80: * if rec.field < rec2,field2 then ! 81: */ ! 82: ! 83: /* ! 84: * Definitions of possible corrective actions ! 85: */ ! 86: #define CPANIC 0 ! 87: #define CDELETE 1 ! 88: #define CREPLACE 2 ! 89: #define CINSERT 3 ! 90: #define CUNIQUE 4 ! 91: #define CCHIDENT 5 ! 92: ! 93: /* ! 94: * Multiplicative cost factors for corrective actions. ! 95: * ! 96: * When an error occurs we take YCSIZ - 1 look-ahead tokens. ! 97: * If a correction being considered will shift over only part of ! 98: * that look-ahead, it is not completely discarded, but rather ! 99: * "weighted", its cost being multiplied by a weighting factor. ! 100: * For a correction to be considered its weighted cost must be less ! 101: * than CLIMIT. ! 102: * ! 103: * Non-weighted costs are considered: ! 104: * ! 105: * LOW <= 3 ! 106: * MEDIUM 4,5 ! 107: * HIGH >= 6 ! 108: * ! 109: * CURRENT WEIGHTING STRATEGY: Aug 20, 1977 ! 110: * ! 111: * For all kinds of corrections we demand shifts over two symbols. ! 112: * Corrections have high weight even after two symbol ! 113: * shifts because the costs for deleting and inserting symbols are actually ! 114: * quite low; we do not want to change weighty symbols ! 115: * on inconclusive evidence. ! 116: * ! 117: * The weights are the same after the third look ahead. ! 118: * This prevents later, unrelated errors from causing "funny" ! 119: * biases of the weights toward one type of correction. ! 120: * ! 121: * Current look ahead is 5 symbols. ! 122: */ ! 123: ! 124: /*** CLIMIT is defined in yy.h for yycosts ***/ ! 125: #define CPRLIMIT 50 ! 126: #define CCHIDCOST 3 ! 127: ! 128: char insmult[8] = {INFINITY, INFINITY, INFINITY, 15, 8, 6, 3, 1}; ! 129: char repmult[7] = {INFINITY, INFINITY, INFINITY, 8, 6, 3, 1}; ! 130: char delmult[6] = {INFINITY, INFINITY, INFINITY, 6, 3, 1}; ! 131: ! 132: #define NOCHAR -1 ! 133: ! 134: #define Eprintf if (errtrace) printf ! 135: #define Tprintf if (testtrace) printf ! 136: ! 137: /* ! 138: * Action arrays of the parser needed here ! 139: */ ! 140: int yyact[], yypact[], *yypv; ! 141: ! 142: /* ! 143: * Yytips is the tip of the stack when using ! 144: * the function loccor to check for local ! 145: * syntactic correctness. As we don't want ! 146: * to copy the whole parser stack, but want ! 147: * to simulate parser moves, we "split" ! 148: * the parser stack and keep the tip here. ! 149: */ ! 150: #define YYTIPSIZ 16 ! 151: int yytips[YYTIPSIZ], yytipct; ! 152: int yytipv[YYTIPSIZ]; ! 153: ! 154: /* ! 155: * The array YC saves the lookahead tokens for the ! 156: * forward moves. ! 157: * Yccnt is the number of tokens in the YC array. ! 158: */ ! 159: #define YCSIZ 6 ! 160: ! 161: int yCcnt; ! 162: struct yytok YC0[YCSIZ + 1]; ! 163: struct yytok *YC; ! 164: ! 165: /* ! 166: * YCps gives the top of stack at ! 167: * the point of error. ! 168: */ ! 169: ! 170: char yyunique = 1; ! 171: ! 172: STATIC unsigned yyTshifts; ! 173: ! 174: /* ! 175: * Cact is the corrective action we have decided on ! 176: * so far, ccost its cost, and cchar the associated token. ! 177: * Cflag tells if the correction is over the previous input token. ! 178: */ ! 179: int cact, ccost, cchar, cflag; ! 180: ! 181: /* ! 182: * ACtok holds the token under ! 183: * consideration when examining ! 184: * the lookaheads in a state. ! 185: */ ! 186: struct yytok ACtok; ! 187: ! 188: #define acchar ACtok.Yychar ! 189: #define aclval ACtok.Yylval ! 190: ! 191: /* ! 192: * Make a correction to the current stack which has ! 193: * top of stack pointer Ps. ! 194: */ ! 195: yyrecover(Ps0, idfail) ! 196: int *Ps0, idfail; ! 197: { ! 198: register int c, i; ! 199: int yyrwant, yyrhave; ! 200: ! 201: #ifdef PI ! 202: Recovery = 1; ! 203: #endif ! 204: ! 205: YC = &YC0[1]; ! 206: #ifdef DEBUG ! 207: if (errtrace) { ! 208: setpfx('p'); ! 209: yerror("Point of error"); ! 210: printf("States %d %d ...", Ps0[0], Ps0[-1]); ! 211: if (idfail) ! 212: printf(" [Idfail]"); ! 213: putchar('\n'); ! 214: printf("Input %s%s", tokname(&Y , 0) ! 215: , tokname(&Y , 1)); ! 216: } ! 217: ! 218: #endif ! 219: /* ! 220: * We first save the current input token ! 221: * and its associated semantic information. ! 222: */ ! 223: if (yychar < 0) ! 224: yychar = yylex(); ! 225: copy(&YC[0], &Y, sizeof Y); ! 226: ! 227: /* ! 228: * Set the default action and cost ! 229: */ ! 230: cact = CPANIC, ccost = CLIMIT, cflag = 0; ! 231: ! 232: /* ! 233: * Peek ahead ! 234: */ ! 235: for (yCcnt = 1; yCcnt < YCSIZ; yCcnt++) { ! 236: yychar = yylex(); ! 237: copy(&YC[yCcnt], &Y, sizeof YC[0]); ! 238: #ifdef DEBUG ! 239: Eprintf(" | %s%s", tokname(&YC[yCcnt] , 0 ) ! 240: , tokname(&YC[yCcnt] , 1 )); ! 241: #endif ! 242: } ! 243: #ifdef DEBUG ! 244: Eprintf("\n"); ! 245: #endif ! 246: ! 247: /* ! 248: * If we are here because a reduction failed, try ! 249: * correcting that. ! 250: */ ! 251: if (idfail) { ! 252: /* ! 253: * Save the particulars about ! 254: * the kind of identifier we want/have. ! 255: */ ! 256: yyrwant = yyidwant; ! 257: yyrhave = yyidhave; ! 258: #ifdef DEBUG ! 259: Tprintf(" Try Replace %s identifier with %s identifier cost=%d\n", ! 260: classes[yyidhave], classes[yyidwant], CCHIDCOST); ! 261: #endif ! 262: ! 263: /* ! 264: * Save the semantics of the ID on the ! 265: * stack, and null them out to free ! 266: * up the reduction in question. ! 267: */ ! 268: i = yypv[0]; ! 269: yypv[0] = nullsem(YID); ! 270: c = correct(NOCHAR, 0, CCHIDCOST, &repmult[2], Ps0, yypv); ! 271: yypv[0] = i; ! 272: #ifdef DEBUG ! 273: if (c < CPRLIMIT || fulltrace) ! 274: Eprintf("Cost %2d Replace %s identifier with %s identifier\n", c, classes[yyrhave], classes[yyrwant]); ! 275: #endif ! 276: if (c < ccost) ! 277: cact = CCHIDENT, ccost = c, cchar = YID; ! 278: } ! 279: ! 280: /* ! 281: * First try correcting the state we are in ! 282: */ ! 283: trystate(Ps0, yypv, 0, &insmult[1], &delmult[1], &repmult[1]); ! 284: ! 285: /* ! 286: * Now, if we just shifted over a terminal, try ! 287: * correcting it. ! 288: */ ! 289: if (OY.Yychar != -1 && OY.Yylval != nullsem(OY.Yychar)) { ! 290: YC--; ! 291: copy(&YC[0], &OY, sizeof YC[0]); ! 292: trystate(Ps0 - 1, yypv - 1, 1, insmult, delmult, repmult); ! 293: if (cflag == 0) ! 294: YC++; ! 295: else { ! 296: yypv--; ! 297: #ifdef PXP ! 298: yypw--; ! 299: #endif ! 300: Ps0--; ! 301: yCcnt++; ! 302: } ! 303: } ! 304: ! 305: /* ! 306: * Restoring the first look ahead into ! 307: * the scanner token allows the error message ! 308: * routine to print the error message with the text ! 309: * of the correct line. ! 310: */ ! 311: copy(&Y, &YC[0], sizeof Y); ! 312: ! 313: /* ! 314: * Unique symbol insertion. ! 315: * ! 316: * If there was no reasonable correction found, ! 317: * but only one input to the parser is acceptable ! 318: * we report that, and try it. ! 319: * ! 320: * Special precautions here to prevent looping. ! 321: * The number of true inputs shifted over at the point ! 322: * of the last unique insertion is recorded in the ! 323: * variable yyTshifts. If this is not less than ! 324: * the current number in yytshifts, we do not insert. ! 325: * Thus, after one unique insertion, no more unique ! 326: * insertions will be made until an input is shifted ! 327: * over. This guarantees termination. ! 328: */ ! 329: if (cact == CPANIC && !idfail) { ! 330: register int *ap; ! 331: ! 332: ap = &yyact[yypact[*Ps0 + 1]]; ! 333: if (*ap == -ERROR) ! 334: ap += 2; ! 335: if (ap[0] <= 0 && ap[2] > 0) { ! 336: cchar = -ap[0]; ! 337: if (cchar == YEOF) ! 338: yyexeof(); ! 339: if (cchar != ERROR && yyTshifts < yytshifts) { ! 340: cact = CUNIQUE; ! 341: #ifdef DEBUG ! 342: Eprintf("Unique symbol %s%s\n", charname(cchar)); ! 343: #endif ! 344: /* ! 345: * Note that the inserted symbol ! 346: * will not be counted as a true input ! 347: * (i.e. the "yytshifts--" below) ! 348: * so that a true shift will be needed ! 349: * to make yytshifts > yyTshifts. ! 350: */ ! 351: yyTshifts = yytshifts; ! 352: } ! 353: } ! 354: } ! 355: ! 356: /* ! 357: * Set up to perform the correction. ! 358: * Build a token appropriate for replacement ! 359: * or insertion in the yytok structure ACchar ! 360: * having the attributes of the input at the ! 361: * point of error. ! 362: */ ! 363: copy(&ACtok, &YC[0], sizeof ACtok); ! 364: acchar = cchar; ! 365: aclval = nullsem(acchar); ! 366: if (aclval != NIL) ! 367: recovered(); ! 368: switch (cact) { ! 369: /* ! 370: * Panic, just restore the ! 371: * lookahead and return. ! 372: */ ! 373: case CPANIC: ! 374: setpfx('E'); ! 375: if (idfail) { ! 376: copy(&Y, &OY, sizeof Y); ! 377: if (yyrhave == NIL) { ! 378: #ifdef PI ! 379: if (yybaduse(yypv[0], yyeline, ISUNDEF) == NIL) ! 380: #endif ! 381: yerror("Undefined identifier"); ! 382: } else { ! 383: yerror("Improper %s identifier", classes[yyrhave]); ! 384: #ifdef PI ! 385: yybaduse(yypv[0], yyeline, NIL); ! 386: #endif ! 387: } ! 388: /* ! 389: * Suppress message from panic routine ! 390: */ ! 391: yyshifts = 1; ! 392: } ! 393: i = 0; ! 394: /* Note that on one path we dont touch yyshifts ! */ ! 395: break; ! 396: /* ! 397: * Delete the input. ! 398: * Mark this as a shift over true input. ! 399: * Restore the lookahead starting at ! 400: * the second token. ! 401: */ ! 402: case CDELETE: ! 403: if (ccost != 0) ! 404: yerror("Deleted %s%s", tokname(&YC[0] , 0 ) ! 405: , tokname(&YC[0] , 1 )); ! 406: yytshifts++; ! 407: i = 1; ! 408: yyshifts = 0; ! 409: break; ! 410: /* ! 411: * Replace the input with a new token. ! 412: */ ! 413: case CREPLACE: ! 414: if (acchar == YEOF) ! 415: yyexeof(); ! 416: if (acchar == YEND) ! 417: aclval = NIL; ! 418: yerror("Replaced %s%s with a %s%s", ! 419: tokname(&YC[0] , 0 ), ! 420: tokname(&YC[0] , 1 ), ! 421: tokname(&ACtok , 0 ), ! 422: tokname(&ACtok , 1 )); ! 423: copy(&YC[0], &ACtok, sizeof YC[0]); ! 424: i = 0; ! 425: yyshifts = 0; ! 426: break; ! 427: /* ! 428: * Insert a token. ! 429: * Don't count this token as a true input shift. ! 430: * For inserted "end"s pas.y is responsible ! 431: * for the error message later so suppress it. ! 432: * Restore all the lookahead. ! 433: */ ! 434: case CINSERT: ! 435: if (acchar == YEOF) ! 436: yyexeof(); ! 437: if (acchar != YEND) ! 438: yerror("Inserted %s%s", ! 439: tokname(&ACtok , 0 ), ! 440: tokname(&ACtok , 1 )); ! 441: yytshifts--; ! 442: i = 0; ! 443: yyshifts = 0; ! 444: break; ! 445: /* ! 446: * Make a unique symbol correction. ! 447: * Like an insertion but a different message. ! 448: */ ! 449: case CUNIQUE: ! 450: setpfx('E'); ! 451: yerror("Expected %s%s", ! 452: tokname(&ACtok , 0 ), ! 453: tokname(&ACtok , 1 )); ! 454: yytshifts--; ! 455: i = 0; ! 456: if (ccost == 0 || yyunique) ! 457: yyshifts = 0; ! 458: else ! 459: yyshifts = -1; ! 460: break; ! 461: /* ! 462: * Change an identifier's type ! 463: * to make it work. ! 464: */ ! 465: case CCHIDENT: ! 466: copy(&Y, &OY, sizeof Y); ! 467: #ifdef PI ! 468: i = 1 << yyrwant; ! 469: #endif ! 470: if (yyrhave == NIL) { ! 471: yerror("Undefined %s", classes[yyrwant]); ! 472: #ifdef PI ! 473: i |= ISUNDEF; ! 474: #endif ! 475: } else ! 476: yerror("Replaced %s id with a %s id", classes[yyrhave], classes[yyrwant]); ! 477: #ifdef PI ! 478: yybaduse(yypv[0], yyeline, i); ! 479: #endif ! 480: yypv[0] = nullsem(YID); ! 481: i = 0; ! 482: yyshifts = 0; ! 483: break; ! 484: } ! 485: ! 486: /* ! 487: * Restore the desired portion of the lookahead, ! 488: * and possibly the inserted or unique inserted token. ! 489: */ ! 490: for (yCcnt--; yCcnt >= i; yCcnt--) ! 491: unyylex(&YC[yCcnt]); ! 492: if (cact == CINSERT || cact == CUNIQUE) ! 493: unyylex(&ACtok); ! 494: ! 495: /* ! 496: * Put the scanner back in sync. ! 497: */ ! 498: yychar = yylex(); ! 499: ! 500: /* ! 501: * We succeeded if we didn't "panic". ! 502: */ ! 503: Recovery = 0; ! 504: Ps = Ps0; ! 505: return (cact != CPANIC); ! 506: } ! 507: ! 508: yyexeof() ! 509: { ! 510: ! 511: yerror("End-of-file expected - QUIT"); ! 512: pexit(ERRS); ! 513: } ! 514: ! 515: yyunexeof() ! 516: { ! 517: ! 518: yerror("Unexpected end-of-file - QUIT"); ! 519: pexit(ERRS); ! 520: } ! 521: ! 522: /* ! 523: * Try corrections with the state at Ps0. ! 524: * Flag is 0 if this is the top of stack state, ! 525: * 1 if it is the state below. ! 526: */ ! 527: trystate(Ps0, Pv0, flag, insmult, delmult, repmult) ! 528: int *Ps0, *Pv0, flag; ! 529: char *insmult, *delmult, *repmult; ! 530: { ! 531: /* ! 532: * C is a working cost, ap a pointer into the action ! 533: * table for looking at feasible alternatives. ! 534: */ ! 535: register int c, *ap; ! 536: int i, *actions; ! 537: ! 538: #ifdef DEBUG ! 539: Eprintf("Trying state %d\n", *Ps0); ! 540: #endif ! 541: /* ! 542: * Try deletion. ! 543: * Correct returns a cost. ! 544: */ ! 545: #ifdef DEBUG ! 546: Tprintf(" Try Delete %s%s cost=%d\n", ! 547: tokname(&YC[0] , 0 ), ! 548: tokname(&YC[0] , 1 ), ! 549: delcost(YC[0].Yychar)); ! 550: #endif ! 551: c = delcost(YC[0].Yychar); ! 552: #ifndef DEBUG ! 553: if (c < ccost) { ! 554: #endif ! 555: c = correct(NOCHAR, 1, c, delmult, Ps0, Pv0); ! 556: #ifdef DEBUG ! 557: if (c < CPRLIMIT || fulltrace) ! 558: Eprintf("Cost %2d Delete %s%s\n", c, ! 559: tokname(&YC[0] , 0 ), ! 560: tokname(&YC[0] , 1 )); ! 561: #endif ! 562: if (c < ccost) ! 563: cact = CDELETE, ccost = c, cflag = flag; ! 564: #ifndef DEBUG ! 565: } ! 566: #endif ! 567: ! 568: /* ! 569: * Look at the inputs to this state ! 570: * which will cause parse action shift. ! 571: */ ! 572: aclval = NIL; ! 573: ap = &yyact[yypact[*Ps0 + 1]]; ! 574: ! 575: /* ! 576: * Skip action on error to ! 577: * detect true unique inputs. ! 578: * Error action is always first. ! 579: */ ! 580: if (*ap == -ERROR) ! 581: ap+= 2; ! 582: ! 583: /* ! 584: * Loop through the test actions ! 585: * for this state. ! 586: */ ! 587: for (actions = ap; *ap <= 0; ap += 2) { ! 588: /* ! 589: * Extract the token of this action ! 590: */ ! 591: acchar = -*ap; ! 592: ! 593: /* ! 594: * Try insertion ! 595: */ ! 596: #ifdef DEBUG ! 597: Tprintf(" Try Insert %s%s cost=%d\n", charname(acchar), inscost(acchar)); ! 598: #endif ! 599: c = inscost(acchar, YC[0].Yychar); ! 600: #ifndef DEBUG ! 601: if (c < ccost) { ! 602: #endif ! 603: if (c == 0) { ! 604: c = correct(acchar, 0, 1, insmult + 1, Ps0, Pv0); ! 605: #ifdef DEBUG ! 606: Eprintf("Cost %2d Freebie %s%s\n", c, charname(acchar)); ! 607: #endif ! 608: if (c < ccost) ! 609: cact = CUNIQUE, ccost = 0, cchar = acchar, cflag = flag; ! 610: } else { ! 611: c = correct(acchar, 0, c, insmult, Ps0, Pv0); ! 612: #ifdef DEBUG ! 613: if (c < CPRLIMIT || fulltrace) ! 614: Eprintf("Cost %2d Insert %s%s\n", c, charname(acchar)); ! 615: #endif ! 616: if (c < ccost) ! 617: cact = CINSERT, ccost = c, cchar = acchar, cflag = flag; ! 618: } ! 619: #ifndef DEBUG ! 620: } ! 621: #endif ! 622: ! 623: /* ! 624: * Try replacement ! 625: */ ! 626: #ifdef DEBUG ! 627: Tprintf`* Try Replace %s%s with %s%s cost=%d\n", ! 628: tokname(&YC[0] , 0 ), ! 629: tokname(&YC[0] , 1 ), ! 630: charname(acchar , 0 ), ! 631: charname(acchar , 1 ), ! 632: repcost(YC[0].Yychar, acchar)); ! 633: #endif ! 634: c = repcost(YC[0].Yychar, acchar); ! 635: #ifndef DEBUG ! 636: if (c < ccost) { ! 637: #endif ! 638: c = correct(acchar, 1, repcost(YC[0].Yychar, acchar), repmult, Ps0, Pv0); ! 639: #ifdef DEBUG ! 640: if (c < CPRLIMIT || fulltrace) ! 641: Eprintf("Cost %2d Replace %s%s with %s%s\n", ! 642: c, ! 643: tokname(&YC[0] , 0 ), ! 644: tokname(&YC[0] , 1 ), ! 645: tokname(&ACtok , 0 ), ! 646: tokname(&ACtok , 1 )); ! 647: #endif ! 648: if (c < ccost) ! 649: cact = CREPLACE, ccost = c, cchar = acchar, cflag = flag; ! 650: #ifndef DEBUG ! 651: } ! 652: #endif ! 653: } ! 654: } ! 655: ! 656: int *yCpv; ! 657: char yyredfail; ! 658: ! 659: /* ! 660: * The ntok structure is used to build a ! 661: * scanner structure for tokens inserted ! 662: * from the argument "fchar" to "correct" below. ! 663: */ ! 664: static struct yytok ntok; ! 665: ! 666: /* ! 667: * Compute the cost of a correction ! 668: * C is the base cost for it. ! 669: * Fchar is the first input character from ! 670: * the current state, NOCHAR if none. ! 671: * The rest of the inputs come from the array ! 672: * YC, starting at origin and continuing to the ! 673: * last character there, YC[yCcnt - 1].Yychar. ! 674: * ! 675: * The cost returned is INFINITE if this correction ! 676: * allows no shifts, otherwise is weighted based ! 677: * on the number of shifts this allows against the ! 678: * maximum number possible with the available lookahead. ! 679: */ ! 680: correct(fchar, origin, c, multvec, Ps0, Pv0) ! 681: register int fchar, c; ! 682: int origin; ! 683: char *multvec; ! 684: int *Ps0, *Pv0; ! 685: { ! 686: register char *mv; ! 687: ! 688: /* ! 689: * Ps is the top of the parse stack after the most ! 690: * recent local correctness check. Loccor returns ! 691: * NIL when we cannot shift. ! 692: */ ! 693: register int *ps; ! 694: ! 695: yyredfail = 0; ! 696: /* ! 697: * Initialize the tip parse and semantic stacks. ! 698: */ ! 699: ps = Ps0; ! 700: yytips[0] = *ps; ! 701: ps--; ! 702: yytipv[0] = Pv0[0]; ! 703: yCpv = Pv0 - 1; ! 704: yytipct = 1; ! 705: ! 706: /* ! 707: * Shift while possible. ! 708: * Adjust cost as necessary. ! 709: */ ! 710: mv = multvec; ! 711: do { ! 712: if (fchar != NOCHAR) { ! 713: copy(&ntok, &YC[0], sizeof ntok); ! 714: ntok.Yychar = fchar, ntok.Yylval = nullsem(fchar); ! 715: fchar = NOCHAR; ! 716: ps = loccor(ps, &ntok); ! 717: } else ! 718: ps = loccor(ps, &YC[origin++]); ! 719: if (ps == NIL) { ! 720: if (yyredfail && mv > multvec) ! 721: mv--; ! 722: c *= *mv; ! 723: break; ! 724: } ! 725: mv++; ! 726: } while (*mv != 1); ! 727: return (c); ! 728: } ! 729: ! 730: extern int yygo[], yypgo[], yyr1[], yyr2[]; ! 731: /* ! 732: * Local syntactic correctness check. ! 733: * The arguments to this routine are a ! 734: * top of stack pointer, ps, and an input ! 735: * token tok. Also, implicitly, the contents ! 736: * of the yytips array which contains the tip ! 737: * of the stack, and into which the new top ! 738: * state on the stack will be placed if we shift. ! 739: * ! 740: * If we succeed, we return a new top of stack ! 741: * pointer, else we return NIL. ! 742: */ ! 743: loccor(ps, ntok) ! 744: int *ps; ! 745: struct yytok *ntok; ! 746: { ! 747: register int *p, n; ! 748: register int nchar; ! 749: int i; ! 750: ! 751: if (ps == NIL) ! 752: return (NIL); ! 753: nchar = ntok->Yychar; ! 754: yyeline = ntok->Yyeline; ! 755: #ifdef DEBUG ! 756: Tprintf(" Stack "); ! 757: for (i = yytipct - 1; i >= 0; i--) ! 758: Tprintf("%d ", yytips[i]); ! 759: Tprintf("| %d, Input %s%s\n", *ps, charname(nchar)); ! 760: #endif ! 761: /* ! 762: * As in the yacc parser yyparse, ! 763: * p traces through the action list ! 764: * and "n" is the information associated ! 765: * with the action. ! 766: */ ! 767: newstate: ! 768: p = &yyact[ yypact[yytips[yytipct - 1]+1] ]; ! 769: ! 770: actn: ! 771: /* ! 772: * Search the parse actions table ! 773: * for something useful to do. ! 774: * While n is non-positive, it is the ! 775: * arithmetic inverse of the token to be tested. ! 776: * This allows a fast check. ! 777: */ ! 778: while ((n = *p++) <= 0) ! 779: if ((n += nchar) != 0) ! 780: p++; ! 781: switch (n >> 12) { ! 782: /* ! 783: * SHIFT ! 784: */ ! 785: case 2: ! 786: n &= 07777; ! 787: yyredfail = 0; ! 788: if (nchar == YID) ! 789: yyredfail++; ! 790: if (yytipct == YYTIPSIZ) { ! 791: tipover: ! 792: #ifdef DEBUG ! 793: Tprintf("\tTIP OVFLO\n"); ! 794: #endif ! 795: return (NIL); ! 796: } ! 797: yytips[yytipct] = n; ! 798: yytipv[yytipct] = ntok->Yylval; ! 799: yytipct++; ! 800: #ifdef DEBUG ! 801: Tprintf("\tShift to state %d\n", n); ! 802: #endif ! 803: return (ps); ! 804: /* ! 805: * REDUCE ! 806: */ ! 807: case 3: ! 808: n &= 07777; ! 809: if (yyEactr(n, yytipv[yytipct - 1]) == 0) { ! 810: #ifdef DEBUG ! 811: Tprintf("\tYyEactr objects: have %s id, want %s id\n", classes[yyidhave], classes[yyidwant]); ! 812: #endif ! 813: return (NIL); ! 814: } ! 815: yyredfail = 0; ! 816: i = yyr2[n]; ! 817: #ifdef DEBUG ! 818: Tprintf("\tReduce, length %d,", i); ! 819: #endif ! 820: if (i > yytipct) { ! 821: i -= yytipct; ! 822: yytipct = 0; ! 823: ps -= i; ! 824: yCpv -= i; ! 825: } else ! 826: yytipct -= i; ! 827: if (yytipct >= YYTIPSIZ) ! 828: goto tipover; ! 829: /* ! 830: * Use goto table to find next state ! 831: */ ! 832: p = &yygo[yypgo[yyr1[n]]]; ! 833: i = yytipct ? yytips[yytipct - 1] : *ps; ! 834: while (*p != i && *p >= 0) ! 835: p += 2; ! 836: #ifdef DEBUG ! 837: Tprintf(" new state %d\n", p[1]); ! 838: #endif ! 839: yytips[yytipct] = p[1]; ! 840: yytipct++; ! 841: goto newstate; ! 842: /* ! 843: * ACCEPT ! 844: */ ! 845: case 4: ! 846: #ifdef DEBUG ! 847: Tprintf("\tAccept\n"); ! 848: #endif ! 849: return (ps); ! 850: /* ! 851: * ERROR ! 852: */ ! 853: case 1: ! 854: #ifdef DEBUG ! 855: Tprintf("\tError\n"); ! 856: #endif ! 857: return (0); ! 858: } ! 859: panic("loccor"); ! 860: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.