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