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