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