Annotation of researchv10dc/cmd/pascal/pxp/yyrecover.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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