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

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

unix.superglobalmegacorp.com

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