1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)yyrecover.c 1.3 02/05/83"; 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 #ifdef PXP 203 putchar('\n'); 204 #else 205 pchr('\n'); 206 #endif 207 printf("Input %s%s", tokname(&Y , 0) 208 , tokname(&Y , 1)); 209 } 210 211 #endif 212 /* 213 * We first save the current input token 214 * and its associated semantic information. 215 */ 216 if (yychar < 0) 217 yychar = yylex(); 218 copy(&YC[0], &Y, sizeof Y); 219 220 /* 221 * Set the default action and cost 222 */ 223 cact = CPANIC, ccost = CLIMIT, cflag = 0; 224 225 /* 226 * Peek ahead 227 */ 228 for (yCcnt = 1; yCcnt < YCSIZ; yCcnt++) { 229 yychar = yylex(); 230 copy(&YC[yCcnt], &Y, sizeof YC[0]); 231 #ifdef DEBUG 232 Eprintf(" | %s%s", tokname(&YC[yCcnt] , 0 ) 233 , tokname(&YC[yCcnt] , 1 )); 234 #endif 235 } 236 #ifdef DEBUG 237 Eprintf("\n"); 238 #endif 239 240 /* 241 * If we are here because a reduction failed, try 242 * correcting that. 243 */ 244 if (idfail) { 245 /* 246 * Save the particulars about 247 * the kind of identifier we want/have. 248 */ 249 yyrwant = yyidwant; 250 yyrhave = yyidhave; 251 #ifdef DEBUG 252 Tprintf(" Try Replace %s identifier with %s identifier cost=%d\n", 253 classes[yyidhave], classes[yyidwant], CCHIDCOST); 254 #endif 255 256 /* 257 * Save the semantics of the ID on the 258 * stack, and null them out to free 259 * up the reduction in question. 260 */ 261 i = yypv[0]; 262 yypv[0] = nullsem(YID); 263 c = correct(NOCHAR, 0, CCHIDCOST, &repmult[2], Ps0, yypv); 264 yypv[0] = i; 265 #ifdef DEBUG 266 if (c < CPRLIMIT || fulltrace) 267 Eprintf("Cost %2d Replace %s identifier with %s identifier\n", c, classes[yyrhave], classes[yyrwant]); 268 #endif 269 if (c < ccost) 270 cact = CCHIDENT, ccost = c, cchar = YID; 271 } 272 273 /* 274 * First try correcting the state we are in 275 */ 276 trystate(Ps0, yypv, 0, &insmult[1], &delmult[1], &repmult[1]); 277 278 /* 279 * Now, if we just shifted over a terminal, try 280 * correcting it. 281 */ 282 if (OY.Yychar != -1 && OY.Yylval != nullsem(OY.Yychar)) { 283 YC--; 284 copy(&YC[0], &OY, sizeof YC[0]); 285 trystate(Ps0 - 1, yypv - 1, 1, insmult, delmult, repmult); 286 if (cflag == 0) 287 YC++; 288 else { 289 yypv--; 290 #ifdef PXP 291 yypw--; 292 #endif 293 Ps0--; 294 yCcnt++; 295 } 296 } 297 298 /* 299 * Restoring the first look ahead into 300 * the scanner token allows the error message 301 * routine to print the error message with the text 302 * of the correct line. 303 */ 304 copy(&Y, &YC[0], sizeof Y); 305 306 /* 307 * Unique symbol insertion. 308 * 309 * If there was no reasonable correction found, 310 * but only one input to the parser is acceptable 311 * we report that, and try it. 312 * 313 * Special precautions here to prevent looping. 314 * The number of true inputs shifted over at the point 315 * of the last unique insertion is recorded in the 316 * variable yyTshifts. If this is not less than 317 * the current number in yytshifts, we do not insert. 318 * Thus, after one unique insertion, no more unique 319 * insertions will be made until an input is shifted 320 * over. This guarantees termination. 321 */ 322 if (cact == CPANIC && !idfail) { 323 register int *ap; 324 325 ap = &yyact[yypact[*Ps0 + 1]]; 326 if (*ap == -ERROR) 327 ap += 2; 328 if (ap[0] <= 0 && ap[2] > 0) { 329 cchar = -ap[0]; 330 if (cchar == YEOF) 331 yyexeof(); 332 if (cchar != ERROR && yyTshifts < yytshifts) { 333 cact = CUNIQUE; 334 #ifdef DEBUG 335 Eprintf("Unique symbol %s%s\n" 336 , charname(cchar , 0 ) 337 , charname(cchar , 1 )); 338 #endif 339 /* 340 * Note that the inserted symbol 341 * will not be counted as a true input 342 * (i.e. the "yytshifts--" below) 343 * so that a true shift will be needed 344 * to make yytshifts > yyTshifts. 345 */ 346 yyTshifts = yytshifts; 347 } 348 } 349 } 350 351 /* 352 * Set up to perform the correction. 353 * Build a token appropriate for replacement 354 * or insertion in the yytok structure ACchar 355 * having the attributes of the input at the 356 * point of error. 357 */ 358 copy(&ACtok, &YC[0], sizeof ACtok); 359 acchar = cchar; 360 aclval = nullsem(acchar); 361 if (aclval != NIL) 362 recovered(); 363 switch (cact) { 364 /* 365 * Panic, just restore the 366 * lookahead and return. 367 */ 368 case CPANIC: 369 setpfx('E'); 370 if (idfail) { 371 copy(&Y, &OY, sizeof Y); 372 if (yyrhave == NIL) { 373 #ifdef PI 374 if (yybaduse(yypv[0], yyeline, ISUNDEF) == NIL) 375 #endif 376 yerror("Undefined identifier"); 377 } else { 378 yerror("Improper %s identifier", classes[yyrhave]); 379 #ifdef PI 380 yybaduse(yypv[0], yyeline, NIL); 381 #endif 382 } 383 /* 384 * Suppress message from panic routine 385 */ 386 yyshifts = 1; 387 } 388 i = 0; 389 /* Note that on one path we dont touch yyshifts ! */ 390 break; 391 /* 392 * Delete the input. 393 * Mark this as a shift over true input. 394 * Restore the lookahead starting at 395 * the second token. 396 */ 397 case CDELETE: 398 if (ccost != 0) 399 yerror("Deleted %s%s", tokname(&YC[0] , 0 ) 400 , tokname(&YC[0] , 1 )); 401 yytshifts++; 402 i = 1; 403 yyshifts = 0; 404 break; 405 /* 406 * Replace the input with a new token. 407 */ 408 case CREPLACE: 409 if (acchar == YEOF) 410 yyexeof(); 411 if (acchar == YEND) 412 aclval = NIL; 413 yerror("Replaced %s%s with a %s%s", 414 tokname(&YC[0] , 0 ), 415 tokname(&YC[0] , 1 ), 416 tokname(&ACtok , 0 ), 417 tokname(&ACtok , 1 )); 418 copy(&YC[0], &ACtok, sizeof YC[0]); 419 i = 0; 420 yyshifts = 0; 421 break; 422 /* 423 * Insert a token. 424 * Don't count this token as a true input shift. 425 * For inserted "end"s pas.y is responsible 426 * for the error message later so suppress it. 427 * Restore all the lookahead. 428 */ 429 case CINSERT: 430 if (acchar == YEOF) 431 yyexeof(); 432 if (acchar != YEND) 433 yerror("Inserted %s%s", 434 tokname(&ACtok , 0 ), 435 tokname(&ACtok , 1 )); 436 yytshifts--; 437 i = 0; 438 yyshifts = 0; 439 break; 440 /* 441 * Make a unique symbol correction. 442 * Like an insertion but a different message. 443 */ 444 case CUNIQUE: 445 setpfx('E'); 446 yerror("Expected %s%s", 447 tokname(&ACtok , 0 ), 448 tokname(&ACtok , 1 )); 449 yytshifts--; 450 i = 0; 451 if (ccost == 0 || yyunique) 452 yyshifts = 0; 453 else 454 yyshifts = -1; 455 break; 456 /* 457 * Change an identifier's type 458 * to make it work. 459 */ 460 case CCHIDENT: 461 copy(&Y, &OY, sizeof Y); 462 #ifdef PI 463 i = 1 << yyrwant; 464 #endif 465 if (yyrhave == NIL) { 466 yerror("Undefined %s", classes[yyrwant]); 467 #ifdef PI 468 i |= ISUNDEF; 469 #endif 470 } else 471 yerror("Replaced %s id with a %s id", classes[yyrhave], classes[yyrwant]); 472 #ifdef PI 473 yybaduse(yypv[0], yyeline, i); 474 #endif 475 yypv[0] = nullsem(YID); 476 i = 0; 477 yyshifts = 0; 478 break; 479 } 480 481 /* 482 * Restore the desired portion of the lookahead, 483 * and possibly the inserted or unique inserted token. 484 */ 485 for (yCcnt--; yCcnt >= i; yCcnt--) 486 unyylex(&YC[yCcnt]); 487 if (cact == CINSERT || cact == CUNIQUE) 488 unyylex(&ACtok); 489 490 /* 491 * Put the scanner back in sync. 492 */ 493 yychar = yylex(); 494 495 /* 496 * We succeeded if we didn't "panic". 497 */ 498 Recovery = 0; 499 Ps = Ps0; 500 return (cact != CPANIC); 501 } 502 503 yyexeof() 504 { 505 506 yerror("End-of-file expected - QUIT"); 507 pexit(ERRS); 508 } 509 510 yyunexeof() 511 { 512 513 yerror("Unexpected end-of-file - QUIT"); 514 pexit(ERRS); 515 } 516 517 /* 518 * Try corrections with the state at Ps0. 519 * Flag is 0 if this is the top of stack state, 520 * 1 if it is the state below. 521 */ 522 trystate(Ps0, Pv0, flag, insmult, delmult, repmult) 523 int *Ps0, *Pv0, flag; 524 char *insmult, *delmult, *repmult; 525 { 526 /* 527 * C is a working cost, ap a pointer into the action 528 * table for looking at feasible alternatives. 529 */ 530 register int c, *ap; 531 int i, *actions; 532 533 #ifdef DEBUG 534 Eprintf("Trying state %d\n", *Ps0); 535 #endif 536 /* 537 * Try deletion. 538 * Correct returns a cost. 539 */ 540 #ifdef DEBUG 541 Tprintf(" Try Delete %s%s cost=%d\n", 542 tokname(&YC[0] , 0 ), 543 tokname(&YC[0] , 1 ), 544 delcost(YC[0].Yychar)); 545 #endif 546 c = delcost(YC[0].Yychar); 547 #ifndef DEBUG 548 if (c < ccost) { 549 #endif 550 c = correct(NOCHAR, 1, c, delmult, Ps0, Pv0); 551 #ifdef DEBUG 552 if (c < CPRLIMIT || fulltrace) 553 Eprintf("Cost %2d Delete %s%s\n", c, 554 tokname(&YC[0] , 0 ), 555 tokname(&YC[0] , 1 )); 556 #endif 557 if (c < ccost) 558 cact = CDELETE, ccost = c, cflag = flag; 559 #ifndef DEBUG 560 } 561 #endif 562 563 /* 564 * Look at the inputs to this state 565 * which will cause parse action shift. 566 */ 567 aclval = NIL; 568 ap = &yyact[yypact[*Ps0 + 1]]; 569 570 /* 571 * Skip action on error to 572 * detect true unique inputs. 573 * Error action is always first. 574 */ 575 if (*ap == -ERROR) 576 ap += 2; 577 578 /* 579 * Loop through the test actions 580 * for this state. 581 */ 582 for (actions = ap; *ap <= 0; ap += 2) { 583 /* 584 * Extract the token of this action 585 */ 586 acchar = -*ap; 587 588 /* 589 * Try insertion 590 */ 591 #ifdef DEBUG 592 Tprintf(" Try Insert %s%s cost=%d\n" 593 , charname(acchar , 0 ) 594 , charname(acchar , 1 ) 595 , inscost(acchar)); 596 #endif 597 c = inscost(acchar, YC[0].Yychar); 598 #ifndef DEBUG 599 if (c < ccost) { 600 #endif 601 if (c == 0) { 602 c = correct(acchar, 0, 1, insmult + 1, Ps0, Pv0); 603 #ifdef DEBUG 604 Eprintf("Cost %2d Freebie %s%s\n", c 605 , charname(acchar , 0 ) 606 , charname(acchar , 1 )); 607 #endif 608 if (c < ccost) 609 cact = CUNIQUE, ccost = 0, cchar = acchar, cflag = flag; 610 } else { 611 c = correct(acchar, 0, c, insmult, Ps0, Pv0); 612 #ifdef DEBUG 613 if (c < CPRLIMIT || fulltrace) 614 Eprintf("Cost %2d Insert %s%s\n", c 615 , charname(acchar , 0 ) 616 , charname(acchar , 1 )); 617 #endif 618 if (c < ccost) 619 cact = CINSERT, ccost = c, cchar = acchar, cflag = flag; 620 } 621 #ifndef DEBUG 622 } 623 #endif 624 625 /* 626 * Try replacement 627 */ 628 #ifdef DEBUG 629 Tprintf(" Try Replace %s%s with %s%s cost=%d\n", 630 tokname(&YC[0] , 0 ), 631 tokname(&YC[0] , 1 ), 632 charname(acchar , 0 ), 633 charname(acchar , 1 ), 634 repcost(YC[0].Yychar, acchar)); 635 #endif 636 c = repcost(YC[0].Yychar, acchar); 637 #ifndef DEBUG 638 if (c < ccost) { 639 #endif 640 c = correct(acchar, 1, repcost(YC[0].Yychar, acchar), repmult, Ps0, Pv0); 641 #ifdef DEBUG 642 if (c < CPRLIMIT || fulltrace) 643 Eprintf("Cost %2d Replace %s%s with %s%s\n", 644 c, 645 tokname(&YC[0] , 0 ), 646 tokname(&YC[0] , 1 ), 647 tokname(&ACtok , 0 ), 648 tokname(&ACtok , 1 )); 649 #endif 650 if (c < ccost) 651 cact = CREPLACE, ccost = c, cchar = acchar, cflag = flag; 652 #ifndef DEBUG 653 } 654 #endif 655 } 656 } 657 658 int *yCpv; 659 char yyredfail; 660 661 /* 662 * The ntok structure is used to build a 663 * scanner structure for tokens inserted 664 * from the argument "fchar" to "correct" below. 665 */ 666 static struct yytok ntok; 667 668 /* 669 * Compute the cost of a correction 670 * C is the base cost for it. 671 * Fchar is the first input character from 672 * the current state, NOCHAR if none. 673 * The rest of the inputs come from the array 674 * YC, starting at origin and continuing to the 675 * last character there, YC[yCcnt - 1].Yychar. 676 * 677 * The cost returned is INFINITE if this correction 678 * allows no shifts, otherwise is weighted based 679 * on the number of shifts this allows against the 680 * maximum number possible with the available lookahead. 681 */ 682 correct(fchar, origin, c, multvec, Ps0, Pv0) 683 register int fchar, c; 684 int origin; 685 char *multvec; 686 int *Ps0, *Pv0; 687 { 688 register char *mv; 689 690 /* 691 * Ps is the top of the parse stack after the most 692 * recent local correctness check. Loccor returns 693 * NIL when we cannot shift. 694 */ 695 register int *ps; 696 697 yyredfail = 0; 698 /* 699 * Initialize the tip parse and semantic stacks. 700 */ 701 ps = Ps0; 702 yytips[0] = *ps; 703 ps--; 704 yytipv[0] = Pv0[0]; 705 yCpv = Pv0 - 1; 706 yytipct = 1; 707 708 /* 709 * Shift while possible. 710 * Adjust cost as necessary. 711 */ 712 mv = multvec; 713 do { 714 if (fchar != NOCHAR) { 715 copy(&ntok, &YC[0], sizeof ntok); 716 ntok.Yychar = fchar, ntok.Yylval = nullsem(fchar); 717 fchar = NOCHAR; 718 ps = loccor(ps, &ntok); 719 } else 720 ps = loccor(ps, &YC[origin++]); 721 if (ps == NIL) { 722 if (yyredfail && mv > multvec) 723 mv--; 724 c *= *mv; 725 break; 726 } 727 mv++; 728 } while (*mv != 1); 729 return (c); 730 } 731 732 extern int yygo[], yypgo[], yyr1[], yyr2[]; 733 /* 734 * Local syntactic correctness check. 735 * The arguments to this routine are a 736 * top of stack pointer, ps, and an input 737 * token tok. Also, implicitly, the contents 738 * of the yytips array which contains the tip 739 * of the stack, and into which the new top 740 * state on the stack will be placed if we shift. 741 * 742 * If we succeed, we return a new top of stack 743 * pointer, else we return NIL. 744 */ 745 loccor(ps, ntok) 746 int *ps; 747 struct yytok *ntok; 748 { 749 register int *p, n; 750 register int nchar; 751 int i; 752 753 if (ps == NIL) 754 return (NIL); 755 nchar = ntok->Yychar; 756 yyeline = ntok->Yyeline; 757 #ifdef DEBUG 758 Tprintf(" Stack "); 759 for (i = yytipct - 1; i >= 0; i--) 760 Tprintf("%d ", yytips[i]); 761 Tprintf("| %d, Input %s%s\n", *ps 762 , charname(nchar , 0 ) 763 , charname(nchar , 1 )); 764 #endif 765 /* 766 * As in the yacc parser yyparse, 767 * p traces through the action list 768 * and "n" is the information associated 769 * with the action. 770 */ 771 newstate: 772 p = &yyact[ yypact[yytips[yytipct - 1]+1] ]; 773 774 actn: 775 /* 776 * Search the parse actions table 777 * for something useful to do. 778 * While n is non-positive, it is the 779 * arithmetic inverse of the token to be tested. 780 * This allows a fast check. 781 */ 782 while ((n = *p++) <= 0) 783 if ((n += nchar) != 0) 784 p++; 785 switch (n >> 12) { 786 /* 787 * SHIFT 788 */ 789 case 2: 790 n &= 07777; 791 yyredfail = 0; 792 if (nchar == YID) 793 yyredfail++; 794 if (yytipct == YYTIPSIZ) { 795 tipover: 796 #ifdef DEBUG 797 Tprintf("\tTIP OVFLO\n"); 798 #endif 799 return (NIL); 800 } 801 yytips[yytipct] = n; 802 yytipv[yytipct] = ntok->Yylval; 803 yytipct++; 804 #ifdef DEBUG 805 Tprintf("\tShift to state %d\n", n); 806 #endif 807 return (ps); 808 /* 809 * REDUCE 810 */ 811 case 3: 812 n &= 07777; 813 if (yyEactr(n, yytipv[yytipct - 1]) == 0) { 814 #ifdef DEBUG 815 Tprintf("\tYyEactr objects: have %s id, want %s id\n", classes[yyidhave], classes[yyidwant]); 816 #endif 817 return (NIL); 818 } 819 yyredfail = 0; 820 i = yyr2[n]; 821 #ifdef DEBUG 822 Tprintf("\tReduce, length %d,", i); 823 #endif 824 if (i > yytipct) { 825 i -= yytipct; 826 yytipct = 0; 827 ps -= i; 828 yCpv -= i; 829 } else 830 yytipct -= i; 831 if (yytipct >= YYTIPSIZ) 832 goto tipover; 833 /* 834 * Use goto table to find next state 835 */ 836 p = &yygo[yypgo[yyr1[n]]]; 837 i = yytipct ? yytips[yytipct - 1] : *ps; 838 while (*p != i && *p >= 0) 839 p += 2; 840 #ifdef DEBUG 841 Tprintf(" new state %d\n", p[1]); 842 #endif 843 yytips[yytipct] = p[1]; 844 yytipct++; 845 goto newstate; 846 /* 847 * ACCEPT 848 */ 849 case 4: 850 #ifdef DEBUG 851 Tprintf("\tAccept\n"); 852 #endif 853 return (ps); 854 /* 855 * ERROR 856 */ 857 case 1: 858 #ifdef DEBUG 859 Tprintf("\tError\n"); 860 #endif 861 return (0); 862 } 863 panic("loccor"); 864 } 865