Annotation of 43BSD/ucb/pascal/src/yyrecover.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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