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