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