Annotation of coherent/d/bin/yacc/y1.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * LALR-1 parser generator
                      3:  *
                      4:  * the comments previously here have been suppressed since they were
                      5:  * boring
                      6:  */
                      7: #include "yacc.h"
                      8: 
                      9: main(argc,argv)
                     10: char *argv[];
                     11: {
                     12:        options(argc,argv);
                     13:        getfiles();
                     14:        readrules();
                     15:        ntprod();
                     16:        ntderive();
                     17:        listgram();
                     18:        if( nerrors )
                     19:                cleanup(1);
                     20:        ntempty();
                     21:        if( nerrors )
                     22:                cleanup(1);
                     23:        genstates();
                     24:        genslist();
                     25:        sttrans();
                     26:        genlook();
                     27:        go2out();
                     28:        paout();
                     29:        callopt();
                     30:        cleanup(0);
                     31: }
                     32: 
                     33: getfiles()
                     34: {
                     35:        if( gramy==NULL )
                     36:                usage();
                     37:        if( strcmp(gramy,"-")==0 )
                     38:                defin = stdin;
                     39:        else
                     40:                if( (defin = fopen(gramy,"r")) == NULL )
                     41:                        yyerror(!FATAL, "cannot open grammar file %s", gramy);
                     42:        mktemp(acttmp);
                     43:        mktemp(opttmp);
                     44:        if( (actout = fopen(acttmp,"w")) == NULL )
                     45:                yyerror(!FATAL, "cannot create action temp file %s", acttmp);
                     46:        if( (tabout = fopen(ytabc,"w")) == NULL )
                     47:                yyerror(!FATAL, "cannot create output file %s", ytabc);
                     48:        if( (fhdr = fopen(ytabh, "w")) == NULL )
                     49:                yyerror(!FATAL, "cannot create %s", ytabh);
                     50:        if( verbose )
                     51:                if( (listout = fopen(youtput,"w")) == NULL )
                     52:                        yyerror(NLNO, "cannot open listing file %s", youtput);
                     53:        if ((optout = fopen(opttmp, "wb")) == NULL
                     54:        ||  (optout = freopen(opttmp, "rwb", optout)) == NULL)
                     55:                yyerror(NLNO, "open error temp %s", opttmp);
                     56:        if( nerrors )
                     57:                cleanup(2);
                     58: }
                     59: 
                     60: rewopt()
                     61: {
                     62:        fseek(optout, 0L, 0);
                     63: }
                     64: 
                     65: /*
                     66:  * for each non-terminal, generate a list of productions which the
                     67:  * the non terminal derives
                     68:  */
                     69: ntprod()
                     70: {
                     71:        register i;
                     72:        register struct sym *sp;
                     73: 
                     74:        /* first run down the production table, counting references to
                     75:            all the non terminals. */
                     76:        for(i=0; i<nnonterm; i++)
                     77:                ntrmptr[i]->s_nprods = 0;
                     78:        for(i=0; i<nprod; i++)
                     79:                ntrmptr[-prdptr[i]->p_left-NTBASE]->s_nprods++;
                     80:        for(i=0; i<nnonterm; i++)
                     81:                if( ntrmptr[i]->s_nprods==0 )
                     82:                        yyerror(NLNO|!FATAL, "non terminal %s not defined",
                     83:                                ntrmptr[i]->s_name);
                     84:        if( nerrors )
                     85:                cleanup(1);
                     86:        /* now allocate list pointers for each non-terminal */
                     87:        for(i=0; i<nnonterm; i++) {
                     88:                sp = ntrmptr[i];
                     89:                sp->s_prods = (struct prod **)yalloc(sp->s_nprods, sizeof *sp->s_prods);
                     90:                sp->s_nprods = 0; /* il sera recharge a la suite */
                     91:        }
                     92:        /* finally, run down the production table again filling in the
                     93:           list pointers for the corresponding non terminal */
                     94:        for(i=0; i<nprod; i++) {
                     95:                sp = ntrmptr[ -prdptr[i]->p_left-NTBASE ];
                     96:                sp->s_prods[sp->s_nprods++] = prdptr[i];
                     97:        }
                     98: }
                     99: 
                    100: /*
                    101:  * assure that all non-terminals generate a token string
                    102:  * algorithm:
                    103:  *   assume a priori that no non-terminal generates a token string
                    104:  *   if a non terminal contains a production which consists only
                    105:  *      of non-terminals generating a token string, and terminals
                    106:  *   then it generates a token string
                    107:  *   cycle on this until no new non terminals are found
                    108:  *    - a similar procedure applies for finding out which non terminals
                    109:  *      generate the empty string
                    110:  */
                    111: 
                    112: ntderive()
                    113: {
                    114:        register i, j;
                    115:        register struct sym *sp;
                    116:        register struct prod *pp;
                    117:        int *ip;
                    118:        int changed;
                    119: 
                    120:        for(i=0; i<nnonterm; i++)
                    121:                ntrmptr[i]->s_flags &= ~DERIV;
                    122:        do {
                    123:                changed = 0;
                    124:                for(i=0; i<nnonterm; i++) {
                    125:                        sp = ntrmptr[i];
                    126:                        if( sp->s_flags&DERIV )
                    127:                                continue;
                    128:                        for(j=0; j<sp->s_nprods; j++) {
                    129:                                pp = sp->s_prods[j];
                    130:                                for(ip=pp->p_right; *ip!=-1; ip++)
                    131:                                        if( *ip>=NTBASE &&
                    132:                                            (ntrmptr[*ip-NTBASE]->s_flags&DERIV)==0 )
                    133:                                                break;
                    134:                                if( *ip == -1 ) {
                    135:                                        sp->s_flags |= DERIV;
                    136:                                        changed++;
                    137:                                        break;
                    138:                                }
                    139:                        }
                    140:                }
                    141:        } while( changed );
                    142:        for(i=0; i<nnonterm; i++)
                    143:                if( (ntrmptr[i]->s_flags&DERIV)==0 )
                    144:                        yyerror(NLNO|!FATAL, "nonterminal %s derives no token string",
                    145:                                ntrmptr[i]->s_name);
                    146:        if( nerrors )
                    147:                cleanup(1);
                    148: }
                    149: 
                    150: /*
                    151:  * find out which non-terminals derive the empty string
                    152:  * algorithm is simple
                    153:  *  if the non-terminal has a production deriving the empty string
                    154:  *  it derives the empty string trivially
                    155:  *  otherwise if it consists only of productions which can derive the
                    156:  *  empty string, then it derives the empty string as well
                    157:  */
                    158: 
                    159: ntempty()
                    160: {
                    161:        register *kp;
                    162:        register struct prod **ppp;
                    163:        register struct sym *sp;
                    164:        int i, changed;
                    165: 
                    166:        for(i=0; i<nnonterm; i++) 
                    167:                ntrmptr[i]->s_flags &= ~DERIV;
                    168:        do {
                    169:                changed = 0;
                    170:                for(i=0; i<nnonterm; i++) {
                    171:                        sp = ntrmptr[i];
                    172:                        if( sp->s_flags&DERIV )
                    173:                                continue;
                    174:                        for(ppp=sp->s_prods; ppp<&sp->s_prods[sp->s_nprods]; ppp++) {
                    175:                                for(kp = (*ppp)->p_right; *kp!=-1; kp++ )
                    176:                                        if( *kp<NTBASE ||
                    177:                                            (ntrmptr[*kp-NTBASE]->s_flags&DERIV)==0 )
                    178:                                                break;
                    179:                                if( *kp==-1 ) {
                    180:                                        sp->s_flags |= DERIV;
                    181:                                        changed++;
                    182:                                        break;
                    183:                                }
                    184:                        }
                    185:                }
                    186:        } while( changed );
                    187: }
                    188: 
                    189:        /* some useful local variables */
                    190: static newgen; /* communication between genstates and install */
                    191: static char *ntp;      /* buffer for use by chklhs */
                    192: 
                    193: genstates()
                    194: {
                    195:        extern struct sitem  *nititem;
                    196:        register k, sno;
                    197:        int i;
                    198:        struct tgo tgo;
                    199:        struct ntgo ntgo;
                    200: 
                    201:        /* initialize the list of states associated with each nt to empty */
                    202:        if( verbose )
                    203:                fprintf(listout, "\nAutomaton state description:\n\n");
                    204:        for(i=0; i<nnonterm; i++) 
                    205:                ntrmptr[i]->s_nstates = 0;
                    206:        ntp = yalloc(nnonterm, sizeof *ntp); /* array used by "install" */
                    207:        nititem->i_nitems = 1;
                    208:        nititem->i_items[0] = prdptr[0]->p_right;
                    209:        closure();
                    210:        install();
                    211:        i = 0;
                    212:        do {
                    213:                newgen = 0; /* newgen is flagged by the install routine */
                    214:                for(; i<nstates; i++) {
                    215:                        fwrite(&i, sizeof i, 1, optout); /* sync number */
                    216:                        states[i].s_tgo = 0;
                    217:                        for(k=0; k<nterm; k++)
                    218:                                if( (sno = go2(items[i], k)) >= 0 ) {
                    219:                                        states[i].s_tgo++;
                    220:                                        tgo.tg_st = sno;
                    221:                                        tgo.tg_trm = k;
                    222:                                        fwrite(&tgo, sizeof tgo, 1, optout);
                    223:                                }
                    224:                        states[i].s_ntgo = 0;
                    225:                        for(k=0; k<nnonterm; k++)
                    226:                                if( (sno = go2(items[i], k+NTBASE)) >= 0 ) {
                    227:                                        states[i].s_ntgo++;
                    228:                                        ntgo.ng_st = sno;
                    229:                                        ntgo.ng_nt = k+NTBASE;
                    230:                                        ntgo.ng_rel = NULL;     /* MWC DSC */
                    231:                                        fwrite(&ntgo, sizeof ntgo, 1, optout);
                    232:                                }
                    233:                        states[i].s_nred = 0;
                    234:                        for(k=0; k<items[i]->i_nitems; k++)
                    235:                                if( *(items[i]->i_items[k]) == -1 )
                    236:                                        states[i].s_nred++;
                    237:                        states[i].s_tgos = states[i].s_ntgos =
                    238:                            states[i].s_reds = NULL;            /* MWC DSC */
                    239:                }
                    240:        } while( newgen );
                    241:        free(ntp);
                    242: }
                    243: 
                    244: /*
                    245:  * generate the closure of a state (found in global variable `nititem'
                    246:  * Algorithm:
                    247:  *  - look at every non terminal's after every '.' item pointer
                    248:  *  - add all the productions associated with this non-terminal
                    249:  *    to the state (the '.' being at the beginning of the rhs) unless
                    250:  *    they are already there. It suffices to test if one of them is
                    251:  *    already there, since productions are added to the closure according
                    252:  *    according to their lhs
                    253:  *    repeat this procedure until no new items are added.
                    254:  *
                    255:  *    "It can be shown that (this procedure) computes exactly the sets
                    256:  *     of items that are valid for gamma X [Aho and Ullmann 1972]"
                    257:  */
                    258: 
                    259: closure()
                    260: {
                    261:        register j, **ipp;
                    262:        register struct prod **ppp;
                    263:        struct sitem *itp;
                    264:        struct sym *sp;
                    265:        int i, changed, nt;
                    266: 
                    267:        itp = nititem;
                    268:        for(i=0; i<nnonterm; i++)
                    269:                ntrmptr[i]->s_flags &= ~CPRES;
                    270:        for(i=0; i<itp->i_nitems; i++)
                    271:                /* kludge: requires p.left & p.rights contigouuous */
                    272:                if( (nt = *(itp->i_items[i]-1)) < 0 )   /* ARE THEY???? */
                    273:                        ntrmptr[-nt-NTBASE]->s_flags |= CPRES;
                    274:        do {
                    275:                changed = 0;
                    276:                for(i=0; i<itp->i_nitems; i++) {
                    277:                        nt = *(itp->i_items[i]);
                    278:                        if( nt>=NTBASE && ((sp = ntrmptr[nt-NTBASE])->s_flags
                    279:                            &CPRES)==0 ) {
                    280:                                sp->s_flags |= CPRES;
                    281:                                changed = 1;
                    282:                                ppp = sp->s_prods;
                    283:                                ipp = &itp->i_items[itp->i_nitems];
                    284:                                itp->i_nitems += j = sp->s_nprods;
                    285:                                bounded(itp->i_nitems, MAXITEM, "items in state");
                    286:                                do
                    287:                                        *ipp++ = (*ppp++)->p_right;
                    288:                                while( --j );
                    289:                        }
                    290:                }
                    291:        } while( changed );
                    292: }
                    293: 
                    294: /*
                    295:  * add the state in `nititem' to the collection of sets of accessible
                    296:  * items, returning the state pointer
                    297:  * the real work is concerned with finding out whether the set is there
                    298:  * already or not
                    299:  * we sort the items in nititem, compare with every set in "items",
                    300:  * and return the old state pointer if its there already
                    301:  */
                    302: install()
                    303: {
                    304:        register n, **ipp1, **ipp2;
                    305:        struct sitem *itp, *itp1;
                    306:        int i;
                    307: 
                    308:        itp = nititem;
                    309:        bubble(itp->i_items, itp->i_nitems);
                    310:        for(i=0; i<nstates; i++) {
                    311:                itp1 = items[i];
                    312:                if( (n = itp->i_nitems) != itp1->i_nitems )
                    313:                        continue;
                    314:                ipp1 = itp->i_items;
                    315:                ipp2 = itp1->i_items;
                    316:                do
                    317:                        if( *ipp1++ != *ipp2++ )
                    318:                                break;
                    319:                while( --n );
                    320:                if( n==0 )
                    321:                        break;
                    322:        }
                    323:        if( i==nstates ) {
                    324:                bounded(nstates,maxstates,"states");
                    325:                chklhs();
                    326:                itp1 = (struct sitem *)yalloc(1, sizeof *itp1 + itp->i_nitems *
                    327:                                sizeof itp->i_items[0]);
                    328:                copyb(itp, itp1, sizeof *itp1 + itp->i_nitems *
                    329:                        sizeof itp->i_items[0]);
                    330:                newgen = 1;
                    331:                items[nstates] = itp1;
                    332:                if( verbose )
                    333:                        prstate(nstates, listout);
                    334:                nstates++;
                    335:        }
                    336:        return( i );
                    337: }
                    338: 
                    339: go2(itp, tk)
                    340: struct sitem *itp;
                    341: int tk;
                    342: {
                    343:        register **ipp1, **ipp, n;
                    344: 
                    345:        nititem->i_nitems = 0;
                    346:        ipp1 = nititem->i_items;
                    347:        ipp = itp->i_items;
                    348:        n = itp->i_nitems;
                    349:        do {
                    350:                if( **ipp == tk ) {
                    351:                        nititem->i_nitems++;
                    352:                        *ipp1++ = *ipp+1;
                    353:                }
                    354:                ipp++;
                    355:        } while( --n );
                    356:        if( nititem->i_nitems==0 )
                    357:                return( -1 );
                    358:        else {
                    359:                closure();
                    360:                return( install() );
                    361:        }
                    362: }
                    363: 
                    364: chklhs()
                    365: {
                    366:        register n, **ipp;
                    367:        register char *cp;
                    368:        int nt;
                    369: 
                    370:        n = nnonterm;
                    371:        cp = ntp;
                    372:        do *cp++ = 0; while( --n );
                    373:        ipp = nititem->i_items;
                    374:        n = nititem->i_nitems;
                    375:        cp = ntp;
                    376:        do
                    377:                if( (nt = (*ipp++) [-1]) < 0 )
                    378:                        cp[ -nt-NTBASE ] = 1;
                    379:        while( --n );
                    380:        for(n=0; n<nnonterm; n++)
                    381:                if( cp[n] )
                    382:                        ntrmptr[n]->s_nstates++;
                    383: }
                    384: 
                    385: /*
                    386:  * for each nonterminal generate a list of items
                    387:  * containing items with all of the rhs of a production
                    388:  * whose lhs is the non-terminal after the '.'
                    389:  */
                    390: genslist()
                    391: {
                    392:        register struct sym *sp;
                    393:        register i, j;
                    394:        int *ip;
                    395:        int *stp;
                    396: 
                    397:        for(i=j=0; i<nnonterm; i++)
                    398:                j += ntrmptr[i]->s_nstates;
                    399:        stp = (int *)yalloc(j, sizeof *stp);
                    400:        for(i=0; i<nnonterm; i++) {
                    401:                sp = ntrmptr[i];
                    402:                sp->s_states = stp;
                    403:                stp += sp->s_nstates;
                    404:                sp->s_nstates = 0; /* a recharcher dans le boucle suivant */
                    405:        }
                    406:        for(i=0; i<nnonterm; i++) {
                    407:                sp = ntrmptr[i];
                    408:                ip = sp->s_prods[0]->p_right; /* pick an item, any item */
                    409:                for(j=0; j<nstates; j++)
                    410:                        if( pitem(ip, items[j]) )
                    411:                                sp->s_states[sp->s_nstates++] = j;
                    412:        }
                    413: }
                    414: 
                    415: /* binary search for an item in a state */
                    416: 
                    417: pitem(ip,itp)
                    418: int *ip;
                    419: register struct sitem *itp;
                    420: {
                    421:        register int *el, nb;
                    422:        int ub, lb;
                    423: 
                    424:        lb = 0;
                    425:        ub = itp->i_nitems-1;
                    426:        do {
                    427:                nb = (ub+lb) / 2;
                    428:                if( (el = itp->i_items[nb]) < ip )
                    429:                        lb = nb+1;
                    430:                else if( el > ip )
                    431:                        ub = nb-1;
                    432:                else
                    433:                        return(1);
                    434:        } while( lb<=ub );
                    435:        return(0);
                    436: }
                    437: 
                    438: /* 
                    439:  * linear insertion sort really.
                    440:  * the decision not to use bubbbbbbbbbbbble sort is thanks to Randall
                    441:  * and to his cs240b notes
                    442:  * (p.s. -- i hate sorting)
                    443:  */
                    444: 
                    445: bubble(ipp,n)
                    446: register **ipp;
                    447: int n;
                    448: {
                    449:        register **min, **jpp;
                    450:        int m, *t;                      /* MWC DSC */
                    451: 
                    452:        do {
                    453:                m = n;
                    454:                min = jpp = ipp;
                    455:                do {
                    456:                        if( *jpp < *min )
                    457:                                min = jpp;
                    458:                        jpp++;
                    459:                } while( --m );
                    460:                t = *min;
                    461:                *min = *ipp;
                    462:                *ipp++ = t;
                    463:        } while( --n );
                    464: }
                    465: 
                    466: copyb(sp,dp,n)
                    467: register char *sp, *dp;
                    468: register n;
                    469: {
                    470:        do
                    471:                *dp++ = *sp++;
                    472:        while( --n );
                    473: }
                    474: 
                    475: cleanup(err)
                    476: {
                    477:        unlink(acttmp);
                    478:        unlink(opttmp);
                    479:        stats();
                    480:        exit(err);
                    481: }
                    482: 
                    483: stats()
                    484: {
                    485:        extern nsrconf, nrrconf;
                    486: 
                    487:        if( !pstat && (nsrconf || nrrconf) ) {
                    488:                if( nrrconf ) {
                    489:                        fprintf(stderr, "%d R/R conflict", nrrconf);
                    490:                        if( nrrconf != 1 )
                    491:                                fprintf(stderr, "s");
                    492:                }
                    493:                if( nrrconf && nsrconf )
                    494:                        fprintf(stderr, " and ");
                    495:                if( nsrconf ) {
                    496:                        fprintf(stderr, "%d S/R conflict", nsrconf);
                    497:                        if( nsrconf != 1)
                    498:                                fprintf(stderr, "s");
                    499:                }
                    500:                fprintf(stderr, "\n");
                    501:        }
                    502:        if( verbose )
                    503:                stat1(listout);
                    504:        if( pstat )
                    505:                stat1(stdout);
                    506: }
                    507: 
                    508: 
                    509: stat1(f)
                    510: FILE *f;
                    511: {
                    512:        extern nsrconf, nrrconf, yygodef, yypact, yyredns;
                    513:        extern ndupgos, ndupacts;
                    514:        extern yydefact;
                    515: 
                    516:        fprintf(f, "Statistics:\n");
                    517:        fprintf(f, "%d/%d tokens, %d/%d non terminals\n", nterm, maxterm,
                    518:                nnonterm, maxnterm);
                    519:        fprintf(f, "%d/%d productions, %d/%d states\n", nprod, maxprod,
                    520:                nstates, maxstates);
                    521:        fprintf(f, "%d goto entries; %d saved by goto default\n",
                    522:                yyredns, yygodef);
                    523:        fprintf(f, "%d parsing actions; %d saved by default\n",
                    524:                yypact, yydefact);
                    525:        fprintf(f, "%d duplicated goto entries saved; %d actions\n",
                    526:                ndupgos, ndupacts);
                    527:        if( nsrconf || nrrconf )
                    528:                fprintf(f, "%d R/R conflicts, %d S/R conflicts\n",
                    529:                        nrrconf, nsrconf);
                    530: }
                    531: 
                    532: char *
                    533: yalloc(n, s)
                    534: {
                    535:        register char *cp;
                    536: 
                    537:        if( cp = calloc(n, s) )
                    538:                return(cp);
                    539:        yyerror(NLNO|FATAL, "storage overflow (requested %d)\n", n*s);
                    540: }
                    541: 
                    542: /*
                    543:  * transform the state representation
                    544:  */
                    545: 
                    546: sttrans()
                    547: {
                    548:        register j, k;
                    549:        int i, totgo, tontgo;
                    550:        register struct state *stp;
                    551:        struct tgo *tgp;
                    552:        struct ntgo *ngp;
                    553: 
                    554:        /* a la pubelle !! */
                    555:        for(i=0; i<nstates; i++)
                    556:                free(items[i]);
                    557:        free(items);
                    558: 
                    559:        if( yydebug )
                    560:                fprintf(listout,"Automaton transition graph:\n\n");
                    561:        for(i=totgo=0; i<nstates; i++) 
                    562:                totgo += states[i].s_tgo;
                    563:        for(i=tontgo=0; i<nstates; i++)
                    564:                tontgo += states[i].s_ntgo;
                    565:        tgp = (struct tgo *)yalloc(totgo, sizeof *tgp);
                    566:        ngp = (struct ntgo *)yalloc(tontgo, sizeof *ngp);
                    567:        rewopt();
                    568: 
                    569:        for(j=0; j<nstates; j++) {
                    570:                if( yydebug )
                    571:                        fprintf(listout, "State %d:\n\n", j);
                    572:                stp = &states[j];
                    573:                if( fread(&i, sizeof i, 1, optout)!=1 || i!=j )
                    574:                        yyerror(NLNO|FATAL, "temp file i/o error");
                    575:                fread(tgp, sizeof *tgp, stp->s_tgo, optout);
                    576:                stp->s_tgos = tgp;
                    577:                stp->s_ntgos = ngp;
                    578:                if( yydebug )
                    579:                        for(k=0; k<stp->s_tgo; k++)
                    580:                                fprintf(listout, "\t%s\t%d\n", 
                    581:                                    ptosym(stp->s_tgos[k].tg_trm),
                    582:                                    stp->s_tgos[k].tg_st);
                    583:                fread(ngp, sizeof *ngp, stp->s_ntgo, optout);
                    584:                if( yydebug )
                    585:                        for(k=0; k<stp->s_ntgo; k++)
                    586:                                fprintf(listout, "\t%s\t%d\n",
                    587:                                    ptosym(stp->s_ntgos[k].ng_nt),
                    588:                                    stp->s_ntgos[k].ng_st);
                    589:                tgp += stp->s_tgo;
                    590:                ngp += stp->s_ntgo;
                    591:        }
                    592: }
                    593: 

unix.superglobalmegacorp.com

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