xref: /csrg-svn/old/yacc/y2.c (revision 10933)
1*10933Srrh #ifndef lint
2*10933Srrh static char sccsid[] = "@(#)y2.c	4.1	(Berkeley)	02/11/83";
3*10933Srrh #endif not lint
4*10933Srrh 
5*10933Srrh # include "dextern"
6*10933Srrh # define IDENTIFIER 257
7*10933Srrh # define MARK 258
8*10933Srrh # define TERM 259
9*10933Srrh # define LEFT 260
10*10933Srrh # define RIGHT 261
11*10933Srrh # define BINARY 262
12*10933Srrh # define PREC 263
13*10933Srrh # define LCURLY 264
14*10933Srrh # define C_IDENTIFIER 265  /* name followed by colon */
15*10933Srrh # define NUMBER 266
16*10933Srrh # define START 267
17*10933Srrh # define TYPEDEF 268
18*10933Srrh # define TYPENAME 269
19*10933Srrh # define UNION 270
20*10933Srrh # define ENDFILE 0
21*10933Srrh 
22*10933Srrh 	/* communication variables between various I/O routines */
23*10933Srrh 
24*10933Srrh char *infile;	/* input file name */
25*10933Srrh int numbval;	/* value of an input number */
26*10933Srrh char tokname[NAMESIZE];	/* input token name */
27*10933Srrh 
28*10933Srrh 	/* storage of names */
29*10933Srrh 
30*10933Srrh char cnames[CNAMSZ];	/* place where token and nonterminal names are stored */
31*10933Srrh int cnamsz = CNAMSZ;	/* size of cnames */
32*10933Srrh char * cnamp = cnames;	/* place where next name is to be put in */
33*10933Srrh int ndefout = 3;  /* number of defined symbols output */
34*10933Srrh 
35*10933Srrh 	/* storage of types */
36*10933Srrh int ntypes;	/* number of types defined */
37*10933Srrh char * typeset[NTYPES];	/* pointers to type tags */
38*10933Srrh 
39*10933Srrh 	/* symbol tables for tokens and nonterminals */
40*10933Srrh 
41*10933Srrh int ntokens = 0;
42*10933Srrh struct toksymb tokset[NTERMS];
43*10933Srrh int toklev[NTERMS];
44*10933Srrh int nnonter = -1;
45*10933Srrh struct ntsymb nontrst[NNONTERM];
46*10933Srrh int start;	/* start symbol */
47*10933Srrh 
48*10933Srrh 	/* assigned token type values */
49*10933Srrh int extval = 0;
50*10933Srrh 
51*10933Srrh 	/* input and output file descriptors */
52*10933Srrh 
53*10933Srrh FILE * finput;		/* yacc input file */
54*10933Srrh FILE * faction;		/* file for saving actions */
55*10933Srrh FILE * fdefine;		/* file for # defines */
56*10933Srrh FILE * ftable;		/* y.tab.c file */
57*10933Srrh FILE * ftemp;		/* tempfile to pass 2 */
58*10933Srrh FILE * foutput;		/* y.output file */
59*10933Srrh 
60*10933Srrh 	/* storage for grammar rules */
61*10933Srrh 
62*10933Srrh int mem0[MEMSIZE] ; /* production storage */
63*10933Srrh int *mem = mem0;
64*10933Srrh int nprod= 1;	/* number of productions */
65*10933Srrh int *prdptr[NPROD];	/* pointers to descriptions of productions */
66*10933Srrh int levprd[NPROD] ;	/* precedence levels for the productions */
67*10933Srrh 
68*10933Srrh 
setup(argc,argv)69*10933Srrh setup(argc,argv) int argc; char *argv[];
70*10933Srrh {	int i,j,lev,t, ty;
71*10933Srrh 	int c;
72*10933Srrh 	int *p;
73*10933Srrh 	char actname[8];
74*10933Srrh 
75*10933Srrh 	foutput = NULL;
76*10933Srrh 	fdefine = NULL;
77*10933Srrh 	i = 1;
78*10933Srrh 	while( argc >= 2  && argv[1][0] == '-' ) {
79*10933Srrh 		while( *++(argv[1]) ){
80*10933Srrh 			switch( *argv[1] ){
81*10933Srrh 			case 'v':
82*10933Srrh 			case 'V':
83*10933Srrh 				foutput = fopen(FILEU, "w" );
84*10933Srrh 				if( foutput == NULL ) error( "cannot open y.output" );
85*10933Srrh 				continue;
86*10933Srrh 			case 'D':
87*10933Srrh 			case 'd':
88*10933Srrh 				fdefine = fopen( FILED, "w" );
89*10933Srrh 				continue;
90*10933Srrh 			case 'o':
91*10933Srrh 			case 'O':
92*10933Srrh 				fprintf( stderr, "`o' flag now default in yacc\n" );
93*10933Srrh 				continue;
94*10933Srrh 
95*10933Srrh 			case 'r':
96*10933Srrh 			case 'R':
97*10933Srrh 				error( "Ratfor Yacc is dead: sorry...\n" );
98*10933Srrh 
99*10933Srrh 			default:
100*10933Srrh 				error( "illegal option: %c", *argv[1]);
101*10933Srrh 				}
102*10933Srrh 			}
103*10933Srrh 		argv++;
104*10933Srrh 		argc--;
105*10933Srrh 		}
106*10933Srrh 
107*10933Srrh 	ftable = fopen( OFILE, "w" );
108*10933Srrh 	if( ftable == NULL ) error( "cannot open table file" );
109*10933Srrh 
110*10933Srrh 	ftemp = fopen( TEMPNAME, "w" );
111*10933Srrh 	faction = fopen( ACTNAME, "w" );
112*10933Srrh 	if( ftemp==NULL || faction==NULL ) error( "cannot open temp file" );
113*10933Srrh 
114*10933Srrh 	if( argc < 2 || ((finput=fopen( infile=argv[1], "r" )) == NULL ) ){
115*10933Srrh 		error( "cannot open input file" );
116*10933Srrh 		}
117*10933Srrh 
118*10933Srrh 	cnamp = cnames;
119*10933Srrh 	defin(0,"$end");
120*10933Srrh 	extval = 0400;
121*10933Srrh 	defin(0,"error");
122*10933Srrh 	defin(1,"$accept");
123*10933Srrh 	mem=mem0;
124*10933Srrh 	lev = 0;
125*10933Srrh 	ty = 0;
126*10933Srrh 	i=0;
127*10933Srrh 
128*10933Srrh 	/* sorry -- no yacc parser here.....
129*10933Srrh 		we must bootstrap somehow... */
130*10933Srrh 
131*10933Srrh 	for( t=gettok();  t!=MARK && t!= ENDFILE; ){
132*10933Srrh 		switch( t ){
133*10933Srrh 
134*10933Srrh 		case ';':
135*10933Srrh 			t = gettok();
136*10933Srrh 			break;
137*10933Srrh 
138*10933Srrh 		case START:
139*10933Srrh 			if( (t=gettok()) != IDENTIFIER ){
140*10933Srrh 				error( "bad %%start construction" );
141*10933Srrh 				}
142*10933Srrh 			start = chfind(1,tokname);
143*10933Srrh 			t = gettok();
144*10933Srrh 			continue;
145*10933Srrh 
146*10933Srrh 		case TYPEDEF:
147*10933Srrh 			if( (t=gettok()) != TYPENAME ) error( "bad syntax in %%type" );
148*10933Srrh 			ty = numbval;
149*10933Srrh 			for(;;){
150*10933Srrh 				t = gettok();
151*10933Srrh 				switch( t ){
152*10933Srrh 
153*10933Srrh 				case IDENTIFIER:
154*10933Srrh 					if( (t=chfind( 1, tokname ) ) < NTBASE ) {
155*10933Srrh 						j = TYPE( toklev[t] );
156*10933Srrh 						if( j!= 0 && j != ty ){
157*10933Srrh 							error( "type redeclaration of token %s",
158*10933Srrh 								tokset[t].name );
159*10933Srrh 							}
160*10933Srrh 						else SETTYPE( toklev[t],ty);
161*10933Srrh 						}
162*10933Srrh 					else {
163*10933Srrh 						j = nontrst[t-NTBASE].tvalue;
164*10933Srrh 						if( j != 0 && j != ty ){
165*10933Srrh 							error( "type redeclaration of nonterminal %s",
166*10933Srrh 								nontrst[t-NTBASE].name );
167*10933Srrh 							}
168*10933Srrh 						else nontrst[t-NTBASE].tvalue = ty;
169*10933Srrh 						}
170*10933Srrh 				case ',':
171*10933Srrh 					continue;
172*10933Srrh 
173*10933Srrh 				case ';':
174*10933Srrh 					t = gettok();
175*10933Srrh 					break;
176*10933Srrh 				default:
177*10933Srrh 					break;
178*10933Srrh 					}
179*10933Srrh 				break;
180*10933Srrh 				}
181*10933Srrh 			continue;
182*10933Srrh 
183*10933Srrh 		case UNION:
184*10933Srrh 			/* copy the union declaration to the output */
185*10933Srrh 			cpyunion();
186*10933Srrh 			t = gettok();
187*10933Srrh 			continue;
188*10933Srrh 
189*10933Srrh 		case LEFT:
190*10933Srrh 		case BINARY:
191*10933Srrh 		case RIGHT:
192*10933Srrh 			++i;
193*10933Srrh 		case TERM:
194*10933Srrh 			lev = t-TERM;  /* nonzero means new prec. and assoc. */
195*10933Srrh 			ty = 0;
196*10933Srrh 
197*10933Srrh 			/* get identifiers so defined */
198*10933Srrh 
199*10933Srrh 			t = gettok();
200*10933Srrh 			if( t == TYPENAME ){ /* there is a type defined */
201*10933Srrh 				ty = numbval;
202*10933Srrh 				t = gettok();
203*10933Srrh 				}
204*10933Srrh 
205*10933Srrh 			for(;;) {
206*10933Srrh 				switch( t ){
207*10933Srrh 
208*10933Srrh 				case ',':
209*10933Srrh 					t = gettok();
210*10933Srrh 					continue;
211*10933Srrh 
212*10933Srrh 				case ';':
213*10933Srrh 					break;
214*10933Srrh 
215*10933Srrh 				case IDENTIFIER:
216*10933Srrh 					j = chfind(0,tokname);
217*10933Srrh 					if( lev ){
218*10933Srrh 						if( ASSOC(toklev[j]) ) error( "redeclaration of precedence of %s", tokname );
219*10933Srrh 						SETASC(toklev[j],lev);
220*10933Srrh 						SETPLEV(toklev[j],i);
221*10933Srrh 						}
222*10933Srrh 					if( ty ){
223*10933Srrh 						if( TYPE(toklev[j]) ) error( "redeclaration of type of %s", tokname );
224*10933Srrh 						SETTYPE(toklev[j],ty);
225*10933Srrh 						}
226*10933Srrh 					if( (t=gettok()) == NUMBER ){
227*10933Srrh 						tokset[j].value = numbval;
228*10933Srrh 						if( j < ndefout && j>2 ){
229*10933Srrh 							error( "please define type number of %s earlier",
230*10933Srrh 								tokset[j].name );
231*10933Srrh 							}
232*10933Srrh 						t=gettok();
233*10933Srrh 						}
234*10933Srrh 					continue;
235*10933Srrh 
236*10933Srrh 					}
237*10933Srrh 
238*10933Srrh 				break;
239*10933Srrh 				}
240*10933Srrh 
241*10933Srrh 			continue;
242*10933Srrh 
243*10933Srrh 		case LCURLY:
244*10933Srrh 			defout();
245*10933Srrh 			cpycode();
246*10933Srrh 			t = gettok();
247*10933Srrh 			continue;
248*10933Srrh 
249*10933Srrh 		default:
250*10933Srrh 			error( "syntax error" );
251*10933Srrh 
252*10933Srrh 			}
253*10933Srrh 
254*10933Srrh 		}
255*10933Srrh 
256*10933Srrh 	if( t == ENDFILE ){
257*10933Srrh 		error( "unexpected EOF before %%" );
258*10933Srrh 		}
259*10933Srrh 
260*10933Srrh 	/* t is MARK */
261*10933Srrh 
262*10933Srrh 	defout();
263*10933Srrh 
264*10933Srrh 		fprintf( ftable,  "#define yyclearin yychar = -1\n" );
265*10933Srrh 		fprintf( ftable,  "#define yyerrok yyerrflag = 0\n" );
266*10933Srrh 		fprintf( ftable,  "extern int yychar;\nextern short yyerrflag;\n" );
267*10933Srrh 		fprintf( ftable,  "#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n" );
268*10933Srrh 		if( !ntypes ) fprintf( ftable,  "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n" );
269*10933Srrh 		fprintf( ftable,  "YYSTYPE yylval, yyval;\n" );
270*10933Srrh 
271*10933Srrh 	prdptr[0]=mem;
272*10933Srrh 	/* added production */
273*10933Srrh 	*mem++ = NTBASE;
274*10933Srrh 	*mem++ = start;  /* if start is 0, we will overwrite with the lhs of the first rule */
275*10933Srrh 	*mem++ = 1;
276*10933Srrh 	*mem++ = 0;
277*10933Srrh 	prdptr[1]=mem;
278*10933Srrh 
279*10933Srrh 	while( (t=gettok()) == LCURLY ) cpycode();
280*10933Srrh 
281*10933Srrh 	if( t != C_IDENTIFIER ) error( "bad syntax on first rule" );
282*10933Srrh 
283*10933Srrh 	if( !start ) prdptr[0][1] = chfind(1,tokname);
284*10933Srrh 
285*10933Srrh 	/* read rules */
286*10933Srrh 
287*10933Srrh 	while( t!=MARK && t!=ENDFILE ){
288*10933Srrh 
289*10933Srrh 		/* process a rule */
290*10933Srrh 
291*10933Srrh 		if( t == '|' ){
292*10933Srrh 			*mem++ = *prdptr[nprod-1];
293*10933Srrh 			}
294*10933Srrh 		else if( t == C_IDENTIFIER ){
295*10933Srrh 			*mem = chfind(1,tokname);
296*10933Srrh 			if( *mem < NTBASE ) error( "token illegal on LHS of grammar rule" );
297*10933Srrh 			++mem;
298*10933Srrh 			}
299*10933Srrh 		else error( "illegal rule: missing semicolon or | ?" );
300*10933Srrh 
301*10933Srrh 		/* read rule body */
302*10933Srrh 
303*10933Srrh 
304*10933Srrh 		t = gettok();
305*10933Srrh 	more_rule:
306*10933Srrh 		while( t == IDENTIFIER ) {
307*10933Srrh 			*mem = chfind(1,tokname);
308*10933Srrh 			if( *mem<NTBASE ) levprd[nprod] = toklev[*mem];
309*10933Srrh 			++mem;
310*10933Srrh 			t = gettok();
311*10933Srrh 			}
312*10933Srrh 
313*10933Srrh 
314*10933Srrh 		if( t == PREC ){
315*10933Srrh 			if( gettok()!=IDENTIFIER) error( "illegal %%prec syntax" );
316*10933Srrh 			j = chfind(2,tokname);
317*10933Srrh 			if( j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name);
318*10933Srrh 			levprd[nprod]=toklev[j];
319*10933Srrh 			t = gettok();
320*10933Srrh 			}
321*10933Srrh 
322*10933Srrh 		if( t == '=' ){
323*10933Srrh 			levprd[nprod] |= ACTFLAG;
324*10933Srrh 			fprintf( faction, "\ncase %d:", nprod );
325*10933Srrh 			cpyact( mem-prdptr[nprod]-1 );
326*10933Srrh 			fprintf( faction, " break;" );
327*10933Srrh 			if( (t=gettok()) == IDENTIFIER ){
328*10933Srrh 				/* action within rule... */
329*10933Srrh 
330*10933Srrh 				sprintf( actname, "$$%d", nprod );
331*10933Srrh 				j = chfind(1,actname);  /* make it a nonterminal */
332*10933Srrh 
333*10933Srrh 				/* the current rule will become rule number nprod+1 */
334*10933Srrh 				/* move the contents down, and make room for the null */
335*10933Srrh 
336*10933Srrh 				for( p=mem; p>=prdptr[nprod]; --p ) p[2] = *p;
337*10933Srrh 				mem += 2;
338*10933Srrh 
339*10933Srrh 				/* enter null production for action */
340*10933Srrh 
341*10933Srrh 				p = prdptr[nprod];
342*10933Srrh 
343*10933Srrh 				*p++ = j;
344*10933Srrh 				*p++ = -nprod;
345*10933Srrh 
346*10933Srrh 				/* update the production information */
347*10933Srrh 
348*10933Srrh 				levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
349*10933Srrh 				levprd[nprod] = ACTFLAG;
350*10933Srrh 
351*10933Srrh 				if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
352*10933Srrh 				prdptr[nprod] = p;
353*10933Srrh 
354*10933Srrh 				/* make the action appear in the original rule */
355*10933Srrh 				*mem++ = j;
356*10933Srrh 
357*10933Srrh 				/* get some more of the rule */
358*10933Srrh 
359*10933Srrh 				goto more_rule;
360*10933Srrh 				}
361*10933Srrh 
362*10933Srrh 			}
363*10933Srrh 
364*10933Srrh 		while( t == ';' ) t = gettok();
365*10933Srrh 
366*10933Srrh 		*mem++ = -nprod;
367*10933Srrh 
368*10933Srrh 		/* check that default action is reasonable */
369*10933Srrh 
370*10933Srrh 		if( ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue ){
371*10933Srrh 			/* no explicit action, LHS has value */
372*10933Srrh 			register tempty;
373*10933Srrh 			tempty = prdptr[nprod][1];
374*10933Srrh 			if( tempty < 0 ) error( "must return a value, since LHS has a type" );
375*10933Srrh 			else if( tempty >= NTBASE ) tempty = nontrst[tempty-NTBASE].tvalue;
376*10933Srrh 			else tempty = TYPE( toklev[tempty] );
377*10933Srrh 			if( tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue ){
378*10933Srrh 				error( "default action causes potential type clash" );
379*10933Srrh 				}
380*10933Srrh 			}
381*10933Srrh 
382*10933Srrh 		if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
383*10933Srrh 		prdptr[nprod] = mem;
384*10933Srrh 		levprd[nprod]=0;
385*10933Srrh 
386*10933Srrh 		}
387*10933Srrh 
388*10933Srrh 	/* end of all rules */
389*10933Srrh 
390*10933Srrh 	finact();
391*10933Srrh 	if( t == MARK ){
392*10933Srrh 		fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
393*10933Srrh 		while( (c=getc(finput)) != EOF ) putc( c, ftable );
394*10933Srrh 		}
395*10933Srrh 	fclose( finput );
396*10933Srrh 	}
397*10933Srrh 
finact()398*10933Srrh finact(){
399*10933Srrh 	/* finish action routine */
400*10933Srrh 
401*10933Srrh 	fclose(faction);
402*10933Srrh 
403*10933Srrh 	fprintf( ftable, "# define YYERRCODE %d\n", tokset[2].value );
404*10933Srrh 
405*10933Srrh 	}
406*10933Srrh 
defin(t,s)407*10933Srrh defin( t, s ) register char  *s; {
408*10933Srrh /*	define s to be a terminal if t=0
409*10933Srrh 	or a nonterminal if t=1		*/
410*10933Srrh 
411*10933Srrh 	register val;
412*10933Srrh 
413*10933Srrh 	if (t) {
414*10933Srrh 		if( ++nnonter >= NNONTERM ) error("too many nonterminals, limit %d",NNONTERM);
415*10933Srrh 		nontrst[nnonter].name = cstash(s);
416*10933Srrh 		return( NTBASE + nnonter );
417*10933Srrh 		}
418*10933Srrh 	/* must be a token */
419*10933Srrh 	if( ++ntokens >= NTERMS ) error("too many terminals, limit %d",NTERMS );
420*10933Srrh 	tokset[ntokens].name = cstash(s);
421*10933Srrh 
422*10933Srrh 	/* establish value for token */
423*10933Srrh 
424*10933Srrh 	if( s[0]==' ' && s[2]=='\0' ) /* single character literal */
425*10933Srrh 		val = s[1];
426*10933Srrh 	else if ( s[0]==' ' && s[1]=='\\' ) { /* escape sequence */
427*10933Srrh 		if( s[3] == '\0' ){ /* single character escape sequence */
428*10933Srrh 			switch ( s[2] ){
429*10933Srrh 					 /* character which is escaped */
430*10933Srrh 			case 'n': val = '\n'; break;
431*10933Srrh 			case 'r': val = '\r'; break;
432*10933Srrh 			case 'b': val = '\b'; break;
433*10933Srrh 			case 't': val = '\t'; break;
434*10933Srrh 			case 'f': val = '\f'; break;
435*10933Srrh 			case '\'': val = '\''; break;
436*10933Srrh 			case '"': val = '"'; break;
437*10933Srrh 			case '\\': val = '\\'; break;
438*10933Srrh 			default: error( "invalid escape" );
439*10933Srrh 				}
440*10933Srrh 			}
441*10933Srrh 		else if( s[2] <= '7' && s[2]>='0' ){ /* \nnn sequence */
442*10933Srrh 			if( s[3]<'0' || s[3] > '7' || s[4]<'0' ||
443*10933Srrh 				s[4]>'7' || s[5] != '\0' ) error("illegal \\nnn construction" );
444*10933Srrh 			val = 64*s[2] + 8*s[3] + s[4] - 73*'0';
445*10933Srrh 			if( val == 0 ) error( "'\\000' is illegal" );
446*10933Srrh 			}
447*10933Srrh 		}
448*10933Srrh 	else {
449*10933Srrh 		val = extval++;
450*10933Srrh 		}
451*10933Srrh 	tokset[ntokens].value = val;
452*10933Srrh 	toklev[ntokens] = 0;
453*10933Srrh 	return( ntokens );
454*10933Srrh 	}
455*10933Srrh 
defout()456*10933Srrh defout(){ /* write out the defines (at the end of the declaration section) */
457*10933Srrh 
458*10933Srrh 	register int i, c;
459*10933Srrh 	register char *cp;
460*10933Srrh 
461*10933Srrh 	for( i=ndefout; i<=ntokens; ++i ){
462*10933Srrh 
463*10933Srrh 		cp = tokset[i].name;
464*10933Srrh 		if( *cp == ' ' ) ++cp;  /* literals */
465*10933Srrh 
466*10933Srrh 		for( ; (c= *cp)!='\0'; ++cp ){
467*10933Srrh 
468*10933Srrh 			if( islower(c) || isupper(c) || isdigit(c) || c=='_' );  /* VOID */
469*10933Srrh 			else goto nodef;
470*10933Srrh 			}
471*10933Srrh 
472*10933Srrh 		fprintf( ftable, "# define %s %d\n", tokset[i].name, tokset[i].value );
473*10933Srrh 		if( fdefine != NULL ) fprintf( fdefine, "# define %s %d\n", tokset[i].name, tokset[i].value );
474*10933Srrh 
475*10933Srrh 	nodef:	;
476*10933Srrh 		}
477*10933Srrh 
478*10933Srrh 	ndefout = ntokens+1;
479*10933Srrh 
480*10933Srrh 	}
481*10933Srrh 
482*10933Srrh char *
cstash(s)483*10933Srrh cstash( s ) register char *s; {
484*10933Srrh 	char *temp;
485*10933Srrh 
486*10933Srrh 	temp = cnamp;
487*10933Srrh 	do {
488*10933Srrh 		if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" );
489*10933Srrh 		else *cnamp++ = *s;
490*10933Srrh 		}  while ( *s++ );
491*10933Srrh 	return( temp );
492*10933Srrh 	}
493*10933Srrh 
gettok()494*10933Srrh gettok() {
495*10933Srrh 	register i, base;
496*10933Srrh 	static int peekline; /* number of '\n' seen in lookahead */
497*10933Srrh 	register c, match, reserve;
498*10933Srrh 
499*10933Srrh begin:
500*10933Srrh 	reserve = 0;
501*10933Srrh 	lineno += peekline;
502*10933Srrh 	peekline = 0;
503*10933Srrh 	c = getc(finput);
504*10933Srrh 	while( c==' ' || c=='\n' || c=='\t' || c=='\f' ){
505*10933Srrh 		if( c == '\n' ) ++lineno;
506*10933Srrh 		c=getc(finput);
507*10933Srrh 		}
508*10933Srrh 	if( c == '/' ){ /* skip comment */
509*10933Srrh 		lineno += skipcom();
510*10933Srrh 		goto begin;
511*10933Srrh 		}
512*10933Srrh 
513*10933Srrh 	switch(c){
514*10933Srrh 
515*10933Srrh 	case EOF:
516*10933Srrh 		return(ENDFILE);
517*10933Srrh 	case '{':
518*10933Srrh 		ungetc( c, finput );
519*10933Srrh 		return( '=' );  /* action ... */
520*10933Srrh 	case '<':  /* get, and look up, a type name (union member name) */
521*10933Srrh 		i = 0;
522*10933Srrh 		while( (c=getc(finput)) != '>' && c>=0 && c!= '\n' ){
523*10933Srrh 			tokname[i] = c;
524*10933Srrh 			if( ++i >= NAMESIZE ) --i;
525*10933Srrh 			}
526*10933Srrh 		if( c != '>' ) error( "unterminated < ... > clause" );
527*10933Srrh 		tokname[i] = '\0';
528*10933Srrh 		for( i=1; i<=ntypes; ++i ){
529*10933Srrh 			if( !strcmp( typeset[i], tokname ) ){
530*10933Srrh 				numbval = i;
531*10933Srrh 				return( TYPENAME );
532*10933Srrh 				}
533*10933Srrh 			}
534*10933Srrh 		typeset[numbval = ++ntypes] = cstash( tokname );
535*10933Srrh 		return( TYPENAME );
536*10933Srrh 
537*10933Srrh 	case '"':
538*10933Srrh 	case '\'':
539*10933Srrh 		match = c;
540*10933Srrh 		tokname[0] = ' ';
541*10933Srrh 		i = 1;
542*10933Srrh 		for(;;){
543*10933Srrh 			c = getc(finput);
544*10933Srrh 			if( c == '\n' || c == EOF )
545*10933Srrh 				error("illegal or missing ' or \"" );
546*10933Srrh 			if( c == '\\' ){
547*10933Srrh 				c = getc(finput);
548*10933Srrh 				tokname[i] = '\\';
549*10933Srrh 				if( ++i >= NAMESIZE ) --i;
550*10933Srrh 				}
551*10933Srrh 			else if( c == match ) break;
552*10933Srrh 			tokname[i] = c;
553*10933Srrh 			if( ++i >= NAMESIZE ) --i;
554*10933Srrh 			}
555*10933Srrh 		break;
556*10933Srrh 
557*10933Srrh 	case '%':
558*10933Srrh 	case '\\':
559*10933Srrh 
560*10933Srrh 		switch(c=getc(finput)) {
561*10933Srrh 
562*10933Srrh 		case '0':	return(TERM);
563*10933Srrh 		case '<':	return(LEFT);
564*10933Srrh 		case '2':	return(BINARY);
565*10933Srrh 		case '>':	return(RIGHT);
566*10933Srrh 		case '%':
567*10933Srrh 		case '\\':	return(MARK);
568*10933Srrh 		case '=':	return(PREC);
569*10933Srrh 		case '{':	return(LCURLY);
570*10933Srrh 		default:	reserve = 1;
571*10933Srrh 			}
572*10933Srrh 
573*10933Srrh 	default:
574*10933Srrh 
575*10933Srrh 		if( isdigit(c) ){ /* number */
576*10933Srrh 			numbval = c-'0' ;
577*10933Srrh 			base = (c=='0') ? 8 : 10 ;
578*10933Srrh 			for( c=getc(finput); isdigit(c) ; c=getc(finput) ){
579*10933Srrh 				numbval = numbval*base + c - '0';
580*10933Srrh 				}
581*10933Srrh 			ungetc( c, finput );
582*10933Srrh 			return(NUMBER);
583*10933Srrh 			}
584*10933Srrh 		else if( islower(c) || isupper(c) || c=='_' || c=='.' || c=='$' ){
585*10933Srrh 			i = 0;
586*10933Srrh 			while( islower(c) || isupper(c) || isdigit(c) || c=='_' || c=='.' || c=='$' ){
587*10933Srrh 				tokname[i] = c;
588*10933Srrh 				if( reserve && isupper(c) ) tokname[i] += 'a'-'A';
589*10933Srrh 				if( ++i >= NAMESIZE ) --i;
590*10933Srrh 				c = getc(finput);
591*10933Srrh 				}
592*10933Srrh 			}
593*10933Srrh 		else return(c);
594*10933Srrh 
595*10933Srrh 		ungetc( c, finput );
596*10933Srrh 		}
597*10933Srrh 
598*10933Srrh 	tokname[i] = '\0';
599*10933Srrh 
600*10933Srrh 	if( reserve ){ /* find a reserved word */
601*10933Srrh 		if( !strcmp(tokname,"term")) return( TERM );
602*10933Srrh 		if( !strcmp(tokname,"token")) return( TERM );
603*10933Srrh 		if( !strcmp(tokname,"left")) return( LEFT );
604*10933Srrh 		if( !strcmp(tokname,"nonassoc")) return( BINARY );
605*10933Srrh 		if( !strcmp(tokname,"binary")) return( BINARY );
606*10933Srrh 		if( !strcmp(tokname,"right")) return( RIGHT );
607*10933Srrh 		if( !strcmp(tokname,"prec")) return( PREC );
608*10933Srrh 		if( !strcmp(tokname,"start")) return( START );
609*10933Srrh 		if( !strcmp(tokname,"type")) return( TYPEDEF );
610*10933Srrh 		if( !strcmp(tokname,"union")) return( UNION );
611*10933Srrh 		error("invalid escape, or illegal reserved word: %s", tokname );
612*10933Srrh 		}
613*10933Srrh 
614*10933Srrh 	/* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */
615*10933Srrh 
616*10933Srrh 	c = getc(finput);
617*10933Srrh 	while( c==' ' || c=='\t'|| c=='\n' || c=='\f' || c== '/' ) {
618*10933Srrh 		if( c == '\n' ) ++peekline;
619*10933Srrh 		else if( c == '/' ){ /* look for comments */
620*10933Srrh 			peekline += skipcom();
621*10933Srrh 			}
622*10933Srrh 		c = getc(finput);
623*10933Srrh 		}
624*10933Srrh 	if( c == ':' ) return( C_IDENTIFIER );
625*10933Srrh 	ungetc( c, finput );
626*10933Srrh 	return( IDENTIFIER );
627*10933Srrh }
628*10933Srrh 
fdtype(t)629*10933Srrh fdtype( t ){ /* determine the type of a symbol */
630*10933Srrh 	register v;
631*10933Srrh 	if( t >= NTBASE ) v = nontrst[t-NTBASE].tvalue;
632*10933Srrh 	else v = TYPE( toklev[t] );
633*10933Srrh 	if( v <= 0 ) error( "must specify type for %s", (t>=NTBASE)?nontrst[t-NTBASE].name:
634*10933Srrh 			tokset[t].name );
635*10933Srrh 	return( v );
636*10933Srrh 	}
637*10933Srrh 
chfind(t,s)638*10933Srrh chfind( t, s ) register char *s; {
639*10933Srrh 	int i;
640*10933Srrh 
641*10933Srrh 	if (s[0]==' ')t=0;
642*10933Srrh 	TLOOP(i){
643*10933Srrh 		if(!strcmp(s,tokset[i].name)){
644*10933Srrh 			return( i );
645*10933Srrh 			}
646*10933Srrh 		}
647*10933Srrh 	NTLOOP(i){
648*10933Srrh 		if(!strcmp(s,nontrst[i].name)) {
649*10933Srrh 			return( i+NTBASE );
650*10933Srrh 			}
651*10933Srrh 		}
652*10933Srrh 	/* cannot find name */
653*10933Srrh 	if( t>1 )
654*10933Srrh 		error( "%s should have been defined earlier", s );
655*10933Srrh 	return( defin( t, s ) );
656*10933Srrh 	}
657*10933Srrh 
cpyunion()658*10933Srrh cpyunion(){
659*10933Srrh 	/* copy the union declaration to the output, and the define file if present */
660*10933Srrh 
661*10933Srrh 	int level, c;
662*10933Srrh 	fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
663*10933Srrh 	fprintf( ftable, "typedef union " );
664*10933Srrh 	if( fdefine ) fprintf( fdefine, "\ntypedef union " );
665*10933Srrh 
666*10933Srrh 	level = 0;
667*10933Srrh 	for(;;){
668*10933Srrh 		if( (c=getc(finput)) < 0 ) error( "EOF encountered while processing %%union" );
669*10933Srrh 		putc( c, ftable );
670*10933Srrh 		if( fdefine ) putc( c, fdefine );
671*10933Srrh 
672*10933Srrh 		switch( c ){
673*10933Srrh 
674*10933Srrh 		case '\n':
675*10933Srrh 			++lineno;
676*10933Srrh 			break;
677*10933Srrh 
678*10933Srrh 		case '{':
679*10933Srrh 			++level;
680*10933Srrh 			break;
681*10933Srrh 
682*10933Srrh 		case '}':
683*10933Srrh 			--level;
684*10933Srrh 			if( level == 0 ) { /* we are finished copying */
685*10933Srrh 				fprintf( ftable, " YYSTYPE;\n" );
686*10933Srrh 				if( fdefine ) fprintf( fdefine, " YYSTYPE;\nextern YYSTYPE yylval;\n" );
687*10933Srrh 				return;
688*10933Srrh 				}
689*10933Srrh 			}
690*10933Srrh 		}
691*10933Srrh 	}
692*10933Srrh 
cpycode()693*10933Srrh cpycode(){ /* copies code between \{ and \} */
694*10933Srrh 
695*10933Srrh 	int c;
696*10933Srrh 	c = getc(finput);
697*10933Srrh 	if( c == '\n' ) {
698*10933Srrh 		c = getc(finput);
699*10933Srrh 		lineno++;
700*10933Srrh 		}
701*10933Srrh 	fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
702*10933Srrh 	while( c>=0 ){
703*10933Srrh 		if( c=='\\' )
704*10933Srrh 			if( (c=getc(finput)) == '}' ) return;
705*10933Srrh 			else putc('\\', ftable );
706*10933Srrh 		if( c=='%' )
707*10933Srrh 			if( (c=getc(finput)) == '}' ) return;
708*10933Srrh 			else putc('%', ftable );
709*10933Srrh 		putc( c , ftable );
710*10933Srrh 		if( c == '\n' ) ++lineno;
711*10933Srrh 		c = getc(finput);
712*10933Srrh 		}
713*10933Srrh 	error("eof before %%}" );
714*10933Srrh 	}
715*10933Srrh 
skipcom()716*10933Srrh skipcom(){ /* skip over comments */
717*10933Srrh 	register c, i=0;  /* i is the number of lines skipped */
718*10933Srrh 
719*10933Srrh 	/* skipcom is called after reading a / */
720*10933Srrh 
721*10933Srrh 	if( getc(finput) != '*' ) error( "illegal comment" );
722*10933Srrh 	c = getc(finput);
723*10933Srrh 	while( c != EOF ){
724*10933Srrh 		while( c == '*' ){
725*10933Srrh 			if( (c=getc(finput)) == '/' ) return( i );
726*10933Srrh 			}
727*10933Srrh 		if( c == '\n' ) ++i;
728*10933Srrh 		c = getc(finput);
729*10933Srrh 		}
730*10933Srrh 	error( "EOF inside comment" );
731*10933Srrh 	/* NOTREACHED */
732*10933Srrh 	}
733*10933Srrh 
cpyact(offset)734*10933Srrh cpyact(offset){ /* copy C action to the next ; or closing } */
735*10933Srrh 	int brac, c, match, j, s, tok;
736*10933Srrh 
737*10933Srrh 	fprintf( faction, "\n# line %d \"%s\"\n", lineno, infile );
738*10933Srrh 
739*10933Srrh 	brac = 0;
740*10933Srrh 
741*10933Srrh loop:
742*10933Srrh 	c = getc(finput);
743*10933Srrh swt:
744*10933Srrh 	switch( c ){
745*10933Srrh 
746*10933Srrh case ';':
747*10933Srrh 		if( brac == 0 ){
748*10933Srrh 			putc( c , faction );
749*10933Srrh 			return;
750*10933Srrh 			}
751*10933Srrh 		goto lcopy;
752*10933Srrh 
753*10933Srrh case '{':
754*10933Srrh 		brac++;
755*10933Srrh 		goto lcopy;
756*10933Srrh 
757*10933Srrh case '$':
758*10933Srrh 		s = 1;
759*10933Srrh 		tok = -1;
760*10933Srrh 		c = getc(finput);
761*10933Srrh 		if( c == '<' ){ /* type description */
762*10933Srrh 			ungetc( c, finput );
763*10933Srrh 			if( gettok() != TYPENAME ) error( "bad syntax on $<ident> clause" );
764*10933Srrh 			tok = numbval;
765*10933Srrh 			c = getc(finput);
766*10933Srrh 			}
767*10933Srrh 		if( c == '$' ){
768*10933Srrh 			fprintf( faction, "yyval");
769*10933Srrh 			if( ntypes ){ /* put out the proper tag... */
770*10933Srrh 				if( tok < 0 ) tok = fdtype( *prdptr[nprod] );
771*10933Srrh 				fprintf( faction, ".%s", typeset[tok] );
772*10933Srrh 				}
773*10933Srrh 			goto loop;
774*10933Srrh 			}
775*10933Srrh 		if( c == '-' ){
776*10933Srrh 			s = -s;
777*10933Srrh 			c = getc(finput);
778*10933Srrh 			}
779*10933Srrh 		if( isdigit(c) ){
780*10933Srrh 			j=0;
781*10933Srrh 			while( isdigit(c) ){
782*10933Srrh 				j= j*10+c-'0';
783*10933Srrh 				c = getc(finput);
784*10933Srrh 				}
785*10933Srrh 
786*10933Srrh 			j = j*s - offset;
787*10933Srrh 			if( j > 0 ){
788*10933Srrh 				error( "Illegal use of $%d", j+offset );
789*10933Srrh 				}
790*10933Srrh 
791*10933Srrh 			fprintf( faction, "yypvt[-%d]", -j );
792*10933Srrh 			if( ntypes ){ /* put out the proper tag */
793*10933Srrh 				if( j+offset <= 0 && tok < 0 ) error( "must specify type of $%d", j+offset );
794*10933Srrh 				if( tok < 0 ) tok = fdtype( prdptr[nprod][j+offset] );
795*10933Srrh 				fprintf( faction, ".%s", typeset[tok] );
796*10933Srrh 				}
797*10933Srrh 			goto swt;
798*10933Srrh 			}
799*10933Srrh 		putc( '$' , faction );
800*10933Srrh 		if( s<0 ) putc('-', faction );
801*10933Srrh 		goto swt;
802*10933Srrh 
803*10933Srrh case '}':
804*10933Srrh 		if( --brac ) goto lcopy;
805*10933Srrh 		putc( c, faction );
806*10933Srrh 		return;
807*10933Srrh 
808*10933Srrh 
809*10933Srrh case '/':	/* look for comments */
810*10933Srrh 		putc( c , faction );
811*10933Srrh 		c = getc(finput);
812*10933Srrh 		if( c != '*' ) goto swt;
813*10933Srrh 
814*10933Srrh 		/* it really is a comment */
815*10933Srrh 
816*10933Srrh 		putc( c , faction );
817*10933Srrh 		c = getc(finput);
818*10933Srrh 		while( c != EOF ){
819*10933Srrh 			while( c=='*' ){
820*10933Srrh 				putc( c , faction );
821*10933Srrh 				if( (c=getc(finput)) == '/' ) goto lcopy;
822*10933Srrh 				}
823*10933Srrh 			putc( c , faction );
824*10933Srrh 			if( c == '\n' )++lineno;
825*10933Srrh 			c = getc(finput);
826*10933Srrh 			}
827*10933Srrh 		error( "EOF inside comment" );
828*10933Srrh 
829*10933Srrh case '\'':	/* character constant */
830*10933Srrh 		match = '\'';
831*10933Srrh 		goto string;
832*10933Srrh 
833*10933Srrh case '"':	/* character string */
834*10933Srrh 		match = '"';
835*10933Srrh 
836*10933Srrh 	string:
837*10933Srrh 
838*10933Srrh 		putc( c , faction );
839*10933Srrh 		while( c=getc(finput) ){
840*10933Srrh 
841*10933Srrh 			if( c=='\\' ){
842*10933Srrh 				putc( c , faction );
843*10933Srrh 				c=getc(finput);
844*10933Srrh 				if( c == '\n' ) ++lineno;
845*10933Srrh 				}
846*10933Srrh 			else if( c==match ) goto lcopy;
847*10933Srrh 			else if( c=='\n' ) error( "newline in string or char. const." );
848*10933Srrh 			putc( c , faction );
849*10933Srrh 			}
850*10933Srrh 		error( "EOF in string or character constant" );
851*10933Srrh 
852*10933Srrh case EOF:
853*10933Srrh 		error("action does not terminate" );
854*10933Srrh 
855*10933Srrh case '\n':	++lineno;
856*10933Srrh 		goto lcopy;
857*10933Srrh 
858*10933Srrh 		}
859*10933Srrh 
860*10933Srrh lcopy:
861*10933Srrh 	putc( c , faction );
862*10933Srrh 	goto loop;
863*10933Srrh 	}
864