|
|
1.1 root 1: /*
2: * Copyright (c) 1979 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)ey2.c 5.1 (Berkeley) 4/29/85";
9: #endif not lint
10:
11: # include "ey.h"
12: # define IDENTIFIER 257
13: # define MARK 258
14: # define TERM 259
15: # define LEFT 260
16: # define BINARY 261
17: # define RIGHT 262
18: # define PREC 263
19: # define LCURLY 264
20: # define C_IDENTIFIER 265 /* name followed by colon */
21: # define NUMBER 266
22:
23: FILE *copen();
24:
25: setup(argc,argv) int argc; char *argv[];
26: { int i,j,lev,t;
27: int c;
28:
29: foutput = stdout;
30: i = 1;
31: while( argc >= 2 && argv[1][0] == '-' ) {
32: while( *++(argv[1]) ){
33: switch( *argv[1] ){
34: case 'v':
35: case 'V':
36: foutput = copen("y.output", 'w' );
37: if( foutput == 0 ) error( "cannot open y.output");
38: continue;
39: case 'o':
40: case 'O':
41: oflag = 1;
42: continue;
43: case 'r':
44: case 'R':
45: oflag = 1;
46: rflag = 1;
47: continue;
48: default: error( "illegal option: %c", *argv[1]);
49: }
50: }
51: argv++;
52: argc--;
53: }
54:
55: ftable = copen( oflag ? "yacc.tmp" : "y.tab.c" , 'w' );
56: if( ftable==0 ) error( "cannot open table file" );
57: if( argc > 1 ) { cin = copen( argv[1], 'r' );
58: if( cin == 0 ) error( "cannot open input" );
59: }
60: settab();
61: fprintf( cout , "#\n");
62: ctokn = "$end";
63: defin(0); /* eof */
64: extval = 0400; /* beginning of assigned values */
65: ctokn = "error";
66: defin(0);
67: ctokn = "$accept";
68: defin(1);
69: mem=mem0;
70: cnamp = cnames;
71: lev=0;
72: i=0;
73:
74: while( ( t = gettok() ) != EOF ) {
75: switch( t ){
76: case IDENTIFIER: j = chfind(0);
77: trmlev[j] = lev;
78: continue;
79: case ',':
80: case ';': continue;
81: case TERM: lev=0; continue;
82: case LEFT: lev=(++i<<3)|01; continue;
83: case BINARY: lev=(++i<<3)|02; continue;
84: case RIGHT: lev=(++i<<3)|03; continue;
85: case MARK:
86: defout();
87: if( rflag ){ /* RATFOR */
88: fprintf( cout , "define yyerrok yyerrf = 0\n" );
89: fprintf( cout , "define yyclearin yychar = -1\n" );
90: fprintf( cout , "subroutine yyactr(yyprdn)\n");
91: fprintf( cout , "common/yycomn/yylval,yyval,yypv,yyvalv(150)\n" );
92: fprintf( cout , "common/yylcom/yychar,yyerrf,yydebu\n" );
93: fprintf( cout , "integer yychar, yyerrf, yydebu\n" );
94: fprintf( cout , "integer yyprdn,yyval,yylval,yypv,yyvalv\n" );
95: }
96: else {
97: fprintf( cout , "#define yyclearin yychar = -1\n" );
98: fprintf( cout , "#define yyerrok yyerrflag = 0\n" );
99: fprintf( cout , "extern int yychar, yyerrflag;\n" );
100: fprintf( cout , "\nint yyval 0;\nint *yypv;\nint yylval 0;");
101: fprintf( cout , "\nyyactr(__np__){\n");
102: }
103: break;
104: case LCURLY: defout();
105: cpycode();
106: continue;
107: case NUMBER:
108: trmset[j].value = numbval;
109: if( j < ndefout && j>2 )
110: error("please define type # of %s earlier", trmset[j].name );
111: continue;
112: default: error("bad precedence syntax, input %d", t );
113: }
114: break;
115: }
116: prdptr[0]=mem;
117: /* added production */
118: *mem++ = NTBASE;
119: *mem++ = NTBASE+1;
120: *mem++ = 1;
121: *mem++ = 0;
122: prdptr[1]=mem;
123: i=0;
124:
125: /* i is 0 when a rule can begin, 1 otherwise */
126:
127: for(;;) switch( t=gettok() ) {
128: case C_IDENTIFIER: if( mem == prdptr[1] ) { /* first time */
129: if( rflag ){
130: fprintf( cout , "goto 1000\n" );
131: }
132: else fprintf( cout , "\nswitch(__np__){\n");
133: }
134: if( i != 0 ) error( "previous rule not terminated" );
135: *mem = chfind(1);
136: if( *mem < NTBASE )error( "token illegal on lhs of grammar rule" );
137: i=1;
138: ++mem;
139: continue;
140: case IDENTIFIER:
141: *mem=chfind(1);
142: if(*mem < NTBASE)levprd[nprod]=trmlev[*mem];
143: mem++;
144: if(i==0) error("missing :");
145: continue;
146: case '=': levprd[nprod] |= 04;
147: if( i==0 ) error("semicolon preceeds action");
148: fprintf( cout , rflag?"\n%d ":"\ncase %d:", nprod );
149: cpyact();
150: fprintf( cout , rflag ? " return" : " break;" );
151: case '|':
152: case ';': if(i){
153: *mem++ = -nprod;
154: prdptr[++nprod] = mem;
155: levprd[nprod]=0;
156: i=0;}
157: if (t=='|'){i=1;*mem++ = *prdptr[nprod-1];}
158: continue;
159: case 0: /* End Of File */
160: case EOF:
161: case MARK: if( i != 0 ) error( "rule not terminated before %%%% or EOF" );
162: settab();
163: finact();
164: /* copy the programs which follow the rules */
165: if( t == MARK ){
166: while (( c=fgetc( cin)) != EOF ) fputc(c,cout);
167: }
168: return;
169: case PREC:
170: if( i==0 ) error( "%%prec must appear inside rule" );
171: if( gettok()!=IDENTIFIER)error("illegal %%prec syntax" );
172: j=chfind(2);
173: if(j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name);
174: levprd[nprod]=trmlev[j];
175: continue;
176: case LCURLY:
177: if( i!=0 ) error( "%%{ appears within a rule" );
178: cpycode();
179: continue;
180: default: error( "syntax error, input %d", t );
181: }
182: }
183:
184: finact(){
185: /* finish action routine */
186: register i;
187:
188: if( rflag ){
189:
190: fprintf( cout , "\n1000 goto(" );
191: for( i=1; i<nprod; ++i ){
192: fprintf( cout , "%d,", (levprd[i]&04)==0?999:i );
193: }
194: fprintf( cout , "999),yyprdn\n" );
195: fprintf( cout , "999 return\nend\n" );
196: fprintf( cout , "define YYERRCODE %d\n", trmset[2].value );
197: }
198: else {
199: fprintf( cout , "\n}\n}\n" );
200: fprintf( cout , "int yyerrval %d;\n", trmset[2].value );
201: }
202: }
203: defin(t) {
204: /* define ctokn to be a terminal if t=0
205: or a nonterminal if t=1 */
206: char *cp,*p;
207: int c;
208:
209:
210: if (t) {
211: if( ++nnonter >= ntlim ) error("too many nonterminals, limit %d",ntlim);
212: nontrst[nnonter].name = ctokn;
213: return( NTBASE + nnonter );
214: }
215: else {
216: if( ++nterms >= tlim ) error("too many terminals, limit %d",tlim );
217: trmset[nterms].name = ctokn;
218: if( ctokn[0]==' ' && ctokn[2]=='\0' ) /* single character literal */
219: trmset[nterms].value = ctokn[1];
220: else if ( ctokn[0]==' ' && ctokn[1]=='\\' ) { /* escape sequence */
221: if( ctokn[3] == '\0' ){ /* single character escape sequence */
222: switch ( ctokn[2] ){
223: /* character which is escaped */
224: case 'n': trmset[nterms].value = '\n'; break;
225: case 'r': trmset[nterms].value = '\r'; break;
226: case 'b': trmset[nterms].value = '\b'; break;
227: case 't': trmset[nterms].value = '\t'; break;
228: case '\'': trmset[nterms].value = '\''; break;
229: case '"': trmset[nterms].value = '"'; break;
230: case '\\': trmset[nterms].value = '\\'; break;
231: default: error( "invalid escape" );
232: }
233: }
234: else if( ctokn[2] <= '7' && ctokn[2]>='0' ){ /* \nnn sequence */
235: if( ctokn[3]<'0' || ctokn[3] > '7' || ctokn[4]<'0' ||
236: ctokn[4]>'7' || ctokn[5] != '\0' ) error("illegal \\nnn construction" );
237: trmset[nterms].value = 64*(ctokn[2]-'0')+8*(ctokn[3]-'0')+ctokn[4]-'0';
238: if( trmset[nterms].value == 0 ) error( "'\\000' is illegal" );
239: }
240: }
241: else {
242: trmset[nterms].value = extval++;
243:
244: }
245: trmlev[nterms] = 0;
246: return( nterms );
247: }
248: }
249:
250: defout(){ /* write out the defines (at the end of the declaration section) */
251:
252: _REGISTER int i, c;
253: _REGISTER char *cp;
254:
255: for( i=ndefout; i<=nterms; ++i ){
256:
257: cp = trmset[i].name;
258: if( *cp == ' ' ) ++cp; /* literals */
259:
260: for( ; (c= *cp)!='\0'; ++cp ){
261:
262: if( c>='a' && c<='z' ||
263: c>='A' && c<='Z' ||
264: c>='0' && c<='9' ||
265: c=='_' ) ; /* VOID */
266: else goto nodef;
267: }
268:
269: /* define it */
270:
271: fprintf( cout , "%c define %s %d\n", rflag?' ':'#', trmset[i].name, trmset[i].value );
272:
273: nodef: ;
274: }
275:
276: ndefout = nterms+1;
277:
278: }
279:
280: chstash( c ){
281: /* put character away into cnames */
282: if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" );
283: else *cnamp++ = c;
284: }
285:
286: int gettok() {
287: int j, base;
288: static int peekline; /* number of '\n' seen in lookahead */
289: auto int c, match, reserve;
290:
291: begin:
292: reserve = 0;
293: if( peekc>=0 ) {
294: c = peekc;
295: lineno += peekline;
296: peekc = -1;
297: peekline = 0;
298: }
299: else c = fgetc( cin);
300: while( c==' ' || c=='\n' || c=='\t' || c == '\014'){
301: if( c == '\n' ) ++lineno;
302: c=fgetc( cin);
303: }
304: if (c=='/')
305: {if (fgetc( cin)!='*')error("illegal /");
306: c=fgetc( cin);
307: while(c != EOF) {
308: if( c == '\n' ) ++lineno;
309: if (c=='*')
310: {if((c=fgetc( cin))=='/')break;}
311: else c=fgetc( cin);}
312: if (!c) return(0);
313: goto begin;}
314: j=0;
315: switch(c){
316: case '"':
317: case '\'': match = c;
318: ctokn = cnamp;
319: chstash( ' ' );
320: while(1){
321: c = fgetc( cin);
322: if( c == '\n' || c == '\0' )
323: error("illegal or missing ' or \"");
324: if( c == '\\' ){
325: c = fgetc( cin);
326: chstash( '\\' );
327: }
328: else if( c == match ) break;
329: chstash( c );
330: }
331: break;
332: case '%':
333: case '\\': switch(c=fgetc( cin))
334: {case '0': return(TERM);
335: case '<': return(LEFT);
336: case '2': return(BINARY);
337: case '>': return(RIGHT);
338: case '%':
339: case '\\': return(MARK);
340: case '=': return(PREC);
341: case '{': return(LCURLY);
342: default: reserve = 1;
343: }
344: default: if( c >= '0' && c <= '9' ){ /* number */
345: numbval = c-'0' ;
346: base = (c=='0') ? 8 : 10 ;
347: for( c=fgetc( cin); c>='0' && c<='9'; c=fgetc( cin) ){
348: numbval = numbval*base + c - '0';
349: }
350: peekc = c;
351: return(NUMBER);
352: }
353: else if( (c>='a'&&c<='z')||(c>='A'&&c<='Z')||c=='_'||c=='.'||c=='$'){
354: ctokn = cnamp;
355: while( (c>='a'&&c<='z') ||
356: (c>='A'&&c<='Z') ||
357: (c>='0'&&c<='9') ||
358: c=='_' || c=='.' || c=='$' ) {
359: chstash( c );
360: if( peekc>=0 ) { c = peekc; peekc = -1; }
361: else c = fgetc( cin);
362: }
363: }
364: else return(c);
365:
366: peekc=c;
367: }
368: chstash( '\0' );
369:
370: if( reserve ){ /* find a reserved word */
371: if( compare("term")) return( TERM );
372: if( compare("TERM")) return( TERM );
373: if( compare("token")) return( TERM );
374: if( compare("TOKEN")) return( TERM );
375: if( compare("left")) return( LEFT );
376: if( compare("LEFT")) return( LEFT );
377: if( compare("nonassoc")) return( BINARY );
378: if( compare("NONASSOC")) return( BINARY );
379: if( compare("binary")) return( BINARY );
380: if( compare("BINARY")) return( BINARY );
381: if( compare("right")) return( RIGHT );
382: if( compare("RIGHT")) return( RIGHT );
383: if( compare("prec")) return( PREC );
384: if( compare("PREC")) return( PREC );
385: error("invalid escape, or illegal reserved word: %s", ctokn );
386: }
387:
388: /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */
389:
390: look:
391: while( peekc==' ' || peekc=='\t' || peekc == '\n' || peekc == '\014' )
392: {
393: if( peekc == '\n' ) ++peekline;
394: peekc = fgetc( cin);
395: }
396:
397: if( peekc != ':' ) return( IDENTIFIER );
398: peekc = -1;
399: lineno += peekline;
400: peekline = 0;
401: return( C_IDENTIFIER );
402: }
403: chfind(t)
404:
405: { int i,j;
406:
407: if (ctokn[0]==' ')t=0;
408: for(i=1;i<=nterms;i++)
409: if(compare(trmset[i].name)){
410: cnamp = ctokn;
411: return( i );
412: }
413: for(i=1;i<=nnonter;i++)
414: if(compare(nontrst[i].name)) {
415: cnamp = ctokn;
416: return( i+NTBASE );
417: }
418: /* cannot find name */
419: if( t>1 && ctokn[0] != ' ' )
420: error( "%s should have been defined earlier", ctokn );
421: return( defin( t ) );
422: }
423:
424: cpycode(){ /* copies code between \{ and \} */
425:
426: int c;
427: c = fgetc( cin);
428: if( c == '\n' ) {
429: c = fgetc( cin);
430: lineno++;
431: }
432: while( c != EOF ){
433: if( c=='\\' )
434: if( (c=fgetc( cin)) == '}' ) return;
435: else fputc('\\',cout);
436: if( c=='%' )
437: if( (c=fgetc( cin)) == '}' ) return;
438: else fputc('%',cout);
439: fputc( c, cout );
440: if( c == '\n' ) ++lineno;
441: c = fgetc( cin);
442: }
443: error("eof before %%}");
444: }
445:
446: cpyact(){ /* copy C action to the next ; or closing } */
447: int brac, c, match, *i, j, s;
448:
449: brac = 0;
450:
451: loop:
452: c = fgetc( cin);
453: swt:
454: switch( c ){
455:
456: case ';':
457: if( brac == 0 ){
458: fputc( c, cout );
459: return;
460: }
461: goto lcopy;
462:
463: case '{':
464: brac++;
465: goto lcopy;
466:
467: case '$':
468: s = 1;
469: c = fgetc( cin);
470: if( c == '$' ){
471: fprintf( cout , "yyval");
472: goto loop;
473: }
474: if( c == '-' ){
475: s = -s;
476: c = fgetc( cin);
477: }
478: if( c>='0' && c <= '9' ){
479: j=0;
480: while( c>='0' && c<= '9' ){
481: j= j*10+c-'0';
482: c = fgetc( cin);
483: }
484: if( rflag ) fprintf( cout , "yyvalv(yypv%c%d)", s==1?'+':'-', j );
485: else fprintf( cout , "yypv[%d]", s*j );
486: goto swt;
487: }
488: fputc( '$' , cout);
489: if( s<0 ) fputc('-', cout);
490: goto swt;
491:
492: case '}':
493: brac--;
494: if( brac == 0 ){
495: fputc( c , cout);
496: return;
497: }
498: goto lcopy;
499:
500: case '/': /* look for comments */
501: fputc( c ,cout);
502: c = fgetc( cin);
503: if( c != '*' ) goto swt;
504:
505: /* it really is a comment */
506:
507: fputc( c , cout);
508: while( (c=fgetc( cin)) != EOF ){
509: if( c=='*' ){
510: fputc( c , cout);
511: if( (c=fgetc( cin)) == '/' ) goto lcopy;
512: }
513: fputc( c , cout);
514: }
515: error( "EOF inside comment" );
516:
517: case '\'': /* character constant */
518: match = '\'';
519: goto string;
520:
521: case '"': /* character string */
522: match = '"';
523:
524: string:
525:
526: fputc( c , cout);
527: while( (c=fgetc( cin)) != EOF ){
528:
529: if( c=='\\' ){
530: fputc( c , cout);
531: c=fgetc( cin);
532: }
533: else if( c==match ) goto lcopy;
534: fputc( c , cout);
535: }
536: error( "EOF in string or character constant" );
537:
538: case '\0':
539: error("action does not terminate");
540: case '\n': ++lineno;
541: goto lcopy;
542:
543: }
544:
545: lcopy:
546: fputc( c , cout);
547: goto loop;
548: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.