|
|
1.1 root 1: /* @(#) cgram.y: 1.2 2/9/84 */
2: %{
3: static char SCCSID[] = "@(#) cgram.y: 2.1 83/08/02";
4: %}
5: %term NAME 2
6: %term STRING 3
7: %term ICON 4
8: %term FCON 5
9: %term PLUS 6
10: %term MINUS 8
11: %term MUL 11
12: %term AND 14
13: %term OR 17
14: %term ER 19
15: %term QUEST 21
16: %term COLON 22
17: %term ANDAND 23
18: %term OROR 24
19:
20: /* special interfaces for yacc alone */
21: /* These serve as abbreviations of 2 or more ops:
22: ASOP =, = ops
23: RELOP LE,LT,GE,GT
24: EQUOP EQ,NE
25: DIVOP DIV,MOD
26: SHIFTOP LS,RS
27: ICOP ICR,DECR
28: UNOP NOT,COMPL
29: STROP DOT,STREF
30:
31: */
32: %term ASOP 25
33: %term RELOP 26
34: %term EQUOP 27
35: %term DIVOP 28
36: %term SHIFTOP 29
37: %term INCOP 30
38: %term UNOP 31
39: %term STROP 32
40:
41: /* reserved words, etc */
42: %term TYPE 33
43: %term CLASS 34
44: %term STRUCT 35
45: %term RETURN 36
46: %term GOTO 37
47: %term IF 38
48: %term ELSE 39
49: %term SWITCH 40
50: %term BREAK 41
51: %term CONTINUE 42
52: %term WHILE 43
53: %term DO 44
54: %term FOR 45
55: %term DEFAULT 46
56: %term CASE 47
57: %term SIZEOF 48
58: %term ENUM 49
59:
60: /* little symbols, etc. */
61: /* namely,
62:
63: LP (
64: RP )
65:
66: LC {
67: RC }
68:
69: LB [
70: RB ]
71:
72: CM ,
73: SM ;
74:
75: */
76:
77: %term LP 50
78: %term RP 51
79: %term LC 52
80: %term RC 53
81: %term LB 54
82: %term RB 55
83: %term CM 56
84: %term SM 57
85: %term ASSIGN 58
86: %term ASM 59
87:
88: /* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts
89: /* these involved:
90: if/else
91: recognizing functions in various contexts, including declarations
92: error recovery
93: */
94:
95: %left CM
96: %right ASOP ASSIGN
97: %right QUEST COLON
98: %left OROR
99: %left ANDAND
100: %left OR
101: %left ER
102: %left AND
103: %left EQUOP
104: %left RELOP
105: %left SHIFTOP
106: %left PLUS MINUS
107: %left MUL DIVOP
108: %right UNOP
109: %right INCOP SIZEOF
110: %left LB LP STROP
111: %{
112: # include "mfile1.h"
113: %}
114:
115: /* define types */
116: %start ext_def_list
117:
118: %type <intval> con_e ifelprefix ifprefix doprefix switchpart
119: enum_head str_head name_lp
120: %type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl
121: cast_type null_decl funct_idn declarator fdeclarator
122: nfdeclarator elist
123:
124: %token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR
125: ER ANDAND OROR ASSIGN STROP INCOP UNOP ICON
126: %token <nodep> TYPE
127:
128: %%
129:
130: %{
131: extern int wloop_level; /* specifies while loop code generation */
132: extern int floop_level; /* specifies for loop code generation */
133: static int fake = 0;
134: static char fakename[NCHNAM+1];
135: %}
136:
137: ext_def_list: ext_def_list external_def
138: | /* EMPTY */
139: {
140: #ifndef LINT
141: beg_file();
142: #endif
143: ftnend();
144: }
145: ;
146: external_def: data_def
147: { curclass = SNULL; blevel = 0; }
148: | error
149: { curclass = SNULL; blevel = 0; }
150: | ASM SM
151: { asmout(); curclass = SNULL; blevel = 0; }
152: ;
153: data_def: oattributes SM
154: { $1->in.op = FREE; }
155: | oattributes init_dcl_list SM
156: { $1->in.op = FREE; }
157: | oattributes fdeclarator
158: { defid( tymerge($1,$2),
159: curclass==STATIC?STATIC:EXTDEF ); }
160: function_body
161: {
162: if( blevel ) cerror( "function level error" );
163: if( reached ) retstat |= NRETVAL;
164: $1->in.op = FREE;
165: ftnend();
166: }
167: ;
168:
169: function_body: arg_dcl_list compoundstmt
170: { regvar = 0; } /* clear out arguments */
171: ;
172:
173: arg_dcl_list: arg_dcl_list attributes declarator_list SM
174: { curclass = SNULL; $2->in.op = FREE; }
175: | arg_dcl_list attributes SM
176: /* to permit structs in decl. lists */
177: { curclass = SNULL; $2->in.op = FREE; }
178: | /* EMPTY */ { blevel = 1; }
179: ;
180:
181: stmt_list: stmt_list statement
182: | /* EMPTY */
183: { bccode();
184: locctr(PROG);
185: }
186: ;
187:
188: dcl_stat_list : dcl_stat_list attributes SM
189: { $2->in.op = FREE; }
190: | dcl_stat_list attributes init_dcl_list SM
191: { $2->in.op = FREE; }
192: | /* EMPTY */
193: ;
194:
195: oattributes: attributes
196: | /* empty */
197: { $$ = mkty(INT,0,INT); curclass = SNULL; }
198: ;
199: attributes: class type
200: { $$ = $2; }
201: | type class
202: | class
203: { $$ = mkty(INT,0,INT); }
204: | type
205: { curclass = SNULL ; }
206: | type class type
207: { $1->in.type = types( $1->in.type, $3->in.type,
208: UNDEF );
209: $3->in.op = FREE;
210: }
211: ;
212:
213: class: CLASS
214: { curclass = $1; }
215: ;
216:
217: type: TYPE
218: | TYPE TYPE
219: { $1->in.type = types( $1->in.type, $2->in.type, UNDEF );
220: $2->in.op = FREE;
221: }
222: | TYPE TYPE TYPE
223: { $1->in.type = types( $1->in.type, $2->in.type, $3->in.type );
224: $2->in.op = $3->in.op = FREE;
225: }
226: | struct_dcl
227: | enum_dcl
228: ;
229:
230: enum_dcl: enum_head LC moe_list optcomma RC
231: { $$ = dclstruct($1); }
232: | ENUM NAME
233: { $$ = rstruct($2,0); stwart = instruct; }
234: ;
235:
236: enum_head: ENUM
237: { $$ = bstruct(-1,0); stwart = SEENAME; }
238: | ENUM NAME
239: { $$ = bstruct($2,0); stwart = SEENAME; }
240: ;
241:
242: moe_list: moe
243: | moe_list CM moe
244: ;
245:
246: moe: NAME
247: { moedef( $1 ); }
248: | NAME ASSIGN con_e
249: { strucoff = $3; moedef( $1 ); }
250: ;
251:
252: struct_dcl: str_head LC type_dcl_list optsemi RC
253: { $$ = dclstruct($1); }
254: | STRUCT NAME
255: { $$ = rstruct($2,$1); }
256: ;
257:
258: str_head: STRUCT
259: { $$ = bstruct(-1,$1); stwart=0; }
260: | STRUCT NAME
261: { $$ = bstruct($2,$1); stwart=0; }
262: ;
263:
264: type_dcl_list: type_declaration
265: | type_dcl_list SM type_declaration
266: ;
267:
268: type_declaration: type declarator_list
269: { curclass = SNULL; stwart=0; $1->in.op = FREE; }
270: | type
271: { if( curclass != MOU ){
272: curclass = SNULL;
273: }
274: else {
275: sprintf( fakename, "$%dFAKE", fake++ );
276: defid( tymerge($1, bdty(NAME,NIL,
277: lookup( fakename, SMOS ))), curclass );
278: werror("union member must be named");
279: }
280: stwart = 0;
281: $1->in.op = FREE;
282: }
283: ;
284:
285:
286: declarator_list: declarator
287: { defid( tymerge($<nodep>0,$1), curclass);
288: stwart = instruct; }
289: | declarator_list CM {$<nodep>$=$<nodep>0;} declarator
290: { defid( tymerge($<nodep>0,$4), curclass);
291: stwart = instruct; }
292: ;
293: declarator: nfdeclarator
294: | nfdeclarator COLON con_e
295: %prec CM
296: { if( !(instruct&INSTRUCT) )
297: uerror( "field outside of structure" );
298: if( $3<0 || $3 >= FIELD ){
299: uerror( "illegal field size" );
300: $3 = 1;
301: }
302: defid( tymerge($<nodep>0,$1), FIELD|$3 );
303: $$ = NIL;
304: }
305: | COLON con_e
306: %prec CM
307: { if( !(instruct&INSTRUCT) )
308: uerror( "field outside of structure" );
309: /* alignment or hole */
310: falloc( stab, $2, -1, $<nodep>0 );
311: $$ = NIL;
312: }
313: | error
314: { $$ = NIL; }
315: ;
316:
317: /* int (a)(); is not a function --- sorry! */
318: nfdeclarator: MUL nfdeclarator
319: { umul:
320: $$ = bdty( UNARY MUL, $2, 0 ); }
321: | nfdeclarator LP RP
322: { uftn:
323: $$ = bdty( UNARY CALL, $1, 0 ); }
324: | nfdeclarator LB RB
325: { uary:
326: $$ = bdty( LB, $1, 0 ); }
327: | nfdeclarator LB con_e RB
328: { bary:
329: if( (int)$3 <= 0 )
330: werror( "zero or negative subscript" );
331: $$ = bdty( LB, $1, $3 ); }
332: | NAME
333: { $$ = bdty( NAME, NIL, $1 ); }
334: | LP nfdeclarator RP
335: { $$=$2; }
336: ;
337: fdeclarator: MUL fdeclarator
338: { goto umul; }
339: | fdeclarator LP RP
340: { goto uftn; }
341: | fdeclarator LB RB
342: { goto uary; }
343: | fdeclarator LB con_e RB
344: { goto bary; }
345: | LP fdeclarator RP
346: { $$ = $2; }
347: | name_lp
348: { if (paramno)
349: uerror("arg list in declaration"); }
350: name_list RP
351: {
352: if( blevel!=0 )
353: uerror(
354: "function declaration in bad context");
355: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 );
356: stwart = 0;
357: }
358: | name_lp
359: { if (paramno)
360: uerror("arg list in declaration"); }
361: RP
362: {
363: $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 );
364: stwart = 0;
365: }
366: ;
367:
368: name_lp: NAME LP
369: {
370: /* turn off typedefs for argument names */
371: stwart = SEENAME;
372: if( stab[$1].sclass == SNULL )
373: stab[$1].stype = FTN;
374: }
375: ;
376:
377: name_list: NAME
378: { ftnarg( $1 ); stwart = SEENAME; }
379: | name_list CM NAME
380: { ftnarg( $3 ); stwart = SEENAME; }
381: | error
382: ;
383: /* always preceeded by attributes: thus the $<nodep>0's */
384: init_dcl_list: init_declarator
385: %prec CM
386: | init_dcl_list CM {$<nodep>$=$<nodep>0;} init_declarator
387: ;
388: /* always preceeded by attributes */
389: xnfdeclarator: nfdeclarator
390: { defid( $1 = tymerge($<nodep>0,$1), curclass);
391: beginit($1->tn.rval);
392: }
393: | error
394: ;
395: /* always preceeded by attributes */
396: init_declarator: nfdeclarator
397: { nidcl( tymerge($<nodep>0,$1) ); }
398: | fdeclarator
399: { defid( tymerge($<nodep>0,$1), uclass(curclass) );
400: }
401: | xnfdeclarator ASSIGN e
402: %prec CM
403: { doinit( $3 );
404: endinit(); }
405: | xnfdeclarator ASSIGN LC init_list optcomma RC
406: { endinit(); }
407: | error
408: ;
409:
410: init_list: initializer
411: %prec CM
412: | init_list CM initializer
413: ;
414: initializer: e
415: %prec CM
416: { doinit( $1 ); }
417: | ibrace init_list optcomma RC
418: { irbrace(); }
419: ;
420:
421: optcomma : /* empty */
422: | CM
423: ;
424:
425: optsemi : /* empty */
426: | SM
427: ;
428:
429: ibrace : LC
430: { ilbrace(); }
431: ;
432:
433: /* STATEMENTS */
434:
435: compoundstmt: begin dcl_stat_list stmt_list RC
436: {
437: clearst(blevel);
438: if (--blevel == 1)
439: {
440: clearst(blevel);
441: blevel = 0;
442: }
443: checkst(blevel);
444: autooff = *--psavbc;
445: regvar = *--psavbc;
446: }
447: ;
448:
449: begin: LC
450: { if( blevel == 1 ) dclargs();
451: uplevel();
452: if( psavbc > &asavbc[BCSZ-2] )
453: cerror( "nesting too deep" );
454: *psavbc++ = regvar;
455: *psavbc++ = autooff;
456: }
457: ;
458:
459: statement: e SM
460: { ecomp($1); }
461: | ASM SM
462: { asmout(); }
463: | compoundstmt
464: | ifprefix statement
465: { deflab($1);
466: reached = 1;
467: #ifdef M32B
468: brdepth--;
469: #endif
470: }
471: | ifelprefix statement
472: { if( $1 != NOLAB ){
473: deflab( $1 );
474: reached = 1;
475: }
476: #ifdef M32B
477: brdepth--;
478: #endif
479: }
480: | WHILE
481: {
482: #ifdef M32B
483: whdepth++;
484: #endif
485: }
486: LP e RP
487: {
488: savebc();
489: if (!reached)
490: werror("loop not entered at top");
491: reached = 1;
492: brklab = getlab();
493: contlab = getlab();
494: switch (wloop_level) {
495: default:
496: cerror("bad while loop code gen value");
497: /*NOTREACHED*/
498: case LL_TOP: /* test at loop top */
499: deflab(contlab);
500: if ($4->in.op == ICON && $4->tn.lval) {
501: flostat = FLOOP;
502: tfree($4);
503: } else {
504: $4->ln.lineno = $<lineno>1;
505: ecomp(buildtree(CBRANCH, $4,
506: bcon(brklab)));
507: }
508: break;
509: case LL_BOT: /* test at loop bottom */
510: if ($4->in.op == ICON && $4->tn.lval) {
511: flostat = FLOOP;
512: tfree($4);
513: deflab(contlab);
514: } else {
515: branch(contlab);
516: deflab($<intval>$ = getlab());
517: }
518: break;
519: case LL_DUP: /* dup. test at top & bottom */
520: if ($4->in.op == ICON && $4->tn.lval) {
521: flostat = FLOOP;
522: tfree($4);
523: deflab($<intval>$ = contlab);
524: } else {
525: register NODE *sav;
526: extern NODE *treecpy();
527: sav = treecpy($4);
528: ecomp(buildtree(CBRANCH,$4,
529: bcon(brklab)));
530: $4 = sav;
531: deflab($<intval>$ = getlab());
532: }
533: break;
534: }
535: }
536: statement
537: {
538: switch (wloop_level) {
539: default:
540: cerror("bad while loop code gen. value");
541: /*NOTREACHED*/
542: case LL_TOP: /* test at loop top */
543: branch(contlab);
544: break;
545: case LL_BOT: /* test at loop bottom */
546: if (flostat & FLOOP)
547: branch(contlab);
548: else {
549: reached = 1;
550: deflab(contlab);
551: ecomp(buildtree(CBRANCH,
552: buildtree(NOT, $4, NIL),
553: bcon($<intval>6)));
554: }
555: break;
556: case LL_DUP: /* dup. test at top & bottom */
557: if (flostat & FLOOP)
558: branch(contlab);
559: else {
560: if (flostat & FCONT) {
561: reached = 1;
562: deflab(contlab);
563: }
564: ecomp(buildtree(CBRANCH,
565: buildtree(NOT, $4, NIL),
566: bcon($<intval>6)));
567: }
568: break;
569: }
570: if ((flostat & FBRK) || !(flostat & FLOOP))
571: reached = 1;
572: else
573: reached = 0;
574: deflab(brklab);
575: resetbc(0);
576: #ifdef M32B
577: whdepth--;
578: #endif
579: }
580: | doprefix statement WHILE LP e RP SM
581: { deflab( contlab );
582: if( flostat & FCONT ) reached = 1;
583: $5->ln.lineno = $<lineno>3;
584: ecomp( buildtree(CBRANCH,
585: buildtree(NOT, $5, NIL), bcon($1)));
586: deflab( brklab );
587: reached = 1;
588: resetbc(0);
589: #ifdef M32B
590: whdepth--;
591: #endif
592: }
593: | FOR LP .e SM
594: {
595: #ifdef M32B
596: fordepth++;
597: #endif
598: }
599: .e SM
600: {
601: if ($3) {
602: $3->ln.lineno = $<lineno>1;
603: ecomp($3);
604: } else if (!reached)
605: werror("loop not entered at top");
606: savebc();
607: contlab = getlab();
608: brklab = getlab();
609: reached = 1;
610: switch (floop_level) {
611: default:
612: cerror("bad for loop code gen. value");
613: /*NOTREACHED*/
614: case LL_TOP: /* test at loop top */
615: deflab($<intval>$ = getlab());
616: if (!$6)
617: flostat |= FLOOP;
618: else if ($6->in.op == ICON && $6->tn.lval) {
619: flostat |= FLOOP;
620: tfree($6);
621: $6 = (NODE *)0;
622: } else {
623: if (!$3)
624: $6->ln.lineno = $<lineno>1;
625: ecomp(buildtree(CBRANCH, $6,
626: bcon(brklab)));
627: }
628: break;
629: case LL_BOT: /* test at loop bottom */
630: if (!$6)
631: flostat |= FLOOP;
632: else if ($6->in.op == ICON && $6->tn.lval) {
633: flostat |= FLOOP;
634: tfree($6);
635: $6 = (NODE *)0;
636: } else
637: branch($<intval>1 = getlab());
638: deflab($<intval>$ = getlab());
639: break;
640: case LL_DUP: /* dup. test at top & bottom */
641: if (!$6)
642: flostat |= FLOOP;
643: else if ($6->in.op == ICON && $6->tn.lval) {
644: flostat |= FLOOP;
645: tfree($6);
646: $6 = (NODE *)0;
647: } else {
648: register NODE *sav;
649: extern NODE *treecpy();
650: sav = treecpy($6);
651: ecomp(buildtree(CBRANCH, $6,
652: bcon(brklab)));
653: $6 = sav;
654: }
655: deflab($<intval>$ = getlab());
656: break;
657: }
658: }
659: .e RP statement
660: {
661: if (flostat & FCONT) {
662: deflab(contlab);
663: reached = 1;
664: }
665: if ($9)
666: $9->ln.lineno = lineno, ecomp($9);
667: switch (floop_level) {
668: default:
669: cerror("bad for loop code gen. value");
670: /*NOTREACHED*/
671: case LL_TOP: /* test at loop top */
672: branch($<intval>8);
673: break;
674: case LL_BOT: /* test at loop bottom */
675: if ($6)
676: deflab($<intval>1);
677: /*FALLTHROUGH*/
678: case LL_DUP: /* dup. test at top & bottom */
679: if ($6) {
680: ecomp(buildtree(CBRANCH,
681: buildtree(NOT, $6, NIL),
682: bcon($<intval>8)));
683: } else
684: branch($<intval>8);
685: break;
686: }
687: deflab(brklab);
688: if ((flostat & FBRK) || !(flostat & FLOOP))
689: reached = 1;
690: else
691: reached = 0;
692: resetbc(0);
693: #ifdef M32B
694: fordepth--;
695: #endif
696: }
697: | switchpart statement
698: { if( reached ) branch( brklab );
699: deflab( $1 );
700: swend();
701: deflab(brklab);
702: if( (flostat&FBRK) || !(flostat&FDEF) ) reached=1;
703: resetbc(FCONT);
704: #ifdef M32B
705: brdepth--;
706: #endif
707: }
708: | BREAK SM
709: { if( brklab == NOLAB ) uerror( "illegal break");
710: else if(reached) {
711: slineno = $<lineno>1; dbline();
712: branch( brklab );
713: }
714: flostat |= FBRK;
715: if( brkflag ) goto rch;
716: reached = 0;
717: }
718: | CONTINUE SM
719: { if( contlab == NOLAB ) uerror( "illegal continue");
720: else {
721: slineno = $<lineno>1; dbline();
722: branch( contlab );
723: }
724: flostat |= FCONT;
725: goto rch;
726: }
727: | RETURN SM
728: { retstat |= NRETVAL;
729: slineno = $<lineno>1; dbline();
730: branch( retlab );
731: rch:
732: if( !reached ) werror( "statement not reached");
733: reached = 0;
734: }
735: | RETURN e SM
736: { register NODE *temp;
737: TWORD indtype();
738: idname = curftn;
739: temp = buildtree( NAME, NIL, NIL );
740: temp->in.type = DECREF(temp->in.type);
741: if(temp->in.type == (FTN|VOID))
742: uerror(
743: "void function %s cannot return value",
744: stab[idname].sname);
745: temp->tn.op = RNODE;
746: $2 = makety( $2, temp->fn.type,
747: temp->fn.cdim, temp->fn.csiz );
748: temp->in.type = indtype( temp->in.type );
749: temp = buildtree( ASSIGN, temp, $2 );
750: temp->ln.lineno = $<lineno>1;
751: ecomp( temp );
752: retstat |= RETVAL;
753: branch( retlab );
754: reached = 0;
755: }
756: | GOTO NAME SM
757: { register NODE *q;
758: q = block( FREE, NIL, NIL, INT|ARY, 0, INT );
759: q->tn.rval = idname = $2;
760: defid( q, ULABEL );
761: stab[idname].suse = -lineno;
762: slineno = $<lineno>1; dbline();
763: branch( stab[idname].offset );
764: goto rch;
765: }
766: | SM
767: | error SM
768: | error RC
769: | label statement
770: ;
771: label: NAME COLON
772: { register NODE *q;
773: q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL );
774: q->tn.rval = $1;
775: defid( q, LABEL );
776: reached = 1;
777: }
778: | CASE e COLON
779: { addcase($2);
780: reached = 1;
781: }
782: | DEFAULT COLON
783: { reached = 1;
784: adddef();
785: flostat |= FDEF;
786: }
787: ;
788: doprefix: DO
789: { savebc();
790: if( !reached ) werror( "loop not entered at top");
791: brklab = getlab();
792: contlab = getlab();
793: deflab( $$ = getlab() );
794: reached = 1;
795: #ifdef M32B
796: whdepth++;
797: #endif
798: }
799: ;
800: ifprefix: IF LP e RP
801: { $3->ln.lineno = $<lineno>1;
802: ecomp(buildtree(CBRANCH, $3, bcon($$=getlab()))) ;
803: reached = 1;
804: #ifdef M32B
805: brdepth++;
806: #endif
807: }
808: ;
809: ifelprefix: ifprefix statement ELSE
810: { if( reached ) branch( $$ = getlab() );
811: else $$ = NOLAB;
812: deflab( $1 );
813: reached = 1;
814: }
815: ;
816:
817: switchpart: SWITCH LP e RP
818: { register NODE *temp;
819: savebc();
820: temp = block( SNODE, NIL, NIL, INT, 0, INT );
821: temp = buildtree( ASSIGN, temp, $3 );
822: #ifdef M32B
823: temp = setswreg( temp );
824: #endif
825: brklab = getlab();
826: temp->ln.lineno = $<lineno>1;
827: ecomp( temp );
828: branch( $$ = getlab() );
829: swstart();
830: reached = 0;
831: #ifdef M32B
832: brdepth++;
833: #endif
834: }
835: ;
836: /* EXPRESSIONS */
837: con_e: { $<intval>$=instruct; stwart=instruct=0; } e
838: %prec CM
839: { $$ = icons( $2 ); instruct=$<intval>1; }
840: ;
841: .e: e
842: |
843: { $$ = 0; }
844: ;
845: elist: e
846: %prec CM
847: | elist CM e
848: { goto bop; }
849: ;
850:
851: e: e RELOP e
852: {
853: preconf:
854: if( yychar==RELOP || yychar==EQUOP || yychar==AND
855: || yychar==OR || yychar==ER ){
856: precplaint:
857: if( hflag ) werror(
858: "precedence confusion possible: parenthesize!"
859: );
860: }
861: bop:
862: $$ = buildtree( $2, $1, $3 );
863: }
864: | e CM e
865: { $2 = COMOP;
866: goto bop;
867: }
868: | e DIVOP e
869: { goto bop; }
870: | e PLUS e
871: { if(yychar==SHIFTOP) goto precplaint; else goto bop; }
872: | e MINUS e
873: { if(yychar==SHIFTOP ) goto precplaint; else goto bop; }
874: | e SHIFTOP e
875: { if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; }
876: | e MUL e
877: { goto bop; }
878: | e EQUOP e
879: { goto preconf; }
880: | e AND e
881: { if( yychar==RELOP||yychar==EQUOP ) goto preconf; else goto bop; }
882: | e OR e
883: { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; }
884: | e ER e
885: { if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; }
886: | e ANDAND e
887: { goto bop; }
888: | e OROR e
889: { goto bop; }
890: | e MUL ASSIGN e
891: { abop:
892: $$ = buildtree( ASG $2, $1, $4 );
893: }
894: | e DIVOP ASSIGN e
895: { goto abop; }
896: | e PLUS ASSIGN e
897: { goto abop; }
898: | e MINUS ASSIGN e
899: { goto abop; }
900: | e SHIFTOP ASSIGN e
901: { goto abop; }
902: | e AND ASSIGN e
903: { goto abop; }
904: | e OR ASSIGN e
905: { goto abop; }
906: | e ER ASSIGN e
907: { goto abop; }
908: | e QUEST e COLON e
909: { $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) );
910: }
911: | e ASOP e
912: { werror( "old-fashioned assignment operator" );
913: goto bop; }
914: | e ASSIGN e
915: { goto bop; }
916: | term
917: ;
918:
919: term: term INCOP
920: { $$ = buildtree( $2, $1, bcon(1) ); }
921: | MUL term
922: { ubop:
923: $$ = buildtree( UNARY $1, $2, NIL );
924: }
925: | AND term
926: {
927: #ifdef M32B
928: myand($2);
929: #endif
930: if( ISFTN($2->in.type) || ISARY($2->in.type) ){
931: werror( "& before array or function: ignored" );
932: $$ = $2;
933: }
934: else goto ubop;
935: }
936: | MINUS term
937: { goto ubop; }
938: | UNOP term
939: {
940: $$ = buildtree( $1, $2, NIL );
941: }
942: | INCOP term
943: { $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS,
944: $2,
945: bcon(1) );
946: }
947: | SIZEOF term
948: { $$ = doszof( $2 ); }
949: | LP cast_type RP term %prec INCOP
950: { $$ = buildtree( CAST, $2, $4 );
951: $$->in.left->in.op = FREE;
952: $$->in.op = FREE;
953: $$ = $$->in.right;
954: }
955: | SIZEOF LP cast_type RP %prec SIZEOF
956: { $$ = doszof( $3 ); }
957: | term LB e RB
958: { $$ = buildtree( LB, $1, $3 ); }
959: | term LB e COLON e RB
960: { $$ = xicolon( $1, $3, $5 ); }
961: | funct_idn RP
962: { $$=buildtree(UNARY CALL,$1,NIL);
963: }
964: | funct_idn elist RP
965: { $$=buildtree(CALL,$1,$2); }
966: | term STROP NAME
967: { if( $2 == DOT ){
968: if( notlval( $1 ) )werror(
969: "structure reference must be addressable"
970: );
971: $1 = buildtree( UNARY AND, $1, NIL );
972: }
973: idname = $3;
974: $$ = buildtree( STREF, $1,
975: buildtree( NAME, NIL, NIL ) );
976: }
977: | NAME
978: { idname = $1;
979: /* recognize identifiers in initializations */
980: if( blevel==0 && stab[idname].stype == UNDEF ) {
981: register NODE *q;
982: werror( "undeclared initializer name %s",
983: stab[idname].sname );
984: q = block( FREE, NIL, NIL, INT, 0, INT );
985: q->tn.rval = idname;
986: defid( q, EXTERN );
987: }
988: $$=buildtree(NAME,NIL,NIL);
989: stab[$1].suse = -lineno;
990: }
991: | ICON
992: { $$=bcon(0);
993: $$->tn.lval = lastcon;
994: $$->tn.rval = NONAME;
995: if( $1 ) $$->fn.csiz = $$->in.type = ctype(LONG);
996: }
997: | FCON
998: { $$=buildtree(FCON,NIL,NIL);
999: $$->fpn.dval = dcon;
1000: }
1001: | STRING
1002: { $$ = getstr(); }
1003: | LP e RP
1004: { $$=$2; }
1005: ;
1006:
1007: cast_type: type null_decl
1008: {
1009: $$ = tymerge( $1, $2 );
1010: $$->in.op = NAME;
1011: $1->in.op = FREE;
1012: }
1013: ;
1014:
1015: null_decl: /* EMPTY */
1016: { $$ = bdty( NAME, NIL, -1 ); }
1017: | LP RP
1018: { $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); }
1019: | LP null_decl RP LP RP
1020: { $$ = bdty( UNARY CALL, $2, 0 ); }
1021: | MUL null_decl
1022: { goto umul; }
1023: | null_decl LB RB
1024: { goto uary; }
1025: | null_decl LB con_e RB
1026: { goto bary; }
1027: | LP null_decl RP
1028: { $$ = $2; }
1029: ;
1030:
1031: funct_idn: NAME LP
1032: { if( stab[$1].stype == UNDEF ){
1033: register NODE *q;
1034: q = block( FREE, NIL, NIL, FTN|INT, 0, INT );
1035: q->tn.rval = $1;
1036: defid( q, EXTERN );
1037: }
1038: idname = $1;
1039: $$=buildtree(NAME,NIL,NIL);
1040: stab[idname].suse = -lineno;
1041: }
1042: | term LP
1043: ;
1044: %%
1045:
1046: NODE *
1047: mkty( t, d, s ) unsigned t; {
1048: return( block( TYPE, NIL, NIL, t, d, s ) );
1049: }
1050:
1051: NODE *
1052: bdty( op, p, v ) NODE *p; {
1053: register NODE *q;
1054:
1055: q = block( op, p, NIL, INT, 0, INT );
1056:
1057: switch( op ){
1058:
1059: case UNARY MUL:
1060: case UNARY CALL:
1061: break;
1062:
1063: case LB:
1064: q->in.right = bcon(v);
1065: break;
1066:
1067: case NAME:
1068: q->tn.rval = v;
1069: break;
1070:
1071: default:
1072: cerror( "bad bdty" );
1073: }
1074:
1075: return( q );
1076: }
1077: int dimtabsz;
1078: allodimtab()
1079: {
1080: if(!dimtabsz)
1081: dimtab = (int *) malloc((dimtabsz = DIMTABSZ)*sizeof(int));
1082: else {
1083: dimtabsz *= 3;
1084: dimtab = (int *) realloc((char *)dimtab, dimtabsz*sizeof(int));
1085: }
1086: if(!dimtab)
1087: cerror("dimension table overflow");
1088: }
1089:
1090: dstash( n ){ /* put n into the dimension table */
1091: if( curdim >= dimtabsz-1 ){
1092: allodimtab();
1093: }
1094: dimtab[ curdim++ ] = n;
1095: }
1096:
1097: savebc() {
1098: if( psavbc > & asavbc[BCSZ-4 ] ){
1099: cerror( "whiles, fors, etc. too deeply nested");
1100: }
1101: *psavbc++ = brklab;
1102: *psavbc++ = contlab;
1103: *psavbc++ = flostat;
1104: *psavbc++ = swx;
1105: #ifdef M32B
1106: *psavbc++ = swregno;
1107: #endif
1108: flostat = 0;
1109: }
1110:
1111: resetbc(mask){
1112:
1113: #ifdef M32B
1114: swregno = *--psavbc;
1115: #endif
1116: swx = *--psavbc;
1117: flostat = *--psavbc | (flostat&mask);
1118: contlab = *--psavbc;
1119: brklab = *--psavbc;
1120:
1121: }
1122:
1123: addcase(p) NODE *p; { /* add case to switch */
1124:
1125: p = optim( p ); /* change enum to ints */
1126: if( p->in.op != ICON || p->tn.rval != NONAME){
1127: uerror( "non-constant case expression");
1128: return;
1129: }
1130: if( swp == swtab ){
1131: uerror( "case not in switch");
1132: return;
1133: }
1134: if( swp >= &swtab[SWITSZ] ){
1135: cerror( "switch table overflow");
1136: }
1137: swp->sval = p->tn.lval;
1138: deflab( swp->slab = getlab() );
1139: ++swp;
1140: tfree(p);
1141: }
1142:
1143: adddef(){ /* add default case to switch */
1144: if( swtab[swx].slab >= 0 ){
1145: uerror( "duplicate default in switch");
1146: return;
1147: }
1148: if( swp == swtab ){
1149: uerror( "default not inside switch");
1150: return;
1151: }
1152: deflab( swtab[swx].slab = getlab() );
1153: }
1154:
1155: swstart(){
1156: /* begin a switch block */
1157: if( swp >= &swtab[SWITSZ] ){
1158: cerror( "switch table overflow");
1159: }
1160: swx = swp - swtab;
1161: swp->slab = -1;
1162: ++swp;
1163: }
1164:
1165: swend(){ /* end a switch block */
1166:
1167: register struct sw *swbeg, *p, *q, *r, *r1;
1168: CONSZ temp;
1169: int tempi;
1170:
1171: swbeg = &swtab[swx+1];
1172:
1173: /* sort */
1174:
1175: r1 = swbeg;
1176: r = swp-1;
1177:
1178: while( swbeg < r ){
1179: /* bubble largest to end */
1180: for( q=swbeg; q<r; ++q ){
1181: if( q->sval > (q+1)->sval ){
1182: /* swap */
1183: r1 = q+1;
1184: temp = q->sval;
1185: q->sval = r1->sval;
1186: r1->sval = temp;
1187: tempi = q->slab;
1188: q->slab = r1->slab;
1189: r1->slab = tempi;
1190: }
1191: }
1192: r = r1;
1193: r1 = swbeg;
1194: }
1195:
1196: /* it is now sorted */
1197:
1198: for( p = swbeg+1; p<swp; ++p ){
1199: if( p->sval == (p-1)->sval ){
1200: uerror( "duplicate case in switch, %d", tempi=p->sval );
1201: return;
1202: }
1203: }
1204:
1205: reached = 1;
1206: genswitch( swbeg-1, (int)(swp-swbeg) );
1207: swp = swbeg-1;
1208: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.