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

Defined functions

correct defined in line 690; used 5 times
loccor defined in line 753; used 2 times
trystate defined in line 530; used 2 times
yyexeof defined in line 511; used 4 times
yyrecover defined in line 196; used 1 times
yyunexeof defined in line 518; used 1 times

Defined variables

ACtok defined in line 187; used 14 times
YC defined in line 164; used 35 times
YC0 defined in line 163; used 1 times
cact defined in line 180; used 12 times
cchar defined in line 180; used 10 times
ccost defined in line 180; used 16 times
cflag defined in line 180; used 6 times
delmult defined in line 131; used 5 times
insmult defined in line 129; used 6 times
ntok defined in line 674; used 10 times
repmult defined in line 130; used 6 times
yCcnt defined in line 162; used 11 times
yCpv defined in line 666; used 2 times
yyTshifts defined in line 173; used 2 times
yyact defined in line 141; used 3 times
yypact defined in line 141; used 3 times
yypv defined in line 141; used 11 times
yyredfail defined in line 667; used 5 times
yytipct defined in line 152; used 17 times
yytips defined in line 152; used 6 times
yytipv defined in line 153; used 3 times

Defined macros

CCHIDCOST defined in line 127; used 2 times
CCHIDENT defined in line 92; used 1 times
CDELETE defined in line 88; used 1 times
CINSERT defined in line 90; used 2 times
CPANIC defined in line 87; used 3 times
CPRLIMIT defined in line 126; used 4 times
CREPLACE defined in line 89; used 1 times
CUNIQUE defined in line 91; used 3 times
Eprintf defined in line 135; used 9 times
NOCHAR defined in line 133; used 4 times
Tprintf defined in line 136; used 14 times
YCSIZ defined in line 160; used 2 times
YYTIPSIZ defined in line 151; used 4 times
acchar defined in line 189; used 26 times
aclval defined in line 190; used 4 times
Last modified: 1983-03-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2321
Valid CSS Valid XHTML 1.0 Strict