Annotation of 41BSD/cmd/pxp/yyrecover.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.