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

Defined functions

correct defined in line 691; used 5 times
loccor defined in line 755; used 3 times
trystate defined in line 532; used 2 times
yyexeof defined in line 513; used 4 times
yyrecover defined in line 192; used 1 times

Defined variables

ACtok defined in line 183; used 14 times
YC defined in line 160; used 36 times
YC0 defined in line 159; used 1 times
cact defined in line 176; used 12 times
cchar defined in line 176; used 10 times
ccost defined in line 176; used 16 times
cflag defined in line 176; used 6 times
delmult defined in line 126; used 5 times
insmult defined in line 124; used 6 times
ntok defined in line 675; used 10 times
repmult defined in line 125; used 6 times
sccsid defined in line 8; never used
yCcnt defined in line 158; used 11 times
yCpv defined in line 667; used 2 times
yyTshifts defined in line 169; used 2 times
yyact defined in line 137; used 3 times
yypact defined in line 137; used 3 times
yypv defined in line 136; used 11 times
yyredfail defined in line 668; used 5 times
yytipct defined in line 148; used 17 times
yytips defined in line 148; used 6 times
yytipv defined in line 149; used 3 times

Defined macros

CCHIDCOST defined in line 122; used 2 times
CCHIDENT defined in line 87; used 1 times
CDELETE defined in line 83; used 1 times
CINSERT defined in line 85; used 2 times
CPANIC defined in line 82; used 3 times
CPRLIMIT defined in line 121; used 4 times
CREPLACE defined in line 84; used 1 times
CUNIQUE defined in line 86; used 3 times
Eprintf defined in line 130; used 9 times
NOCHAR defined in line 128; used 4 times
Tprintf defined in line 131; used 14 times
YCSIZ defined in line 156; used 2 times
YYTIPSIZ defined in line 147; used 4 times
acchar defined in line 185; used 26 times
aclval defined in line 186; used 4 times
Last modified: 1985-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4548
Valid CSS Valid XHTML 1.0 Strict