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