|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: # ! 3: /* ! 4: * pi - Pascal interpreter code translator ! 5: * ! 6: * Charles Haley, Bill Joy UCB ! 7: * Version 1.1 February 1978 ! 8: * ! 9: * ! 10: * pxp - Pascal execution profiler ! 11: * ! 12: * Bill Joy UCB ! 13: * Version 1.1 February 1978 ! 14: */ ! 15: ! 16: #include "whoami" ! 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: bool 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: pchr('\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" ! 343: , charname(cchar , 0 ) ! 344: , charname(cchar , 1 )); ! 345: #endif ! 346: /* ! 347: * Note that the inserted symbol ! 348: * will not be counted as a true input ! 349: * (i.e. the "yytshifts--" below) ! 350: * so that a true shift will be needed ! 351: * to make yytshifts > yyTshifts. ! 352: */ ! 353: yyTshifts = yytshifts; ! 354: } ! 355: } ! 356: } ! 357: ! 358: /* ! 359: * Set up to perform the correction. ! 360: * Build a token appropriate for replacement ! 361: * or insertion in the yytok structure ACchar ! 362: * having the attributes of the input at the ! 363: * point of error. ! 364: */ ! 365: copy(&ACtok, &YC[0], sizeof ACtok); ! 366: acchar = cchar; ! 367: aclval = nullsem(acchar); ! 368: if (aclval != NIL) ! 369: recovered(); ! 370: switch (cact) { ! 371: /* ! 372: * Panic, just restore the ! 373: * lookahead and return. ! 374: */ ! 375: case CPANIC: ! 376: setpfx('E'); ! 377: if (idfail) { ! 378: copy(&Y, &OY, sizeof Y); ! 379: if (yyrhave == NIL) { ! 380: #ifdef PI ! 381: if (yybaduse(yypv[0], yyeline, ISUNDEF) == NIL) ! 382: #endif ! 383: yerror("Undefined identifier"); ! 384: } else { ! 385: yerror("Improper %s identifier", classes[yyrhave]); ! 386: #ifdef PI ! 387: yybaduse(yypv[0], yyeline, NIL); ! 388: #endif ! 389: } ! 390: /* ! 391: * Suppress message from panic routine ! 392: */ ! 393: yyshifts = 1; ! 394: } ! 395: i = 0; ! 396: /* Note that on one path we dont touch yyshifts ! */ ! 397: break; ! 398: /* ! 399: * Delete the input. ! 400: * Mark this as a shift over true input. ! 401: * Restore the lookahead starting at ! 402: * the second token. ! 403: */ ! 404: case CDELETE: ! 405: if (ccost != 0) ! 406: yerror("Deleted %s%s", tokname(&YC[0] , 0 ) ! 407: , tokname(&YC[0] , 1 )); ! 408: yytshifts++; ! 409: i = 1; ! 410: yyshifts = 0; ! 411: break; ! 412: /* ! 413: * Replace the input with a new token. ! 414: */ ! 415: case CREPLACE: ! 416: if (acchar == YEOF) ! 417: yyexeof(); ! 418: if (acchar == YEND) ! 419: aclval = NIL; ! 420: yerror("Replaced %s%s with a %s%s", ! 421: tokname(&YC[0] , 0 ), ! 422: tokname(&YC[0] , 1 ), ! 423: tokname(&ACtok , 0 ), ! 424: tokname(&ACtok , 1 )); ! 425: copy(&YC[0], &ACtok, sizeof YC[0]); ! 426: i = 0; ! 427: yyshifts = 0; ! 428: break; ! 429: /* ! 430: * Insert a token. ! 431: * Don't count this token as a true input shift. ! 432: * For inserted "end"s pas.y is responsible ! 433: * for the error message later so suppress it. ! 434: * Restore all the lookahead. ! 435: */ ! 436: case CINSERT: ! 437: if (acchar == YEOF) ! 438: yyexeof(); ! 439: if (acchar != YEND) ! 440: yerror("Inserted %s%s", ! 441: tokname(&ACtok , 0 ), ! 442: tokname(&ACtok , 1 )); ! 443: yytshifts--; ! 444: i = 0; ! 445: yyshifts = 0; ! 446: break; ! 447: /* ! 448: * Make a unique symbol correction. ! 449: * Like an insertion but a different message. ! 450: */ ! 451: case CUNIQUE: ! 452: setpfx('E'); ! 453: yerror("Expected %s%s", ! 454: tokname(&ACtok , 0 ), ! 455: tokname(&ACtok , 1 )); ! 456: yytshifts--; ! 457: i = 0; ! 458: if (ccost == 0 || yyunique) ! 459: yyshifts = 0; ! 460: else ! 461: yyshifts = -1; ! 462: break; ! 463: /* ! 464: * Change an identifier's type ! 465: * to make it work. ! 466: */ ! 467: case CCHIDENT: ! 468: copy(&Y, &OY, sizeof Y); ! 469: #ifdef PI ! 470: i = 1 << yyrwant; ! 471: #endif ! 472: if (yyrhave == NIL) { ! 473: yerror("Undefined %s", classes[yyrwant]); ! 474: #ifdef PI ! 475: i =| ISUNDEF; ! 476: #endif ! 477: } else ! 478: yerror("Replaced %s id with a %s id", classes[yyrhave], classes[yyrwant]); ! 479: #ifdef PI ! 480: yybaduse(yypv[0], yyeline, i); ! 481: #endif ! 482: yypv[0] = nullsem(YID); ! 483: i = 0; ! 484: yyshifts = 0; ! 485: break; ! 486: } ! 487: ! 488: /* ! 489: * Restore the desired portion of the lookahead, ! 490: * and possibly the inserted or unique inserted token. ! 491: */ ! 492: for (yCcnt--; yCcnt >= i; yCcnt--) ! 493: unyylex(&YC[yCcnt]); ! 494: if (cact == CINSERT || cact == CUNIQUE) ! 495: unyylex(&ACtok); ! 496: ! 497: /* ! 498: * Put the scanner back in sync. ! 499: */ ! 500: yychar = yylex(); ! 501: ! 502: /* ! 503: * We succeeded if we didn't "panic". ! 504: */ ! 505: Recovery = 0; ! 506: Ps = Ps0; ! 507: return (cact != CPANIC); ! 508: } ! 509: ! 510: yyexeof() ! 511: { ! 512: ! 513: yerror("End-of-file expected - QUIT"); ! 514: pexit(ERRS); ! 515: } ! 516: ! 517: yyunexeof() ! 518: { ! 519: ! 520: yerror("Unexpected end-of-file - QUIT"); ! 521: pexit(ERRS); ! 522: } ! 523: ! 524: /* ! 525: * Try corrections with the state at Ps0. ! 526: * Flag is 0 if this is the top of stack state, ! 527: * 1 if it is the state below. ! 528: */ ! 529: trystate(Ps0, Pv0, flag, insmult, delmult, repmult) ! 530: int *Ps0, *Pv0, flag; ! 531: char *insmult, *delmult, *repmult; ! 532: { ! 533: /* ! 534: * C is a working cost, ap a pointer into the action ! 535: * table for looking at feasible alternatives. ! 536: */ ! 537: register int c, *ap; ! 538: int i, *actions; ! 539: ! 540: #ifdef DEBUG ! 541: Eprintf("Trying state %d\n", *Ps0); ! 542: #endif ! 543: /* ! 544: * Try deletion. ! 545: * Correct returns a cost. ! 546: */ ! 547: #ifdef DEBUG ! 548: Tprintf(" Try Delete %s%s cost=%d\n", ! 549: tokname(&YC[0] , 0 ), ! 550: tokname(&YC[0] , 1 ), ! 551: delcost(YC[0].Yychar)); ! 552: #endif ! 553: c = delcost(YC[0].Yychar); ! 554: #ifndef DEBUG ! 555: if (c < ccost) { ! 556: #endif ! 557: c = correct(NOCHAR, 1, c, delmult, Ps0, Pv0); ! 558: #ifdef DEBUG ! 559: if (c < CPRLIMIT || fulltrace) ! 560: Eprintf("Cost %2d Delete %s%s\n", c, ! 561: tokname(&YC[0] , 0 ), ! 562: tokname(&YC[0] , 1 )); ! 563: #endif ! 564: if (c < ccost) ! 565: cact = CDELETE, ccost = c, cflag = flag; ! 566: #ifndef DEBUG ! 567: } ! 568: #endif ! 569: ! 570: /* ! 571: * Look at the inputs to this state ! 572: * which will cause parse action shift. ! 573: */ ! 574: aclval = NIL; ! 575: ap = &yyact[yypact[*Ps0 + 1]]; ! 576: ! 577: /* ! 578: * Skip action on error to ! 579: * detect true unique inputs. ! 580: * Error action is always first. ! 581: */ ! 582: if (*ap == -ERROR) ! 583: ap=+ 2; ! 584: ! 585: /* ! 586: * Loop through the test actions ! 587: * for this state. ! 588: */ ! 589: for (actions = ap; *ap <= 0; ap =+ 2) { ! 590: /* ! 591: * Extract the token of this action ! 592: */ ! 593: acchar = -*ap; ! 594: ! 595: /* ! 596: * Try insertion ! 597: */ ! 598: #ifdef DEBUG ! 599: Tprintf(" Try Insert %s%s cost=%d\n" ! 600: , charname(acchar , 0 ) ! 601: , charname(acchar , 1 ) ! 602: , inscost(acchar)); ! 603: #endif ! 604: c = inscost(acchar, YC[0].Yychar); ! 605: #ifndef DEBUG ! 606: if (c < ccost) { ! 607: #endif ! 608: if (c == 0) { ! 609: c = correct(acchar, 0, 1, insmult + 1, Ps0, Pv0); ! 610: #ifdef DEBUG ! 611: Eprintf("Cost %2d Freebie %s%s\n", c ! 612: , charname(acchar , 0 ) ! 613: , charname(acchar , 1 )); ! 614: #endif ! 615: if (c < ccost) ! 616: cact = CUNIQUE, ccost = 0, cchar = acchar, cflag = flag; ! 617: } else { ! 618: c = correct(acchar, 0, c, insmult, Ps0, Pv0); ! 619: #ifdef DEBUG ! 620: if (c < CPRLIMIT || fulltrace) ! 621: Eprintf("Cost %2d Insert %s%s\n", c ! 622: , charname(acchar , 0 ) ! 623: , charname(acchar , 1 )); ! 624: #endif ! 625: if (c < ccost) ! 626: cact = CINSERT, ccost = c, cchar = acchar, cflag = flag; ! 627: } ! 628: #ifndef DEBUG ! 629: } ! 630: #endif ! 631: ! 632: /* ! 633: * Try replacement ! 634: */ ! 635: #ifdef DEBUG ! 636: Tprintf(" Try Replace %s%s with %s%s cost=%d\n", ! 637: tokname(&YC[0] , 0 ), ! 638: tokname(&YC[0] , 1 ), ! 639: charname(acchar , 0 ), ! 640: charname(acchar , 1 ), ! 641: repcost(YC[0].Yychar, acchar)); ! 642: #endif ! 643: c = repcost(YC[0].Yychar, acchar); ! 644: #ifndef DEBUG ! 645: if (c < ccost) { ! 646: #endif ! 647: c = correct(acchar, 1, repcost(YC[0].Yychar, acchar), repmult, Ps0, Pv0); ! 648: #ifdef DEBUG ! 649: if (c < CPRLIMIT || fulltrace) ! 650: Eprintf("Cost %2d Replace %s%s with %s%s\n", ! 651: c, ! 652: tokname(&YC[0] , 0 ), ! 653: tokname(&YC[0] , 1 ), ! 654: tokname(&ACtok , 0 ), ! 655: tokname(&ACtok , 1 )); ! 656: #endif ! 657: if (c < ccost) ! 658: cact = CREPLACE, ccost = c, cchar = acchar, cflag = flag; ! 659: #ifndef DEBUG ! 660: } ! 661: #endif ! 662: } ! 663: } ! 664: ! 665: int *yCpv; ! 666: char yyredfail; ! 667: ! 668: /* ! 669: * The ntok structure is used to build a ! 670: * scanner structure for tokens inserted ! 671: * from the argument "fchar" to "correct" below. ! 672: */ ! 673: static struct yytok ntok; ! 674: ! 675: /* ! 676: * Compute the cost of a correction ! 677: * C is the base cost for it. ! 678: * Fchar is the first input character from ! 679: * the current state, NOCHAR if none. ! 680: * The rest of the inputs come from the array ! 681: * YC, starting at origin and continuing to the ! 682: * last character there, YC[yCcnt - 1].Yychar. ! 683: * ! 684: * The cost returned is INFINITE if this correction ! 685: * allows no shifts, otherwise is weighted based ! 686: * on the number of shifts this allows against the ! 687: * maximum number possible with the available lookahead. ! 688: */ ! 689: correct(fchar, origin, c, multvec, Ps0, Pv0) ! 690: register int fchar, c; ! 691: int origin; ! 692: char *multvec; ! 693: int *Ps0, *Pv0; ! 694: { ! 695: register char *mv; ! 696: ! 697: /* ! 698: * Ps is the top of the parse stack after the most ! 699: * recent local correctness check. Loccor returns ! 700: * NIL when we cannot shift. ! 701: */ ! 702: register int *ps; ! 703: ! 704: yyredfail = 0; ! 705: /* ! 706: * Initialize the tip parse and semantic stacks. ! 707: */ ! 708: ps = Ps0; ! 709: yytips[0] = *ps; ! 710: ps--; ! 711: yytipv[0] = Pv0[0]; ! 712: yCpv = Pv0 - 1; ! 713: yytipct = 1; ! 714: ! 715: /* ! 716: * Shift while possible. ! 717: * Adjust cost as necessary. ! 718: */ ! 719: mv = multvec; ! 720: do { ! 721: if (fchar != NOCHAR) { ! 722: copy(&ntok, &YC[0], sizeof ntok); ! 723: ntok.Yychar = fchar, ntok.Yylval = nullsem(fchar); ! 724: fchar = NOCHAR; ! 725: ps = loccor(ps, &ntok); ! 726: } else ! 727: ps = loccor(ps, &YC[origin++]); ! 728: if (ps == NIL) { ! 729: if (yyredfail && mv > multvec) ! 730: mv--; ! 731: c =* *mv; ! 732: break; ! 733: } ! 734: mv++; ! 735: } while (*mv != 1); ! 736: return (c); ! 737: } ! 738: ! 739: extern int yygo[], yypgo[], yyr1[], yyr2[]; ! 740: /* ! 741: * Local syntactic correctness check. ! 742: * The arguments to this routine are a ! 743: * top of stack pointer, ps, and an input ! 744: * token tok. Also, implicitly, the contents ! 745: * of the yytips array which contains the tip ! 746: * of the stack, and into which the new top ! 747: * state on the stack will be placed if we shift. ! 748: * ! 749: * If we succeed, we return a new top of stack ! 750: * pointer, else we return NIL. ! 751: */ ! 752: loccor(ps, ntok) ! 753: int *ps; ! 754: struct yytok *ntok; ! 755: { ! 756: register int *p, n; ! 757: register int nchar; ! 758: int i; ! 759: ! 760: if (ps == NIL) ! 761: return (NIL); ! 762: nchar = ntok->Yychar; ! 763: yyeline = ntok->Yyeline; ! 764: #ifdef DEBUG ! 765: Tprintf(" Stack "); ! 766: for (i = yytipct - 1; i >= 0; i--) ! 767: Tprintf("%d ", yytips[i]); ! 768: Tprintf("| %d, Input %s%s\n", *ps ! 769: , charname(nchar , 0 ) ! 770: , charname(nchar , 1 )); ! 771: #endif ! 772: /* ! 773: * As in the yacc parser yyparse, ! 774: * p traces through the action list ! 775: * and "n" is the information associated ! 776: * with the action. ! 777: */ ! 778: newstate: ! 779: p = &yyact[ yypact[yytips[yytipct - 1]+1] ]; ! 780: ! 781: actn: ! 782: /* ! 783: * Search the parse actions table ! 784: * for something useful to do. ! 785: * While n is non-positive, it is the ! 786: * arithmetic inverse of the token to be tested. ! 787: * This allows a fast check. ! 788: */ ! 789: while ((n = *p++) <= 0) ! 790: if ((n =+ nchar) != 0) ! 791: p++; ! 792: switch (n >> 12) { ! 793: /* ! 794: * SHIFT ! 795: */ ! 796: case 2: ! 797: n =& 07777; ! 798: yyredfail = 0; ! 799: if (nchar == YID) ! 800: yyredfail++; ! 801: if (yytipct == YYTIPSIZ) { ! 802: tipover: ! 803: #ifdef DEBUG ! 804: Tprintf("\tTIP OVFLO\n"); ! 805: #endif ! 806: return (NIL); ! 807: } ! 808: yytips[yytipct] = n; ! 809: yytipv[yytipct] = ntok->Yylval; ! 810: yytipct++; ! 811: #ifdef DEBUG ! 812: Tprintf("\tShift to state %d\n", n); ! 813: #endif ! 814: return (ps); ! 815: /* ! 816: * REDUCE ! 817: */ ! 818: case 3: ! 819: n =& 07777; ! 820: if (yyEactr(n, yytipv[yytipct - 1]) == 0) { ! 821: #ifdef DEBUG ! 822: Tprintf("\tYyEactr objects: have %s id, want %s id\n", classes[yyidhave], classes[yyidwant]); ! 823: #endif ! 824: return (NIL); ! 825: } ! 826: yyredfail = 0; ! 827: i = yyr2[n]; ! 828: #ifdef DEBUG ! 829: Tprintf("\tReduce, length %d,", i); ! 830: #endif ! 831: if (i > yytipct) { ! 832: i =- yytipct; ! 833: yytipct = 0; ! 834: ps =- i; ! 835: yCpv =- i; ! 836: } else ! 837: yytipct =- i; ! 838: if (yytipct >= YYTIPSIZ) ! 839: goto tipover; ! 840: /* ! 841: * Use goto table to find next state ! 842: */ ! 843: p = &yygo[yypgo[yyr1[n]]]; ! 844: i = yytipct ? yytips[yytipct - 1] : *ps; ! 845: while (*p != i && *p >= 0) ! 846: p =+ 2; ! 847: #ifdef DEBUG ! 848: Tprintf(" new state %d\n", p[1]); ! 849: #endif ! 850: yytips[yytipct] = p[1]; ! 851: yytipct++; ! 852: goto newstate; ! 853: /* ! 854: * ACCEPT ! 855: */ ! 856: case 4: ! 857: #ifdef DEBUG ! 858: Tprintf("\tAccept\n"); ! 859: #endif ! 860: return (ps); ! 861: /* ! 862: * ERROR ! 863: */ ! 864: case 1: ! 865: #ifdef DEBUG ! 866: Tprintf("\tError\n"); ! 867: #endif ! 868: return (0); ! 869: } ! 870: panic("loccor"); ! 871: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.