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