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

1.1       root        1: /* Copyright (c) 1979 Regents of the University of California */
                      2: 
                      3: static char sccsid[] = "@(#)yyrecover.c 1.3 2/5/83";
                      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: #ifdef PXP
                    203:                putchar('\n');
                    204: #else
                    205:                pchr('\n');
                    206: #endif
                    207:                printf("Input %s%s", tokname(&Y , 0)
                    208:                                   , tokname(&Y , 1));
                    209:        }
                    210: 
                    211: #endif
                    212:        /*
                    213:         * We first save the current input token
                    214:         * and its associated semantic information.
                    215:         */
                    216:        if (yychar < 0)
                    217:                yychar = yylex();
                    218:        copy(&YC[0], &Y, sizeof Y);
                    219: 
                    220:        /*
                    221:         * Set the default action and cost
                    222:         */
                    223:        cact = CPANIC, ccost = CLIMIT, cflag = 0;
                    224: 
                    225:        /*
                    226:         * Peek ahead
                    227:         */
                    228:        for (yCcnt = 1; yCcnt < YCSIZ; yCcnt++) {
                    229:                yychar = yylex();
                    230:                copy(&YC[yCcnt], &Y, sizeof YC[0]);
                    231: #ifdef DEBUG
                    232:                Eprintf(" | %s%s", tokname(&YC[yCcnt] , 0 )
                    233:                                 , tokname(&YC[yCcnt] , 1 ));
                    234: #endif
                    235:        }
                    236: #ifdef DEBUG
                    237:        Eprintf("\n");
                    238: #endif
                    239: 
                    240:        /*
                    241:         * If we are here because a reduction failed, try
                    242:         * correcting that.
                    243:         */
                    244:        if (idfail) {
                    245:                /*
                    246:                 * Save the particulars about
                    247:                 * the kind of identifier we want/have.
                    248:                 */
                    249:                yyrwant = yyidwant;
                    250:                yyrhave = yyidhave;
                    251: #ifdef DEBUG
                    252:                Tprintf("  Try Replace %s identifier with %s identifier cost=%d\n",
                    253:                    classes[yyidhave], classes[yyidwant], CCHIDCOST);
                    254: #endif
                    255: 
                    256:                /*
                    257:                 * Save the semantics of the ID on the
                    258:                 * stack, and null them out to free
                    259:                 * up the reduction in question.
                    260:                 */
                    261:                i = yypv[0];
                    262:                yypv[0] = nullsem(YID);
                    263:                c = correct(NOCHAR, 0, CCHIDCOST, &repmult[2], Ps0, yypv);
                    264:                yypv[0] = i;
                    265: #ifdef DEBUG
                    266:                if (c < CPRLIMIT || fulltrace)
                    267:                        Eprintf("Cost %2d Replace %s identifier with %s identifier\n", c, classes[yyrhave], classes[yyrwant]);
                    268: #endif
                    269:                if (c < ccost)
                    270:                        cact = CCHIDENT, ccost = c, cchar = YID;
                    271:        }
                    272: 
                    273:        /*
                    274:         * First try correcting the state we are in
                    275:         */
                    276:        trystate(Ps0, yypv, 0, &insmult[1], &delmult[1], &repmult[1]);
                    277: 
                    278:        /*
                    279:         * Now, if we just shifted over a terminal, try
                    280:         * correcting it.
                    281:         */
                    282:        if (OY.Yychar != -1 && OY.Yylval != nullsem(OY.Yychar)) {
                    283:                YC--;
                    284:                copy(&YC[0], &OY, sizeof YC[0]);
                    285:                trystate(Ps0 - 1, yypv - 1, 1, insmult, delmult, repmult);
                    286:                if (cflag == 0)
                    287:                        YC++;
                    288:                else {
                    289:                        yypv--;
                    290: #ifdef PXP
                    291:                        yypw--;
                    292: #endif
                    293:                        Ps0--;
                    294:                        yCcnt++;
                    295:                }
                    296:        }
                    297: 
                    298:        /*
                    299:         * Restoring the first look ahead into
                    300:         * the scanner token allows the error message
                    301:         * routine to print the error message with the text
                    302:         * of the correct line.
                    303:         */
                    304:        copy(&Y, &YC[0], sizeof Y);
                    305: 
                    306:        /*
                    307:         * Unique symbol insertion.
                    308:         *
                    309:         * If there was no reasonable correction found,
                    310:         * but only one input to the parser is acceptable
                    311:         * we report that, and try it.
                    312:         *
                    313:         * Special precautions here to prevent looping.
                    314:         * The number of true inputs shifted over at the point
                    315:         * of the last unique insertion is recorded in the
                    316:         * variable yyTshifts.  If this is not less than
                    317:         * the current number in yytshifts, we do not insert.
                    318:         * Thus, after one unique insertion, no more unique
                    319:         * insertions will be made until an input is shifted
                    320:         * over.  This guarantees termination.
                    321:         */
                    322:        if (cact == CPANIC && !idfail) {
                    323:                register int *ap;
                    324: 
                    325:                ap = &yyact[yypact[*Ps0 + 1]];
                    326:                if (*ap == -ERROR)
                    327:                        ap += 2;
                    328:                if (ap[0] <= 0 && ap[2] > 0) {
                    329:                        cchar = -ap[0];
                    330:                        if (cchar == YEOF)
                    331:                                yyexeof();
                    332:                        if (cchar != ERROR && yyTshifts < yytshifts) {
                    333:                                cact = CUNIQUE;
                    334: #ifdef DEBUG
                    335:                                Eprintf("Unique symbol %s%s\n"
                    336:                                        , charname(cchar , 0 )
                    337:                                        , charname(cchar , 1 ));
                    338: #endif
                    339:                                /*
                    340:                                 * Note that the inserted symbol
                    341:                                 * will not be counted as a true input
                    342:                                 * (i.e. the "yytshifts--" below)
                    343:                                 * so that a true shift will be needed
                    344:                                 * to make yytshifts > yyTshifts.
                    345:                                 */
                    346:                                yyTshifts = yytshifts;
                    347:                        }
                    348:                }
                    349:        }
                    350: 
                    351:        /*
                    352:         * Set up to perform the correction.
                    353:         * Build a token appropriate for replacement
                    354:         * or insertion in the yytok structure ACchar
                    355:         * having the attributes of the input at the
                    356:         * point of error.
                    357:         */
                    358:        copy(&ACtok, &YC[0], sizeof ACtok);
                    359:        acchar = cchar;
                    360:        aclval = nullsem(acchar);
                    361:        if (aclval != NIL)
                    362:                recovered();
                    363:        switch (cact) {
                    364:                /*
                    365:                 * Panic, just restore the
                    366:                 * lookahead and return.
                    367:                 */
                    368:                case CPANIC:
                    369:                        setpfx('E');
                    370:                        if (idfail) {
                    371:                                copy(&Y, &OY, sizeof Y);
                    372:                                if (yyrhave == NIL) {
                    373: #ifdef PI
                    374:                                        if (yybaduse(yypv[0], yyeline, ISUNDEF) == NIL)
                    375: #endif
                    376:                                                yerror("Undefined identifier");
                    377:                                } else {
                    378:                                        yerror("Improper %s identifier", classes[yyrhave]);
                    379: #ifdef PI
                    380:                                        yybaduse(yypv[0], yyeline, NIL);
                    381: #endif
                    382:                                }
                    383:                                /*
                    384:                                 * Suppress message from panic routine
                    385:                                 */
                    386:                                yyshifts = 1;
                    387:                        }
                    388:                        i = 0;
                    389:                        /* Note that on one path we dont touch yyshifts ! */
                    390:                        break;
                    391:                /*
                    392:                 * Delete the input.
                    393:                 * Mark this as a shift over true input.
                    394:                 * Restore the lookahead starting at
                    395:                 * the second token.
                    396:                 */
                    397:                case CDELETE:
                    398:                        if (ccost != 0)
                    399:                                yerror("Deleted %s%s", tokname(&YC[0] , 0 )
                    400:                                                     , tokname(&YC[0] , 1 ));
                    401:                        yytshifts++;
                    402:                        i = 1;
                    403:                        yyshifts = 0;
                    404:                        break;
                    405:                /*
                    406:                 * Replace the input with a new token.
                    407:                 */
                    408:                case CREPLACE:
                    409:                        if (acchar == YEOF)
                    410:                                yyexeof();
                    411:                        if (acchar == YEND)
                    412:                                aclval = NIL;
                    413:                        yerror("Replaced %s%s with a %s%s",
                    414:                            tokname(&YC[0] , 0 ),
                    415:                            tokname(&YC[0] , 1 ),
                    416:                            tokname(&ACtok , 0 ),
                    417:                            tokname(&ACtok , 1 ));
                    418:                        copy(&YC[0], &ACtok, sizeof YC[0]);
                    419:                        i = 0;
                    420:                        yyshifts = 0;
                    421:                        break;
                    422:                /*
                    423:                 * Insert a token.
                    424:                 * Don't count this token as a true input shift.
                    425:                 * For inserted "end"s pas.y is responsible
                    426:                 * for the error message later so suppress it.
                    427:                 * Restore all the lookahead.
                    428:                 */
                    429:                case CINSERT:
                    430:                        if (acchar == YEOF)
                    431:                                yyexeof();
                    432:                        if (acchar != YEND)
                    433:                                yerror("Inserted %s%s",
                    434:                                        tokname(&ACtok , 0 ),
                    435:                                        tokname(&ACtok , 1 ));
                    436:                        yytshifts--;
                    437:                        i = 0;
                    438:                        yyshifts = 0;
                    439:                        break;
                    440:                /*
                    441:                 * Make a unique symbol correction.
                    442:                 * Like an insertion but a different message.
                    443:                 */
                    444:                case CUNIQUE:
                    445:                        setpfx('E');
                    446:                        yerror("Expected %s%s",
                    447:                                tokname(&ACtok , 0 ),
                    448:                                tokname(&ACtok , 1 ));
                    449:                        yytshifts--;
                    450:                        i = 0;
                    451:                        if (ccost == 0 || yyunique)
                    452:                                yyshifts = 0;
                    453:                        else
                    454:                                yyshifts = -1;
                    455:                        break;
                    456:                /*
                    457:                 * Change an identifier's type
                    458:                 * to make it work.
                    459:                 */
                    460:                case CCHIDENT:
                    461:                        copy(&Y, &OY, sizeof Y);
                    462: #ifdef PI
                    463:                        i = 1 << yyrwant;
                    464: #endif
                    465:                        if (yyrhave == NIL) {
                    466:                                yerror("Undefined %s", classes[yyrwant]);
                    467: #ifdef PI
                    468:                                i |= ISUNDEF;
                    469: #endif
                    470:                        } else
                    471:                                yerror("Replaced %s id with a %s id", classes[yyrhave], classes[yyrwant]);
                    472: #ifdef PI
                    473:                        yybaduse(yypv[0], yyeline, i);
                    474: #endif
                    475:                        yypv[0] = nullsem(YID);
                    476:                        i = 0;
                    477:                        yyshifts = 0;
                    478:                        break;
                    479:        }
                    480: 
                    481:        /*
                    482:         * Restore the desired portion of the lookahead,
                    483:         * and possibly the inserted or unique inserted token.
                    484:         */
                    485:        for (yCcnt--; yCcnt >= i; yCcnt--)
                    486:                unyylex(&YC[yCcnt]);
                    487:        if (cact == CINSERT || cact == CUNIQUE)
                    488:                unyylex(&ACtok);
                    489: 
                    490:        /*
                    491:         * Put the scanner back in sync.
                    492:         */
                    493:        yychar = yylex();
                    494: 
                    495:        /*
                    496:         * We succeeded if we didn't "panic".
                    497:         */
                    498:        Recovery = 0;
                    499:        Ps = Ps0;
                    500:        return (cact != CPANIC);
                    501: }
                    502: 
                    503: yyexeof()
                    504: {
                    505: 
                    506:        yerror("End-of-file expected - QUIT");
                    507:        pexit(ERRS);
                    508: }
                    509: 
                    510: yyunexeof()
                    511: {
                    512: 
                    513:        yerror("Unexpected end-of-file - QUIT");
                    514:        pexit(ERRS);
                    515: }
                    516: 
                    517: /*
                    518:  * Try corrections with the state at Ps0.
                    519:  * Flag is 0 if this is the top of stack state,
                    520:  * 1 if it is the state below.
                    521:  */
                    522: trystate(Ps0, Pv0, flag, insmult, delmult, repmult)
                    523:        int *Ps0, *Pv0, flag;
                    524:        char *insmult, *delmult, *repmult;
                    525: {
                    526:        /*
                    527:         * C is a working cost, ap a pointer into the action
                    528:         * table for looking at feasible alternatives.
                    529:         */
                    530:        register int c, *ap;
                    531:        int i, *actions;
                    532: 
                    533: #ifdef DEBUG
                    534:        Eprintf("Trying state %d\n", *Ps0);
                    535: #endif
                    536:        /*
                    537:         * Try deletion.
                    538:         * Correct returns a cost.
                    539:         */
                    540: #ifdef DEBUG
                    541:        Tprintf("  Try Delete %s%s cost=%d\n",
                    542:                tokname(&YC[0] , 0 ),
                    543:                tokname(&YC[0] , 1 ),
                    544:                delcost(YC[0].Yychar));
                    545: #endif
                    546:        c = delcost(YC[0].Yychar);
                    547: #ifndef DEBUG
                    548:        if (c < ccost) {
                    549: #endif
                    550:                c = correct(NOCHAR, 1, c, delmult, Ps0, Pv0);
                    551: #ifdef DEBUG
                    552:                if (c < CPRLIMIT || fulltrace)
                    553:                        Eprintf("Cost %2d Delete %s%s\n", c,
                    554:                                tokname(&YC[0] , 0 ),
                    555:                                tokname(&YC[0] , 1 ));
                    556: #endif
                    557:                if (c < ccost)
                    558:                        cact = CDELETE, ccost = c, cflag = flag;
                    559: #ifndef DEBUG
                    560:        }
                    561: #endif
                    562: 
                    563:        /*
                    564:         * Look at the inputs to this state
                    565:         * which will cause parse action shift.
                    566:         */
                    567:        aclval = NIL;
                    568:        ap = &yyact[yypact[*Ps0 + 1]];
                    569: 
                    570:        /*
                    571:         * Skip action on error to
                    572:         * detect true unique inputs.
                    573:         * Error action is always first.
                    574:         */
                    575:        if (*ap == -ERROR) 
                    576:                ap += 2;
                    577: 
                    578:        /*
                    579:         * Loop through the test actions
                    580:         * for this state.
                    581:         */
                    582:        for (actions = ap; *ap <= 0; ap += 2) {
                    583:                /*
                    584:                 * Extract the token of this action
                    585:                 */
                    586:                acchar = -*ap;
                    587: 
                    588:                /*
                    589:                 * Try insertion
                    590:                 */
                    591: #ifdef DEBUG
                    592:                Tprintf("  Try Insert %s%s cost=%d\n"
                    593:                        , charname(acchar , 0 )
                    594:                        , charname(acchar , 1 )
                    595:                        , inscost(acchar));
                    596: #endif
                    597:                c = inscost(acchar, YC[0].Yychar);
                    598: #ifndef DEBUG
                    599:                if (c < ccost) {
                    600: #endif
                    601:                        if (c == 0) {
                    602:                                c = correct(acchar, 0, 1, insmult + 1, Ps0, Pv0);
                    603: #ifdef DEBUG
                    604:                                Eprintf("Cost %2d Freebie %s%s\n", c
                    605:                                        , charname(acchar , 0 )
                    606:                                        , charname(acchar , 1 ));
                    607: #endif
                    608:                                if (c < ccost)
                    609:                                        cact = CUNIQUE, ccost = 0, cchar = acchar, cflag = flag;
                    610:                        } else {
                    611:                                c = correct(acchar, 0, c, insmult, Ps0, Pv0);
                    612: #ifdef DEBUG
                    613:                                if (c < CPRLIMIT || fulltrace)
                    614:                                        Eprintf("Cost %2d Insert %s%s\n", c
                    615:                                                , charname(acchar , 0 )
                    616:                                                , charname(acchar , 1 ));
                    617: #endif
                    618:                                if (c < ccost)
                    619:                                        cact = CINSERT, ccost = c, cchar = acchar, cflag = flag;
                    620:                        }
                    621: #ifndef DEBUG
                    622:                }
                    623: #endif
                    624: 
                    625:                /*
                    626:                 * Try replacement
                    627:                 */
                    628: #ifdef DEBUG
                    629:                Tprintf("  Try Replace %s%s with %s%s cost=%d\n",
                    630:                    tokname(&YC[0] , 0 ),
                    631:                    tokname(&YC[0] , 1 ),
                    632:                    charname(acchar , 0 ),
                    633:                    charname(acchar , 1 ),
                    634:                    repcost(YC[0].Yychar, acchar));
                    635: #endif
                    636:                c = repcost(YC[0].Yychar, acchar);
                    637: #ifndef DEBUG
                    638:                if (c < ccost) {
                    639: #endif
                    640:                        c = correct(acchar, 1, repcost(YC[0].Yychar, acchar), repmult, Ps0, Pv0);
                    641: #ifdef DEBUG
                    642:                        if (c < CPRLIMIT || fulltrace)
                    643:                                Eprintf("Cost %2d Replace %s%s with %s%s\n",
                    644:                                        c,
                    645:                                        tokname(&YC[0] , 0 ),
                    646:                                        tokname(&YC[0] , 1 ),
                    647:                                        tokname(&ACtok , 0 ),
                    648:                                        tokname(&ACtok , 1 ));
                    649: #endif
                    650:                        if (c < ccost)
                    651:                                cact = CREPLACE, ccost = c, cchar = acchar, cflag = flag;
                    652: #ifndef DEBUG
                    653:                }
                    654: #endif
                    655:        }
                    656: }
                    657: 
                    658: int    *yCpv;
                    659: char   yyredfail;
                    660: 
                    661: /*
                    662:  * The ntok structure is used to build a
                    663:  * scanner structure for tokens inserted
                    664:  * from the argument "fchar" to "correct" below.
                    665:  */
                    666: static struct yytok ntok;
                    667: 
                    668: /*
                    669:  * Compute the cost of a correction
                    670:  * C is the base cost for it.
                    671:  * Fchar is the first input character from
                    672:  * the current state, NOCHAR if none.
                    673:  * The rest of the inputs come from the array
                    674:  * YC, starting at origin and continuing to the
                    675:  * last character there, YC[yCcnt - 1].Yychar.
                    676:  *
                    677:  * The cost returned is INFINITE if this correction
                    678:  * allows no shifts, otherwise is weighted based
                    679:  * on the number of shifts this allows against the
                    680:  * maximum number possible with the available lookahead.
                    681:  */
                    682: correct(fchar, origin, c, multvec, Ps0, Pv0)
                    683:        register int fchar, c;
                    684:        int origin;
                    685:        char *multvec;
                    686:        int *Ps0, *Pv0;
                    687: {
                    688:        register char *mv;
                    689: 
                    690:        /*
                    691:         * Ps is the top of the parse stack after the most
                    692:         * recent local correctness check.  Loccor returns
                    693:         * NIL when we cannot shift.
                    694:         */
                    695:        register int *ps;
                    696: 
                    697:        yyredfail = 0;
                    698:        /*
                    699:         * Initialize the tip parse and semantic stacks.
                    700:         */
                    701:        ps = Ps0;
                    702:        yytips[0] = *ps;
                    703:        ps--;
                    704:        yytipv[0] = Pv0[0];
                    705:        yCpv = Pv0 - 1;
                    706:        yytipct = 1;
                    707: 
                    708:        /*
                    709:         * Shift while possible.
                    710:         * Adjust cost as necessary.
                    711:         */
                    712:        mv = multvec;
                    713:        do {
                    714:                if (fchar != NOCHAR) {
                    715:                        copy(&ntok, &YC[0], sizeof ntok);
                    716:                        ntok.Yychar = fchar, ntok.Yylval = nullsem(fchar);
                    717:                        fchar = NOCHAR;
                    718:                        ps = loccor(ps, &ntok);
                    719:                } else
                    720:                        ps = loccor(ps, &YC[origin++]);
                    721:                if (ps == NIL) {
                    722:                        if (yyredfail && mv > multvec)
                    723:                                mv--;
                    724:                        c *= *mv;
                    725:                        break;
                    726:                }
                    727:                mv++;
                    728:        } while (*mv != 1);
                    729:        return (c);
                    730: }
                    731: 
                    732: extern int yygo[], yypgo[], yyr1[], yyr2[];
                    733: /*
                    734:  * Local syntactic correctness check.
                    735:  * The arguments to this routine are a
                    736:  * top of stack pointer, ps, and an input
                    737:  * token tok.  Also, implicitly, the contents
                    738:  * of the yytips array which contains the tip
                    739:  * of the stack, and into which the new top
                    740:  * state on the stack will be placed if we shift.
                    741:  *
                    742:  * If we succeed, we return a new top of stack
                    743:  * pointer, else we return NIL.
                    744:  */
                    745: loccor(ps, ntok)
                    746:        int *ps;
                    747:        struct yytok *ntok;
                    748: {
                    749:        register int *p, n;
                    750:        register int nchar;
                    751:        int i;
                    752: 
                    753:        if (ps == NIL)
                    754:                return (NIL);
                    755:        nchar = ntok->Yychar;
                    756:        yyeline = ntok->Yyeline;
                    757: #ifdef DEBUG
                    758:        Tprintf("    Stack ");
                    759:        for (i = yytipct - 1; i >= 0; i--)
                    760:                Tprintf("%d ", yytips[i]);
                    761:        Tprintf("| %d, Input %s%s\n", *ps
                    762:                , charname(nchar , 0 )
                    763:                , charname(nchar , 1 ));
                    764: #endif
                    765:        /*
                    766:         * As in the yacc parser yyparse,
                    767:         * p traces through the action list
                    768:         * and "n" is the information associated
                    769:         * with the action.
                    770:         */
                    771: newstate:
                    772:        p = &yyact[ yypact[yytips[yytipct - 1]+1] ];
                    773: 
                    774: actn:
                    775:        /*
                    776:         * Search the parse actions table
                    777:         * for something useful to do.
                    778:         * While n is non-positive, it is the
                    779:         * arithmetic inverse of the token to be tested.
                    780:         * This allows a fast check.
                    781:         */
                    782:        while ((n = *p++) <= 0)
                    783:                if ((n += nchar) != 0)
                    784:                        p++;
                    785:        switch (n >> 12) {
                    786:                /*
                    787:                 * SHIFT
                    788:                 */
                    789:                case 2:
                    790:                        n &= 07777;
                    791:                        yyredfail = 0;
                    792:                        if (nchar == YID)
                    793:                                yyredfail++;
                    794:                        if (yytipct == YYTIPSIZ) {
                    795: tipover:
                    796: #ifdef DEBUG
                    797:                                Tprintf("\tTIP OVFLO\n");
                    798: #endif
                    799:                                return (NIL);
                    800:                        }
                    801:                        yytips[yytipct] = n;
                    802:                        yytipv[yytipct] = ntok->Yylval;
                    803:                        yytipct++;
                    804: #ifdef DEBUG
                    805:                        Tprintf("\tShift to state %d\n", n);
                    806: #endif
                    807:                        return (ps);
                    808:                /*
                    809:                 * REDUCE
                    810:                 */
                    811:                case 3:
                    812:                        n &= 07777;
                    813:                        if (yyEactr(n, yytipv[yytipct - 1]) == 0) {
                    814: #ifdef DEBUG
                    815:                                Tprintf("\tYyEactr objects: have %s id, want %s id\n", classes[yyidhave], classes[yyidwant]);
                    816: #endif
                    817:                                return (NIL);
                    818:                        }
                    819:                        yyredfail = 0;
                    820:                        i = yyr2[n];
                    821: #ifdef DEBUG
                    822:                        Tprintf("\tReduce, length %d,", i);
                    823: #endif
                    824:                        if (i > yytipct) {
                    825:                                i -= yytipct;
                    826:                                yytipct = 0;
                    827:                                ps -= i;
                    828:                                yCpv -= i;
                    829:                        } else
                    830:                                yytipct -= i;
                    831:                        if (yytipct >= YYTIPSIZ)
                    832:                                goto tipover;
                    833:                        /*
                    834:                         * Use goto table to find next state
                    835:                         */
                    836:                        p = &yygo[yypgo[yyr1[n]]];
                    837:                        i = yytipct ? yytips[yytipct - 1] : *ps;
                    838:                        while (*p != i && *p >= 0)
                    839:                                p += 2;
                    840: #ifdef DEBUG
                    841:                        Tprintf(" new state %d\n", p[1]);
                    842: #endif
                    843:                        yytips[yytipct] = p[1];
                    844:                        yytipct++;
                    845:                        goto newstate;
                    846:                /*
                    847:                 * ACCEPT
                    848:                 */
                    849:                case 4:
                    850: #ifdef DEBUG
                    851:                        Tprintf("\tAccept\n");
                    852: #endif
                    853:                        return (ps);
                    854:                /*
                    855:                 * ERROR
                    856:                 */
                    857:                case 1:
                    858: #ifdef DEBUG
                    859:                        Tprintf("\tError\n");
                    860: #endif
                    861:                        return (0);
                    862:        }
                    863:        panic("loccor");
                    864: }

unix.superglobalmegacorp.com

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