Annotation of 40BSD/cmd/pxp/yyrecover.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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