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