1*47968Sbostic /*- 2*47968Sbostic * Copyright (c) 1979 The Regents of the University of California. 3*47968Sbostic * All rights reserved. 4*47968Sbostic * 5*47968Sbostic * %sccs.include.proprietary.c% 619570Smckusick */ 719570Smckusick 819570Smckusick #ifndef lint 9*47968Sbostic char copyright[] = 10*47968Sbostic "@(#) Copyright (c) 1979 The Regents of the University of California.\n\ 11*47968Sbostic All rights reserved.\n"; 12*47968Sbostic #endif /* not lint */ 1319570Smckusick 14*47968Sbostic #ifndef lint 15*47968Sbostic static char sccsid[] = "@(#)ey1.c 5.3 (Berkeley) 04/12/91"; 16*47968Sbostic #endif /* not lint */ 17*47968Sbostic 1819570Smckusick # include "ey.h" 1919570Smckusick /* * * * * e y a c c * * * * */ 2019570Smckusick 2119570Smckusick /**** NB ----- 2219570Smckusick * 2319570Smckusick * This version of yacc, known as "eyacc" has been slightly but 2419570Smckusick * importantly modified to allow error recovery in the UNIX Pascal 2519570Smckusick * translator "pi" and also in "pix". 2619570Smckusick * 2719570Smckusick * Changes here include: 2819570Smckusick * 2919570Smckusick * 1) Enumeration of test actions when "error" is an input token. 3019570Smckusick * 3119570Smckusick * 2) Change to the encoding of the action entries. Test entries 3219570Smckusick * are encoded as the arithmetic inverse of the symbol being tested 3319570Smckusick * for. This is an optimization that makes the parser run at the 3419570Smckusick * same speed even though, with error productions and enumerated 3519570Smckusick * lookaheads, it would normally be much slower. Of course the 3619570Smckusick * same thing could be done to the regular yacc... 3719570Smckusick * 3819570Smckusick * 3) Different table sizes 3919570Smckusick * 4019570Smckusick * 4) Recognizes form feeds 4119570Smckusick * 4219570Smckusick * 5) Also most of the numbers for the sizes of the tables have been 4319570Smckusick * increased, to an extent to allow for "eyacc"ing of the Pascal grammar 4419570Smckusick * and of a grammar which I have for "EUCLID". 4519570Smckusick * 4619570Smckusick * There seem to be subtle dependencies between the various magic 4719570Smckusick * numbers... I found some of them but to be safe most of the limits 4819570Smckusick * are very generous... for this reason "eyacc" will most likely 4919570Smckusick * have to run separate i/d... no matter. 5019570Smckusick * 5119570Smckusick * Bill Joy 5219570Smckusick * Computer Science Division 5319570Smckusick * EECS Department 5419570Smckusick * University of California, Berkeley 5519570Smckusick * Berkeley, California 94704 5619570Smckusick * 5719570Smckusick * Office: (415) 642-4948 5819570Smckusick * Home: (415) 524-4510 5919570Smckusick ****/ 6019570Smckusick 6119570Smckusick /* features to be fixed up ... 6219570Smckusick 6319570Smckusick *** Print estimate of total space needed for parser 6419570Smckusick *** Either list inputs on y.output, or list empty prdn's in states 6519570Smckusick *** Mention nonterms not used (or, rules. not reduced) as nonfatal error 6619570Smckusick *** Output states where conflicts were found by default on y.output 6719570Smckusick *** Engage in newspeak: production=>grammar rules, term=>token, etc. 6819570Smckusick *** handle # define, #ifdef, etc., in yacc actions, %{ %} 6919570Smckusick */ 7019570Smckusick 7119570Smckusick /* new features to be added 7219570Smckusick 7319570Smckusick *** reductions by single productions ( by request ) 7419570Smckusick *** follow sets for start symbol 7519570Smckusick *** option to only do slr(1) 7619570Smckusick *** easily changed array names on output 7719570Smckusick *** allocate core, rather than predefined 7819570Smckusick *** input controlled by a grammar 7919570Smckusick *** support multiple choices for conflicts 8019570Smckusick *** better conflict diagnostics 8119570Smckusick */ 8219570Smckusick 8319570Smckusick extern char *symnam(); 8419570Smckusick 8519570Smckusick main(argc,argv) int argc; char *argv[]; { 8619570Smckusick auto int n; 8719570Smckusick 8819570Smckusick setup(argc,argv); /* initialize and read productions */ 8919570Smckusick tbitset = (nterms+16)/16; 9019570Smckusick cpres(); /* make table of which productions yield a given nonterminal */ 9119570Smckusick cempty(); /* make a table of which nonterminals can match the empty string */ 9219570Smckusick cpfir(); /* make a table of e free first lists */ 9319570Smckusick stagen(); /* generate the states */ 9419570Smckusick output(); /* write the states and the tables */ 9519570Smckusick go2out(); 9619570Smckusick summary(); 9735693Sbostic exit(0); 9819570Smckusick } 9919570Smckusick 10019570Smckusick settty() 10119570Smckusick /* sets the output file to y.output */ 10219570Smckusick { 10319570Smckusick cflush( foutput ); /* a bit of a cheat */ 10419570Smckusick cout = foutput; 10519570Smckusick } 10619570Smckusick 10719570Smckusick settab(){ /* sets the output file to y.tab.c */ 10819570Smckusick 10919570Smckusick cflush( ftable ); 11019570Smckusick cout = ftable; 11119570Smckusick } 11219570Smckusick 11319570Smckusick char *chcopy( p, q ) char *p, *q; { 11419570Smckusick /* copies string q into p, returning next free char ptr */ 11519570Smckusick while( *p = *q++ ) ++p; 11619570Smckusick return( p ); 11719570Smckusick } 11819570Smckusick 11919570Smckusick char *writem(pp) struct item *pp; { /* creates output string for item pointed to by pp */ 12019570Smckusick int i,*p; 12119570Smckusick static char sarr[100]; 12219570Smckusick char *q; 12319570Smckusick 12419570Smckusick for( p=pp->pitem; *p>0 ; ++p ) ; 12519570Smckusick p = prdptr[-*p]; 12619570Smckusick q = chcopy( sarr, nontrst[*p-NTBASE].name ); 12719570Smckusick q = chcopy( q, " : " ); 12819570Smckusick 12919570Smckusick for(;;){ 13019570Smckusick *q++ = ++p==(pp->pitem) ? '_' : ' '; 13119570Smckusick if((i = *p) <= 0) break; 13219570Smckusick q = chcopy( q, symnam(i) ); 13319570Smckusick } 13419570Smckusick 13519570Smckusick *q = '\0' ; 13619570Smckusick return( sarr ); 13719570Smckusick } 13819570Smckusick 13919570Smckusick char *symnam(i){ /* return a pointer to the name of symbol i */ 14019570Smckusick char *cp; 14119570Smckusick 14219570Smckusick cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : trmset[i].name ; 14319570Smckusick if( *cp == ' ' ) ++cp; 14419570Smckusick return( cp ); 14519570Smckusick } 14619570Smckusick 14719570Smckusick summary(){ /* output the summary on the tty */ 14819570Smckusick 14919570Smckusick int i, s, *pn; 15019570Smckusick 15119570Smckusick 15219570Smckusick if( !rflag ){ 15319570Smckusick settab(); 15419570Smckusick fprintf( cout , "\nint nterms %d;",nterms); 15519570Smckusick fprintf( cout , "\nint nnonter %d;", nnonter); 15619570Smckusick fprintf( cout , "\nint nstate %d;", nstate); 15719570Smckusick fprintf( cout , "\nchar *yysterm[] {"); 15819570Smckusick for (i=1;i<=nterms;i++) if( trmset[i].value >= 0400 ) fprintf( cout , "\n\"%s\",",symnam(i)); 15919570Smckusick fprintf( cout , "\n0 };\n" ); 16019570Smckusick fprintf( cout , "\nchar *yysnter[] {"); 16119570Smckusick for (i=0;i<nnonter;i++) fprintf( cout , "\n\"%s\",",nontrst[i].name); 16219570Smckusick fprintf( cout , "\n\"%s\" };\n",nontrst[nnonter].name); 16319570Smckusick } 16419570Smckusick 16519570Smckusick settty(); 16619570Smckusick fprintf( cout , "\n%d/%d terminals, %d/%d nonterminals\n", nterms, tlim, 16719570Smckusick nnonter, ntlim ); 16819570Smckusick fprintf( cout , "%d/%d grammar rules, %d/%d states\n", nprod, prdlim, nstate, stsize ); 16919570Smckusick fprintf( cout , "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf ); 17019570Smckusick pn = (int *)pstate[nstate+1]; 17119570Smckusick fprintf( cout , "%d/%d working sets used\n", zzcwset, wssize ); 17219570Smckusick fprintf( cout , "memory: states,etc. %d/%d, parser %d/%d\n", pn-mem0, memsiz, 17319570Smckusick memact, actsiz ); 17419570Smckusick fprintf( cout , "%d/%d distinct lookahead sets\n", nlset, lsetsz ); 17519570Smckusick fprintf( cout , "%d extra closures\n", zzclose - 2*nstate ); 17619570Smckusick fprintf( cout , "%d action entries\n", zzacent ); 17719570Smckusick fprintf( cout , "%d action entries saved through merging %d states\n",zzacsave,zznsave); 17819570Smckusick fprintf( cout , "%d goto entries\n", zzgoent ); 17919570Smckusick fprintf( cout , "%d entries saved by goto default\n", zzgobest ); 18019570Smckusick fprintf( cout , "%d lookahead sets saved\n", savedlook); 18119570Smckusick if( zzsrconf!=0 || zzrrconf!=0 ){ 18219570Smckusick cflush( errfileno ); 18319570Smckusick cout = errfileno; 18419570Smckusick fprintf( cout , "\nconflicts: "); 18519570Smckusick if( zzsrconf )fprintf( cout , "%d shift/reduce" , zzsrconf ); 18619570Smckusick if( zzsrconf && zzrrconf )fprintf( cout , ", " ); 18719570Smckusick if( zzrrconf )fprintf( cout , "%d reduce/reduce" , zzrrconf ); 18819570Smckusick fprintf( cout , "\n" ); 18919570Smckusick } 19019570Smckusick } 19119570Smckusick 19219570Smckusick error(s,a1){ /* write out error comment */ 19319570Smckusick 19419570Smckusick int c; 19519570Smckusick ++nerrors; 19619570Smckusick cflush( errfileno ); 19719570Smckusick cout = errfileno; /* set output to tty */ 19819570Smckusick fprintf( cout , "\n fatal error: "); 19919570Smckusick fprintf( cout , s,a1); 20019570Smckusick fprintf( cout , ", line %d\n", lineno ); 20119570Smckusick if( !fatfl ) return; 20219570Smckusick summary(); 20319570Smckusick cexit(1); 20419570Smckusick } 20519570Smckusick 20619570Smckusick arrset(s) char s[]; { 20719570Smckusick fprintf( cout , "\nint %s[] {0", s ); 20819570Smckusick arrndx = 1; 20919570Smckusick } 21019570Smckusick 21119570Smckusick arrval(n){ 21219570Smckusick fprintf( cout , ",%d",n); 21319570Smckusick if( (++arrndx%10) == 0 ) fprintf( cout , "\n"); 21419570Smckusick } 21519570Smckusick 21619570Smckusick arrdone(){ 21719570Smckusick fprintf( cout , ",-1};\n"); 21819570Smckusick } 21919570Smckusick 22019570Smckusick copy(v) char *v; { /* copy ctokn to v */ 22119570Smckusick char *p; 22219570Smckusick 22319570Smckusick p=ctokn; 22419570Smckusick while( *v++ = *p++ ); 22519570Smckusick } 22619570Smckusick 22719570Smckusick compare(v) char *v; { /* compare ctokn with v */ 22819570Smckusick char *p; 22919570Smckusick 23019570Smckusick for( p=ctokn; ; ++p ){ 23119570Smckusick if( *p != *v++ ) return( 0 ); 23219570Smckusick if( *p == 0 ) return(1); 23319570Smckusick } 23419570Smckusick } 23519570Smckusick 23619570Smckusick int *yalloc(n){ /* allocate n+1 words from vector mem */ 23719570Smckusick int *omem; 23819570Smckusick omem = mem; 23919570Smckusick mem += n+1; 24019570Smckusick if(mem-mem0 >= memsiz) error("memory overflow"); 24119570Smckusick return(omem); 24219570Smckusick } 24319570Smckusick 24419570Smckusick aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */ 24519570Smckusick int i; 24619570Smckusick for( i=0; i<n; ++i ) v[i] = c; 24719570Smckusick } 24819570Smckusick 24919570Smckusick UNION( a, b, c ) int *a, *b, *c; { 25019570Smckusick /* set a to the UNION of b and c */ 25119570Smckusick /* a may equal b */ 25219570Smckusick /* return 1 if c is not a subset of b, 0 otherwise */ 25319570Smckusick 25419570Smckusick _REGISTER int i, x, sub; 25519570Smckusick 25619570Smckusick sub = 0; 25719570Smckusick for( i=0; i<tbitset; ++i ){ 25819570Smckusick x = b[i] | c[i]; 25919570Smckusick if( x != b[i] ) sub=1; 26019570Smckusick a[i] = x; 26119570Smckusick } 26219570Smckusick return( sub ); 26319570Smckusick } 26419570Smckusick 26519570Smckusick prlook( p ) struct looksets *p;{ 26619570Smckusick int j, *pp; 26719570Smckusick pp = p->lset; 26819570Smckusick if( pp == 0 ) fprintf( cout , "\tNULL"); 26919570Smckusick else { 27019570Smckusick fprintf( cout , " { " ); 27119570Smckusick for( j=1; j<=nterms; ++j ){ 27219570Smckusick if( (pp[j>>4]>>(j&017) )&01 != 0 ) fprintf( cout , "%s ", symnam(j) ); 27319570Smckusick } 27419570Smckusick fprintf( cout , "}" ); 27519570Smckusick } 27619570Smckusick } 277