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