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