147968Sbostic /*-
2*62087Sbostic * Copyright (c) 1979, 1993
3*62087Sbostic * The Regents of the University of California. All rights reserved.
447968Sbostic *
547968Sbostic * %sccs.include.proprietary.c%
619570Smckusick */
719570Smckusick
819570Smckusick #ifndef lint
9*62087Sbostic static char copyright[] =
10*62087Sbostic "@(#) Copyright (c) 1979, 1993\n\
11*62087Sbostic The Regents of the University of California. All rights reserved.\n";
1247968Sbostic #endif /* not lint */
1319570Smckusick
1447968Sbostic #ifndef lint
15*62087Sbostic static char sccsid[] = "@(#)ey1.c 8.1 (Berkeley) 06/06/93";
1647968Sbostic #endif /* not lint */
1747968Sbostic
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
main(argc,argv)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
settty()10019570Smckusick settty()
10119570Smckusick /* sets the output file to y.output */
10219570Smckusick {
10319570Smckusick cflush( foutput ); /* a bit of a cheat */
10419570Smckusick cout = foutput;
10519570Smckusick }
10619570Smckusick
settab()10719570Smckusick settab(){ /* sets the output file to y.tab.c */
10819570Smckusick
10919570Smckusick cflush( ftable );
11019570Smckusick cout = ftable;
11119570Smckusick }
11219570Smckusick
chcopy(p,q)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
writem(pp)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
symnam(i)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
summary()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
error(s,a1)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
arrset(s)20619570Smckusick arrset(s) char s[]; {
20719570Smckusick fprintf( cout , "\nint %s[] {0", s );
20819570Smckusick arrndx = 1;
20919570Smckusick }
21019570Smckusick
arrval(n)21119570Smckusick arrval(n){
21219570Smckusick fprintf( cout , ",%d",n);
21319570Smckusick if( (++arrndx%10) == 0 ) fprintf( cout , "\n");
21419570Smckusick }
21519570Smckusick
arrdone()21619570Smckusick arrdone(){
21719570Smckusick fprintf( cout , ",-1};\n");
21819570Smckusick }
21919570Smckusick
copy(v)22019570Smckusick copy(v) char *v; { /* copy ctokn to v */
22119570Smckusick char *p;
22219570Smckusick
22319570Smckusick p=ctokn;
22419570Smckusick while( *v++ = *p++ );
22519570Smckusick }
22619570Smckusick
compare(v)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
yalloc(n)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
aryfil(v,n,c)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
UNION(a,b,c)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