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

unix.superglobalmegacorp.com

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