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