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