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

unix.superglobalmegacorp.com

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